You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ro...@apache.org on 2018/12/04 11:09:53 UTC

[cloudstack] branch master updated (496a639 -> 52f68a2)

This is an automated email from the ASF dual-hosted git repository.

rohit pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git.


    from 496a639  Merge remote-tracking branch 'origin/4.11'
     add 1709792  packaging: correct permissions in spec file and fix class path specified variable (#3030)
     add 89c567a  security: increase keystore setup/import timeout (#3076)
     add 290df5f  api: Discover tags field on superclass of API responses (#3005)
     new 52f68a2  Merge remote-tracking branch 'origin/4.11'

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 agent/src/main/java/com/cloud/agent/Agent.java     |  4 +-
 .../virtualnetwork/VirtualRoutingResource.java     |  4 +-
 packaging/centos7/cloud.spec                       |  2 +-
 packaging/systemd/cloudstack-management.service    |  4 +-
 .../api/response/ApiDiscoveryResponse.java         | 12 ++--
 .../api/response/ApiResponseResponse.java          | 24 ++++++--
 .../discovery/ApiDiscoveryServiceImpl.java         | 42 +++++++-------
 .../cloudstack/discovery/ApiDiscoveryTest.java     | 66 ++++++++++++++--------
 8 files changed, 97 insertions(+), 61 deletions(-)


[cloudstack] 01/01: Merge remote-tracking branch 'origin/4.11'

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 52f68a273aaf0aa6746eaaee4a95a7bf722c53b0
Merge: 496a639 290df5f
Author: Rohit Yadav <ro...@shapeblue.com>
AuthorDate: Tue Dec 4 16:39:21 2018 +0530

    Merge remote-tracking branch 'origin/4.11'
    
    Signed-off-by: Rohit Yadav <ro...@shapeblue.com>

 agent/src/main/java/com/cloud/agent/Agent.java     |  4 +-
 .../virtualnetwork/VirtualRoutingResource.java     |  4 +-
 packaging/centos7/cloud.spec                       |  2 +-
 packaging/systemd/cloudstack-management.service    |  4 +-
 .../api/response/ApiDiscoveryResponse.java         | 12 ++--
 .../api/response/ApiResponseResponse.java          | 24 ++++++--
 .../discovery/ApiDiscoveryServiceImpl.java         | 42 +++++++-------
 .../cloudstack/discovery/ApiDiscoveryTest.java     | 66 ++++++++++++++--------
 8 files changed, 97 insertions(+), 61 deletions(-)

diff --cc core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
index 112d920,0000000..21372a1
mode 100644,000000..100644
--- a/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
+++ b/core/src/main/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
@@@ -1,473 -1,0 +1,473 @@@
 +//
 +// Licensed to the Apache Software Foundation (ASF) under one
 +// or more contributor license agreements.  See the NOTICE file
 +// distributed with this work for additional information
 +// regarding copyright ownership.  The ASF licenses this file
 +// to you under the Apache License, Version 2.0 (the
 +// "License"); you may not use this file except in compliance
 +// with the License.  You may obtain a copy of the License at
 +//
 +//   http://www.apache.org/licenses/LICENSE-2.0
 +//
 +// Unless required by applicable law or agreed to in writing,
 +// software distributed under the License is distributed on an
 +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 +// KIND, either express or implied.  See the License for the
 +// specific language governing permissions and limitations
 +// under the License.
 +//
 +
 +package com.cloud.agent.resource.virtualnetwork;
 +
 +import java.io.IOException;
 +import java.net.InetSocketAddress;
 +import java.nio.channels.SocketChannel;
 +
 +import org.apache.cloudstack.diagnostics.DiagnosticsAnswer;
 +import org.apache.cloudstack.diagnostics.DiagnosticsCommand;
 +import org.joda.time.Duration;
 +import java.util.ArrayList;
 +import java.util.HashMap;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Queue;
 +import java.util.UUID;
 +import java.util.concurrent.LinkedBlockingQueue;
 +import java.util.concurrent.locks.Lock;
 +import java.util.concurrent.locks.ReentrantLock;
 +
 +import javax.naming.ConfigurationException;
 +
 +import org.apache.cloudstack.ca.SetupCertificateAnswer;
 +import org.apache.cloudstack.ca.SetupCertificateCommand;
 +import org.apache.cloudstack.ca.SetupKeyStoreCommand;
 +import org.apache.cloudstack.ca.SetupKeystoreAnswer;
 +import org.apache.cloudstack.utils.security.KeyStoreUtils;
 +import org.apache.log4j.Logger;
 +
 +import com.cloud.agent.api.Answer;
 +import com.cloud.agent.api.CheckRouterAnswer;
 +import com.cloud.agent.api.CheckRouterCommand;
 +import com.cloud.agent.api.CheckS2SVpnConnectionsAnswer;
 +import com.cloud.agent.api.CheckS2SVpnConnectionsCommand;
 +import com.cloud.agent.api.GetDomRVersionAnswer;
 +import com.cloud.agent.api.GetDomRVersionCmd;
 +import com.cloud.agent.api.GetRouterAlertsAnswer;
 +import com.cloud.agent.api.routing.AggregationControlCommand;
 +import com.cloud.agent.api.routing.AggregationControlCommand.Action;
 +import com.cloud.agent.api.routing.GetRouterAlertsCommand;
 +import com.cloud.agent.api.routing.GroupAnswer;
 +import com.cloud.agent.api.routing.NetworkElementCommand;
 +import com.cloud.agent.resource.virtualnetwork.facade.AbstractConfigItemFacade;
 +import com.cloud.utils.ExecutionResult;
 +import com.cloud.utils.NumbersUtil;
 +import com.cloud.utils.exception.CloudRuntimeException;
 +
 +/**
 + * VirtualNetworkResource controls and configures virtual networking
 + *
 + * @config
 + * {@table
 + *    || Param Name | Description | Values | Default ||
 + *  }
 + **/
 +public class VirtualRoutingResource {
 +
 +    private static final Logger s_logger = Logger.getLogger(VirtualRoutingResource.class);
 +    private VirtualRouterDeployer _vrDeployer;
 +    private Map<String, Queue<NetworkElementCommand>> _vrAggregateCommandsSet;
 +    protected Map<String, Lock> _vrLockMap = new HashMap<String, Lock>();
 +
 +    private String _name;
 +    private int _sleep;
 +    private int _retry;
 +    private int _port;
 +    private Duration _eachTimeout;
 +    private Map<String, Object> _params;
 +
 +    private String _cfgVersion = "1.0";
 +
 +    public VirtualRoutingResource(VirtualRouterDeployer deployer) {
 +        _vrDeployer = deployer;
 +    }
 +
 +    public Answer executeRequest(final NetworkElementCommand cmd) {
 +        boolean aggregated = false;
 +        String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
 +        Lock lock;
 +        if (_vrLockMap.containsKey(routerName)) {
 +            lock = _vrLockMap.get(routerName);
 +        } else {
 +            lock = new ReentrantLock();
 +            _vrLockMap.put(routerName, lock);
 +        }
 +        lock.lock();
 +
 +        try {
 +            ExecutionResult rc = _vrDeployer.prepareCommand(cmd);
 +            if (!rc.isSuccess()) {
 +                s_logger.error("Failed to prepare VR command due to " + rc.getDetails());
 +                return new Answer(cmd, false, rc.getDetails());
 +            }
 +
 +            assert cmd.getRouterAccessIp() != null : "Why there is no access IP for VR?";
 +
 +            if (cmd.isQuery()) {
 +                return executeQueryCommand(cmd);
 +            }
 +
 +            if (cmd instanceof SetupKeyStoreCommand) {
 +                return execute((SetupKeyStoreCommand) cmd);
 +            }
 +
 +            if (cmd instanceof SetupCertificateCommand) {
 +                return execute((SetupCertificateCommand) cmd);
 +            }
 +
 +            if (cmd instanceof AggregationControlCommand) {
 +                return execute((AggregationControlCommand)cmd);
 +            }
 +
 +            if (_vrAggregateCommandsSet.containsKey(routerName)) {
 +                _vrAggregateCommandsSet.get(routerName).add(cmd);
 +                aggregated = true;
 +                // Clean up would be done after command has been executed
 +                //TODO: Deal with group answer as well
 +                return new Answer(cmd);
 +            }
 +
 +            List<ConfigItem> cfg = generateCommandCfg(cmd);
 +            if (cfg == null) {
 +                return Answer.createUnsupportedCommandAnswer(cmd);
 +            }
 +
 +            return applyConfig(cmd, cfg);
 +        } catch (final IllegalArgumentException e) {
 +            return new Answer(cmd, false, e.getMessage());
 +        } finally {
 +            lock.unlock();
 +            if (!aggregated) {
 +                ExecutionResult rc = _vrDeployer.cleanupCommand(cmd);
 +                if (!rc.isSuccess()) {
 +                    s_logger.error("Failed to cleanup VR command due to " + rc.getDetails());
 +                }
 +            }
 +        }
 +    }
 +
 +    private Answer execute(final SetupKeyStoreCommand cmd) {
 +        final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties " +
 +                        "/usr/local/cloud/systemvm/conf/%s " +
 +                        "%s %d " +
 +                        "/usr/local/cloud/systemvm/conf/%s",
 +                KeyStoreUtils.KS_FILENAME,
 +                cmd.getKeystorePassword(),
 +                cmd.getValidityDays(),
 +                KeyStoreUtils.CSR_FILENAME);
-         ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), KeyStoreUtils.KS_SETUP_SCRIPT, args);
++        ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), KeyStoreUtils.KS_SETUP_SCRIPT, args, Duration.standardMinutes(15));
 +        return new SetupKeystoreAnswer(result.getDetails());
 +    }
 +
 +    private Answer execute(final SetupCertificateCommand cmd) {
 +        final String args = String.format("/usr/local/cloud/systemvm/conf/agent.properties " +
 +                        "/usr/local/cloud/systemvm/conf/%s %s " +
 +                        "/usr/local/cloud/systemvm/conf/%s \"%s\" " +
 +                        "/usr/local/cloud/systemvm/conf/%s \"%s\" " +
 +                        "/usr/local/cloud/systemvm/conf/%s \"%s\"",
 +                KeyStoreUtils.KS_FILENAME,
 +                KeyStoreUtils.SSH_MODE,
 +                KeyStoreUtils.CERT_FILENAME,
 +                cmd.getEncodedCertificate(),
 +                KeyStoreUtils.CACERT_FILENAME,
 +                cmd.getEncodedCaCertificates(),
 +                KeyStoreUtils.PKEY_FILENAME,
 +                cmd.getEncodedPrivateKey());
-         ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), KeyStoreUtils.KS_IMPORT_SCRIPT, args);
++        ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), KeyStoreUtils.KS_IMPORT_SCRIPT, args, Duration.standardMinutes(15));
 +        return new SetupCertificateAnswer(result.isSuccess());
 +    }
 +
 +    private Answer executeQueryCommand(NetworkElementCommand cmd) {
 +        if (cmd instanceof CheckRouterCommand) {
 +            return execute((CheckRouterCommand)cmd);
 +        } else if (cmd instanceof GetDomRVersionCmd) {
 +            return execute((GetDomRVersionCmd)cmd);
 +        } else if (cmd instanceof CheckS2SVpnConnectionsCommand) {
 +            return execute((CheckS2SVpnConnectionsCommand)cmd);
 +        } else if (cmd instanceof GetRouterAlertsCommand) {
 +            return execute((GetRouterAlertsCommand)cmd);
 +        } else if (cmd instanceof DiagnosticsCommand) {
 +            return execute((DiagnosticsCommand)cmd);
 +        } else {
 +            s_logger.error("Unknown query command in VirtualRoutingResource!");
 +            return Answer.createUnsupportedCommandAnswer(cmd);
 +        }
 +    }
 +
 +    private ExecutionResult applyConfigToVR(String routerAccessIp, ConfigItem c) {
 +        return applyConfigToVR(routerAccessIp, c, VRScripts.VR_SCRIPT_EXEC_TIMEOUT);
 +    }
 +
 +    private ExecutionResult applyConfigToVR(String routerAccessIp, ConfigItem c, Duration timeout) {
 +        if (c instanceof FileConfigItem) {
 +            FileConfigItem configItem = (FileConfigItem)c;
 +            return _vrDeployer.createFileInVR(routerAccessIp, configItem.getFilePath(), configItem.getFileName(), configItem.getFileContents());
 +        } else if (c instanceof ScriptConfigItem) {
 +            ScriptConfigItem configItem = (ScriptConfigItem)c;
 +            return _vrDeployer.executeInVR(routerAccessIp, configItem.getScript(), configItem.getArgs(), timeout);
 +        }
 +        throw new CloudRuntimeException("Unable to apply unknown configitem of type " + c.getClass().getSimpleName());
 +    }
 +
 +
 +    private Answer applyConfig(NetworkElementCommand cmd, List<ConfigItem> cfg) {
 +
 +
 +        if (cfg.isEmpty()) {
 +            return new Answer(cmd, true, "Nothing to do");
 +        }
 +
 +        List<ExecutionResult> results = new ArrayList<ExecutionResult>();
 +        List<String> details = new ArrayList<String>();
 +        boolean finalResult = false;
 +        for (ConfigItem configItem : cfg) {
 +            long startTimestamp = System.currentTimeMillis();
 +            ExecutionResult result = applyConfigToVR(cmd.getRouterAccessIp(), configItem, VRScripts.VR_SCRIPT_EXEC_TIMEOUT);
 +            if (s_logger.isDebugEnabled()) {
 +                long elapsed = System.currentTimeMillis() - startTimestamp;
 +                s_logger.debug("Processing " + configItem + " took " + elapsed + "ms");
 +            }
 +            if (result == null) {
 +                result = new ExecutionResult(false, "null execution result");
 +            }
 +            results.add(result);
 +            details.add(configItem.getInfo() + (result.isSuccess() ? " - success: " : " - failed: ") + result.getDetails());
 +            finalResult = result.isSuccess();
 +        }
 +
 +        // Not sure why this matters, but log it anyway
 +        if (cmd.getAnswersCount() != results.size()) {
 +            s_logger.warn("Expected " + cmd.getAnswersCount() + " answers while executing " + cmd.getClass().getSimpleName() + " but received " + results.size());
 +        }
 +
 +
 +        if (results.size() == 1) {
 +            return new Answer(cmd, finalResult, results.get(0).getDetails());
 +        } else {
 +            return new GroupAnswer(cmd, finalResult, results.size(), details.toArray(new String[details.size()]));
 +        }
 +    }
 +
 +    private CheckS2SVpnConnectionsAnswer execute(CheckS2SVpnConnectionsCommand cmd) {
 +
 +        StringBuffer buff = new StringBuffer();
 +        for (String ip : cmd.getVpnIps()) {
 +            buff.append(ip);
 +            buff.append(" ");
 +        }
 +        ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.S2SVPN_CHECK, buff.toString());
 +        return new CheckS2SVpnConnectionsAnswer(cmd, result.isSuccess(), result.getDetails());
 +    }
 +
 +    private GetRouterAlertsAnswer execute(GetRouterAlertsCommand cmd) {
 +
 +        String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
 +        String args = cmd.getPreviousAlertTimeStamp();
 +
 +        ExecutionResult result = _vrDeployer.executeInVR(routerIp, VRScripts.ROUTER_ALERTS, args);
 +        String alerts[] = null;
 +        String lastAlertTimestamp = null;
 +
 +        if (result.isSuccess()) {
 +            if (!result.getDetails().isEmpty() && !result.getDetails().trim().equals("No Alerts")) {
 +                alerts = result.getDetails().trim().split("\\\\n");
 +                String[] lastAlert = alerts[alerts.length - 1].split(",");
 +                lastAlertTimestamp = lastAlert[0];
 +            }
 +            return new GetRouterAlertsAnswer(cmd, alerts, lastAlertTimestamp);
 +        } else {
 +            return new GetRouterAlertsAnswer(cmd, result.getDetails());
 +        }
 +    }
 +
 +    private Answer execute(CheckRouterCommand cmd) {
 +        final ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.RVR_CHECK, null);
 +        if (!result.isSuccess()) {
 +            return new CheckRouterAnswer(cmd, result.getDetails());
 +        }
 +        return new CheckRouterAnswer(cmd, result.getDetails(), true);
 +    }
 +
 +    private Answer execute(DiagnosticsCommand cmd) {
 +        _eachTimeout = Duration.standardSeconds(NumbersUtil.parseInt("60", 60));
 +        final ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.DIAGNOSTICS, cmd.getSrciptArguments(), _eachTimeout);
 +        if (!result.isSuccess()) {
 +            return new DiagnosticsAnswer(cmd, false, result.getDetails());
 +        }
 +        return new DiagnosticsAnswer(cmd, result.isSuccess(), result.getDetails());
 +    }
 +
 +    private Answer execute(GetDomRVersionCmd cmd) {
 +        final ExecutionResult result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.VERSION, null);
 +        if (!result.isSuccess()) {
 +            return new GetDomRVersionAnswer(cmd, "GetDomRVersionCmd failed");
 +        }
 +        String[] lines = result.getDetails().split("&");
 +        if (lines.length != 2) {
 +            return new GetDomRVersionAnswer(cmd, result.getDetails());
 +        }
 +        return new GetDomRVersionAnswer(cmd, result.getDetails(), lines[0], lines[1]);
 +    }
 +
 +    public boolean configureHostParams(final Map<String, String> params) {
 +        if (_params.get("router.aggregation.command.each.timeout") == null) {
 +            String value = (String)params.get("router.aggregation.command.each.timeout");
 +            _eachTimeout = Duration.standardSeconds(NumbersUtil.parseInt(value, 10));
 +        }
 +
 +        return true;
 +    }
 +
 +    public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
 +        _name = name;
 +        _params = params;
 +
 +        String value = (String)params.get("ssh.sleep");
 +        _sleep = NumbersUtil.parseInt(value, 10) * 1000;
 +
 +        value = (String)params.get("ssh.retry");
 +        _retry = NumbersUtil.parseInt(value, 36);
 +
 +        value = (String)params.get("ssh.port");
 +        _port = NumbersUtil.parseInt(value, 3922);
 +
 +        value = (String)params.get("router.aggregation.command.each.timeout");
 +        _eachTimeout = Duration.standardSeconds(NumbersUtil.parseInt(value, (int)VRScripts.VR_SCRIPT_EXEC_TIMEOUT.getStandardSeconds()));
 +        if (s_logger.isDebugEnabled()){
 +            s_logger.debug("The router.aggregation.command.each.timeout in seconds is set to " + _eachTimeout.getStandardSeconds());
 +        }
 +
 +        if (_vrDeployer == null) {
 +            throw new ConfigurationException("Unable to find the resource for VirtualRouterDeployer!");
 +        }
 +
 +        _vrAggregateCommandsSet = new HashMap<>();
 +        return true;
 +    }
 +
 +    public boolean connect(final String ipAddress) {
 +        return connect(ipAddress, _port);
 +    }
 +
 +    public boolean connect(final String ipAddress, final int port) {
 +        return connect(ipAddress, port, _sleep);
 +    }
 +
 +    public boolean connect(final String ipAddress, int retry, int sleep) {
 +        for (int i = 0; i <= retry; i++) {
 +            SocketChannel sch = null;
 +            try {
 +                if (s_logger.isDebugEnabled()) {
 +                    s_logger.debug("Trying to connect to " + ipAddress);
 +                }
 +                sch = SocketChannel.open();
 +                sch.configureBlocking(true);
 +
 +                final InetSocketAddress addr = new InetSocketAddress(ipAddress, _port);
 +                sch.connect(addr);
 +                return true;
 +            } catch (final IOException e) {
 +                if (s_logger.isDebugEnabled()) {
 +                    s_logger.debug("Could not connect to " + ipAddress);
 +                }
 +            } finally {
 +                if (sch != null) {
 +                    try {
 +                        sch.close();
 +                    } catch (final IOException e) {
 +                    }
 +                }
 +            }
 +            try {
 +                Thread.sleep(sleep);
 +            } catch (final InterruptedException e) {
 +            }
 +        }
 +
 +        s_logger.debug("Unable to logon to " + ipAddress);
 +
 +        return false;
 +    }
 +
 +    private List<ConfigItem> generateCommandCfg(NetworkElementCommand cmd) {
 +        /*
 +         * [TODO] Still have to migrate LoadBalancerConfigCommand and BumpUpPriorityCommand
 +         * [FIXME] Have a look at SetSourceNatConfigItem
 +         */
 +        s_logger.debug("Transforming " + cmd.getClass().getCanonicalName() + " to ConfigItems");
 +
 +        final AbstractConfigItemFacade configItemFacade = AbstractConfigItemFacade.getInstance(cmd.getClass());
 +
 +        return configItemFacade.generateConfig(cmd);
 +    }
 +
 +    private Answer execute(AggregationControlCommand cmd) {
 +        Action action = cmd.getAction();
 +        String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
 +        assert routerName != null;
 +        assert cmd.getRouterAccessIp() != null;
 +
 +        if (action == Action.Start) {
 +            assert (!_vrAggregateCommandsSet.containsKey(routerName));
 +
 +            Queue<NetworkElementCommand> queue = new LinkedBlockingQueue<>();
 +            _vrAggregateCommandsSet.put(routerName, queue);
 +            return new Answer(cmd, true, "Command aggregation started");
 +        } else if (action == Action.Finish) {
 +            Queue<NetworkElementCommand> queue = _vrAggregateCommandsSet.get(routerName);
 +            int answerCounts = 0;
 +            try {
 +                StringBuilder sb = new StringBuilder();
 +                sb.append("#Apache CloudStack Virtual Router Config File\n");
 +                sb.append("<version>\n" + _cfgVersion + "\n</version>\n");
 +                for (NetworkElementCommand command : queue) {
 +                    answerCounts += command.getAnswersCount();
 +                    List<ConfigItem> cfg = generateCommandCfg(command);
 +                    if (cfg == null) {
 +                        s_logger.warn("Unknown commands for VirtualRoutingResource, but continue: " + cmd.toString());
 +                        continue;
 +                    }
 +
 +                    for (ConfigItem c : cfg) {
 +                        sb.append(c.getAggregateCommand());
 +                    }
 +                }
 +
 +                // TODO replace with applyConfig with a stop on fail
 +                String cfgFileName = "VR-"+ UUID.randomUUID().toString() + ".cfg";
 +                FileConfigItem fileConfigItem = new FileConfigItem(VRScripts.CONFIG_CACHE_LOCATION, cfgFileName, sb.toString());
 +                ScriptConfigItem scriptConfigItem = new ScriptConfigItem(VRScripts.VR_CFG, "-c " + VRScripts.CONFIG_CACHE_LOCATION + cfgFileName);
 +                // 120s is the minimal timeout
 +                Duration timeout = _eachTimeout.withDurationAdded(_eachTimeout.getStandardSeconds(), answerCounts);
 +                if (s_logger.isDebugEnabled()){
 +                    s_logger.debug("Aggregate action timeout in seconds is " + timeout.getStandardSeconds());
 +                }
 +
 +                ExecutionResult result = applyConfigToVR(cmd.getRouterAccessIp(), fileConfigItem, timeout);
 +                if (!result.isSuccess()) {
 +                    return new Answer(cmd, false, result.getDetails());
 +                }
 +
 +                result = applyConfigToVR(cmd.getRouterAccessIp(), scriptConfigItem, timeout);
 +                if (!result.isSuccess()) {
 +                    return new Answer(cmd, false, result.getDetails());
 +                }
 +
 +                return new Answer(cmd, true, "Command aggregation finished");
 +            } finally {
 +                queue.clear();
 +                _vrAggregateCommandsSet.remove(routerName);
 +            }
 +        }
 +        return new Answer(cmd, false, "Fail to recognize aggregation action " + action.toString());
 +    }
 +}
diff --cc packaging/systemd/cloudstack-management.service
index 28eedef,58c4343..e10b82e
--- a/packaging/systemd/cloudstack-management.service
+++ b/packaging/systemd/cloudstack-management.service
@@@ -28,8 -28,8 +28,8 @@@ Environment="NAME=cloudstack-management
  EnvironmentFile=/etc/default/cloudstack-management
  ExecStartPre=/bin/bash -c "/bin/systemctl set-environment JAVA_HOME=$( readlink -f $( which java ) | sed s:bin/.*$:: )"
  ExecStartPre=/bin/bash -c "/bin/systemctl set-environment JARS=$(ls /usr/share/cloudstack-management/lib/*.jar | tr '\n' ':' | sed s'/.$//')"
- ExecStart=/usr/bin/jsvc $JAVA_DEBUG -home "${JAVA_HOME}" -user "${CLOUDSTACK_USER}" -cp "${JARS}:${CLASSPATH}" -errfile ${LOGDIR}/${NAME}.err -cwd ${LOGDIR} -pidfile "${CLOUDSTACK_PID}" ${JAVA_OPTS} "${BOOTSTRAP_CLASS}"
- ExecStop=/usr/bin/jsvc -cp "$JARS:$CLASSPATH" -pidfile "$CLOUDSTACK_PID" -stop "$BOOTSTRAP_CLASS"
 -ExecStart=/usr/bin/jsvc -home "${JAVA_HOME}" -user "${CLOUDSTACK_USER}" -cp "${JARS}:${CLASSPATH}" -errfile "${LOGDIR}/${NAME}.err" -cwd "${LOGDIR}" -pidfile "${CLOUDSTACK_PID}" "${JAVA_OPTS}" "${BOOTSTRAP_CLASS}"
++ExecStart=/usr/bin/jsvc $JAVA_DEBUG -home "${JAVA_HOME}" -user "${CLOUDSTACK_USER}" -cp "${JARS}:${CLASSPATH}" -errfile "${LOGDIR}/${NAME}.err" -cwd "${LOGDIR}" -pidfile "${CLOUDSTACK_PID}" "${JAVA_OPTS}" "${BOOTSTRAP_CLASS}"
+ ExecStop=/usr/bin/jsvc -cp "${JARS}:${CLASSPATH}" -pidfile "${CLOUDSTACK_PID}" -stop "${BOOTSTRAP_CLASS}"
  SuccessExitStatus=143
  
  [Install]