From 0fe7c5c9353eb1970238015cf48668d196adf82d Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Tue, 18 Jun 2013 14:56:07 -0700 Subject: [PATCH] CLOUDSTACK-2843: Provideded an ability to turn off the synchronization being done on the CS agent side, for number of commands participating in Vm deployment process, as parallel deployment is supported on the hypervisor side. The behavior is controlled by global config varirables: "execute.in.sequence.hypervisor.commands" (false by default) sets/resets the synchronization for commands: ========================= StartCommand StopCommand CreateCommand CopyVolumeCommand "execute.in.sequence.network.element.commands" (false by default) sets/resets the synchronization for commands: ========================== DhcpEntryCommand SavePasswordCommand UserDataCommand VmDataCommand As a part of the fix, increased the global lock timeout to 30 mins in several VR scripts: =========================== edithosts.sh savepassword.sh userdata.sh to support situations when multiple concurrent calls to the script are being made. --- api/src/com/cloud/network/NetworkModel.java | 2 ++ .../src/com/cloud/agent/api/StartCommand.java | 10 +++--- core/src/com/cloud/agent/api/StopCommand.java | 15 ++++++--- .../agent/api/routing/DhcpEntryCommand.java | 10 +++--- .../api/routing/SavePasswordCommand.java | 6 ++-- .../agent/api/routing/UserDataCommand.java | 6 ++-- .../agent/api/routing/VmDataCommand.java | 10 +++--- .../agent/api/storage/CopyVolumeCommand.java | 6 ++-- .../agent/api/storage/CreateCommand.java | 32 +++++++++++-------- .../motion/AncientDataMotionStrategy.java | 18 +++++++---- .../systemvm/debian/config/root/edithosts.sh | 4 ++- .../debian/config/root/savepassword.sh | 4 ++- .../systemvm/debian/config/root/userdata.sh | 4 ++- .../BaremetalDhcpManagerImpl.java | 5 ++- .../BaremetalPxeManagerImpl.java | 4 ++- .../CloudStackPrimaryDataStoreDriverImpl.java | 10 +++--- .../src/com/cloud/configuration/Config.java | 8 +++-- .../src/com/cloud/network/NetworkManager.java | 1 + .../com/cloud/network/NetworkManagerImpl.java | 4 +-- .../com/cloud/network/NetworkModelImpl.java | 11 +++++++ .../element/CloudZonesNetworkElement.java | 4 +-- .../VirtualNetworkApplianceManagerImpl.java | 7 ++-- .../com/cloud/server/ManagementServer.java | 2 ++ .../cloud/server/ManagementServerImpl.java | 14 ++++++-- .../cloud/vm/VirtualMachineManagerImpl.java | 15 +++++---- .../cloud/network/MockNetworkModelImpl.java | 6 ++++ .../com/cloud/vpc/MockNetworkModelImpl.java | 6 ++++ setup/db/db/schema-410to420.sql | 4 +++ 28 files changed, 155 insertions(+), 73 deletions(-) diff --git a/api/src/com/cloud/network/NetworkModel.java b/api/src/com/cloud/network/NetworkModel.java index 05307eb47aa..ea39d835eb7 100644 --- a/api/src/com/cloud/network/NetworkModel.java +++ b/api/src/com/cloud/network/NetworkModel.java @@ -274,4 +274,6 @@ public interface NetworkModel { Networks.IsolationType[] listNetworkIsolationMethods(); Nic getNicInNetworkIncludingRemoved(long vmId, long networkId); + + boolean getExecuteInSeqNtwkElmtCmd(); } \ No newline at end of file diff --git a/core/src/com/cloud/agent/api/StartCommand.java b/core/src/com/cloud/agent/api/StartCommand.java index ec707d6e851..308730ab5b7 100644 --- a/core/src/com/cloud/agent/api/StartCommand.java +++ b/core/src/com/cloud/agent/api/StartCommand.java @@ -24,6 +24,7 @@ import com.cloud.host.Host; public class StartCommand extends Command { VirtualMachineTO vm; String hostIp; + boolean executeInSequence = false; public VirtualMachineTO getVirtualMachine() { return vm; @@ -31,19 +32,16 @@ public class StartCommand extends Command { @Override public boolean executeInSequence() { - return true; + return executeInSequence; } protected StartCommand() { } - public StartCommand(VirtualMachineTO vm) { - this.vm = vm; - } - - public StartCommand(VirtualMachineTO vm, Host host) { + public StartCommand(VirtualMachineTO vm, Host host, boolean executeInSequence) { this.vm = vm; this.hostIp = host.getPrivateIpAddress(); + this.executeInSequence = executeInSequence; } public String getHostIp() { diff --git a/core/src/com/cloud/agent/api/StopCommand.java b/core/src/com/cloud/agent/api/StopCommand.java index 1c67f3816ca..a3ee3c967d3 100755 --- a/core/src/com/cloud/agent/api/StopCommand.java +++ b/core/src/com/cloud/agent/api/StopCommand.java @@ -23,28 +23,33 @@ public class StopCommand extends RebootCommand { private boolean isProxy=false; private String urlPort=null; private String publicConsoleProxyIpAddress=null; + boolean executeInSequence = false; protected StopCommand() { } - public StopCommand(VirtualMachine vm, boolean isProxy, String urlPort, String publicConsoleProxyIpAddress) { + public StopCommand(VirtualMachine vm, boolean isProxy, String urlPort, String publicConsoleProxyIpAddress, boolean executeInSequence) { super(vm); this.isProxy = isProxy; this.urlPort = urlPort; this.publicConsoleProxyIpAddress = publicConsoleProxyIpAddress; + this.executeInSequence = executeInSequence; } - public StopCommand(VirtualMachine vm, String vnet) { + public StopCommand(VirtualMachine vm, String vnet, boolean executeInSequence) { super(vm); this.vnet = vnet; + this.executeInSequence = executeInSequence; } - public StopCommand(VirtualMachine vm) { + public StopCommand(VirtualMachine vm, boolean executeInSequence) { super(vm); + this.executeInSequence = executeInSequence; } - public StopCommand(String vmName) { + public StopCommand(String vmName, boolean executeInSequence) { super(vmName); + this.executeInSequence = executeInSequence; } public String getVnet() { @@ -53,7 +58,7 @@ public class StopCommand extends RebootCommand { @Override public boolean executeInSequence() { - return true; + return executeInSequence; } public boolean isProxy() { diff --git a/core/src/com/cloud/agent/api/routing/DhcpEntryCommand.java b/core/src/com/cloud/agent/api/routing/DhcpEntryCommand.java index fd8d84c8c3a..d51ea5e70b5 100644 --- a/core/src/com/cloud/agent/api/routing/DhcpEntryCommand.java +++ b/core/src/com/cloud/agent/api/routing/DhcpEntryCommand.java @@ -32,6 +32,7 @@ public class DhcpEntryCommand extends NetworkElementCommand { String ip6Gateway; String duid; private boolean isDefault; + boolean executeInSequence = false; protected DhcpEntryCommand() { @@ -39,19 +40,20 @@ public class DhcpEntryCommand extends NetworkElementCommand { @Override public boolean executeInSequence() { - return true; + return executeInSequence; } - public DhcpEntryCommand(String vmMac, String vmIpAddress, String vmName, String vmIp6Address) { + public DhcpEntryCommand(String vmMac, String vmIpAddress, String vmName, String vmIp6Address, boolean executeInSequence) { this.vmMac = vmMac; this.vmIpAddress = vmIpAddress; this.vmName = vmName; this.vmIp6Address = vmIp6Address; this.setDefault(true); + this.executeInSequence = executeInSequence; } - public DhcpEntryCommand(String vmMac, String vmIpAddress, String vmName, String vmIp6Address, String dns, String gateway, String ip6Gateway) { - this(vmMac, vmIpAddress, vmName, vmIp6Address); + public DhcpEntryCommand(String vmMac, String vmIpAddress, String vmName, String vmIp6Address, String dns, String gateway, String ip6Gateway, boolean executeInSequence) { + this(vmMac, vmIpAddress, vmName, vmIp6Address, executeInSequence); this.dns = dns; this.gateway = gateway; } diff --git a/core/src/com/cloud/agent/api/routing/SavePasswordCommand.java b/core/src/com/cloud/agent/api/routing/SavePasswordCommand.java index 6dac1488e11..c77dbf60987 100644 --- a/core/src/com/cloud/agent/api/routing/SavePasswordCommand.java +++ b/core/src/com/cloud/agent/api/routing/SavePasswordCommand.java @@ -22,19 +22,21 @@ public class SavePasswordCommand extends NetworkElementCommand { String password; String vmIpAddress; String vmName; + boolean executeInSequence = false; protected SavePasswordCommand() { } @Override public boolean executeInSequence() { - return true; + return executeInSequence; } - public SavePasswordCommand(String password, String vmIpAddress, String vmName) { + public SavePasswordCommand(String password, String vmIpAddress, String vmName, boolean executeInSequence) { this.password = password; this.vmIpAddress = vmIpAddress; this.vmName = vmName; + this.executeInSequence = executeInSequence; } public String getPassword() { diff --git a/core/src/com/cloud/agent/api/routing/UserDataCommand.java b/core/src/com/cloud/agent/api/routing/UserDataCommand.java index f7b38c8c364..cf360023abc 100644 --- a/core/src/com/cloud/agent/api/routing/UserDataCommand.java +++ b/core/src/com/cloud/agent/api/routing/UserDataCommand.java @@ -23,6 +23,7 @@ public class UserDataCommand extends NetworkElementCommand { String vmIpAddress; String routerPrivateIpAddress; String vmName; + boolean executeInSequence = false; protected UserDataCommand() { @@ -30,14 +31,15 @@ public class UserDataCommand extends NetworkElementCommand { @Override public boolean executeInSequence() { - return true; + return executeInSequence; } - public UserDataCommand(String userData, String vmIpAddress, String routerPrivateIpAddress, String vmName) { + public UserDataCommand(String userData, String vmIpAddress, String routerPrivateIpAddress, String vmName, boolean executeInSequence) { this.userData = userData; this.vmIpAddress = vmIpAddress; this.routerPrivateIpAddress = routerPrivateIpAddress; this.vmName = vmName; + this.executeInSequence = executeInSequence; } public String getRouterPrivateIpAddress() { diff --git a/core/src/com/cloud/agent/api/routing/VmDataCommand.java b/core/src/com/cloud/agent/api/routing/VmDataCommand.java index df882554479..861f7006432 100644 --- a/core/src/com/cloud/agent/api/routing/VmDataCommand.java +++ b/core/src/com/cloud/agent/api/routing/VmDataCommand.java @@ -28,27 +28,29 @@ public class VmDataCommand extends NetworkElementCommand { String vmName; @LogLevel(Log4jLevel.Trace) List vmData; + boolean executeInSequence = false; protected VmDataCommand() { } @Override public boolean executeInSequence() { - return true; + return executeInSequence; } - public VmDataCommand(String vmIpAddress) { - this(vmIpAddress, null); + public VmDataCommand(String vmIpAddress, boolean executeInSequence) { + this(vmIpAddress, null, executeInSequence); } public String getVmName() { return vmName; } - public VmDataCommand(String vmIpAddress, String vmName) { + public VmDataCommand(String vmIpAddress, String vmName, boolean executeInSequence) { this.vmName = vmName; this.vmIpAddress = vmIpAddress; this.vmData = new ArrayList(); + this.executeInSequence = executeInSequence; } diff --git a/core/src/com/cloud/agent/api/storage/CopyVolumeCommand.java b/core/src/com/cloud/agent/api/storage/CopyVolumeCommand.java index 3d05e9ba69c..1acf2cc13f1 100644 --- a/core/src/com/cloud/agent/api/storage/CopyVolumeCommand.java +++ b/core/src/com/cloud/agent/api/storage/CopyVolumeCommand.java @@ -28,22 +28,24 @@ public class CopyVolumeCommand extends Command { String secondaryStorageURL; boolean toSecondaryStorage; String vmName; + boolean executeInSequence = false; public CopyVolumeCommand() { } - public CopyVolumeCommand(long volumeId, String volumePath, StoragePool pool, String secondaryStorageURL, boolean toSecondaryStorage, int wait) { + public CopyVolumeCommand(long volumeId, String volumePath, StoragePool pool, String secondaryStorageURL, boolean toSecondaryStorage, int wait, boolean executeInSequence) { this.volumeId = volumeId; this.volumePath = volumePath; this.pool = new StorageFilerTO(pool); this.secondaryStorageURL = secondaryStorageURL; this.toSecondaryStorage = toSecondaryStorage; setWait(wait); + this.executeInSequence = executeInSequence; } @Override public boolean executeInSequence() { - return true; + return executeInSequence; } public String getVolumePath() { diff --git a/core/src/com/cloud/agent/api/storage/CreateCommand.java b/core/src/com/cloud/agent/api/storage/CreateCommand.java index fd0375aa6e7..900abfd744e 100644 --- a/core/src/com/cloud/agent/api/storage/CreateCommand.java +++ b/core/src/com/cloud/agent/api/storage/CreateCommand.java @@ -26,6 +26,7 @@ public class CreateCommand extends Command { private StorageFilerTO pool; private DiskProfile diskCharacteristics; private String templateUrl; + boolean executeInSequence = false; protected CreateCommand() { super(); @@ -33,44 +34,47 @@ public class CreateCommand extends Command { /** * Construction for template based volumes. - * - * @param vol - * @param vm * @param diskCharacteristics * @param templateUrl * @param pool + * @param executeInSequence TODO + * @param vol + * @param vm */ - public CreateCommand(DiskProfile diskCharacteristics, String templateUrl, StorageFilerTO pool) { - this(diskCharacteristics, pool); + public CreateCommand(DiskProfile diskCharacteristics, String templateUrl, StorageFilerTO pool, boolean executeInSequence) { + this(diskCharacteristics, pool, executeInSequence); this.templateUrl = templateUrl; + this.executeInSequence = executeInSequence; } /** * Construction for regular volumes. - * - * @param vol - * @param vm * @param diskCharacteristics * @param pool + * @param executeInSequence TODO + * @param vol + * @param vm */ - public CreateCommand(DiskProfile diskCharacteristics, StorageFilerTO pool) { + public CreateCommand(DiskProfile diskCharacteristics, StorageFilerTO pool, boolean executeInSequence) { this.volId = diskCharacteristics.getVolumeId(); this.diskCharacteristics = diskCharacteristics; this.pool = pool; this.templateUrl = null; + this.executeInSequence = executeInSequence; } - public CreateCommand(DiskProfile diskCharacteristics, String templateUrl, StoragePool pool) { - this(diskCharacteristics, templateUrl, new StorageFilerTO(pool)); + public CreateCommand(DiskProfile diskCharacteristics, String templateUrl, StoragePool pool, boolean executeInSequence) { + this(diskCharacteristics, templateUrl, new StorageFilerTO(pool), executeInSequence); } - public CreateCommand(DiskProfile diskCharacteristics, StoragePool pool) { - this(diskCharacteristics, new StorageFilerTO(pool)); + public CreateCommand(DiskProfile diskCharacteristics, StoragePool pool, boolean executeInSequence) { + this(diskCharacteristics, new StorageFilerTO(pool), executeInSequence); + this.executeInSequence = executeInSequence; } @Override public boolean executeInSequence() { - return true; + return executeInSequence; } public String getTemplateUrl() { diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java index a6880c3f548..cb7940e94e4 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java +++ b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java @@ -50,11 +50,11 @@ import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.storage.CopyVolumeAnswer; import com.cloud.agent.api.storage.CopyVolumeCommand; -import com.cloud.agent.api.storage.MigrateVolumeAnswer; -import com.cloud.agent.api.storage.MigrateVolumeCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; +import com.cloud.agent.api.storage.MigrateVolumeAnswer; +import com.cloud.agent.api.storage.MigrateVolumeCommand; import com.cloud.agent.api.to.S3TO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.SwiftTO; @@ -67,6 +67,7 @@ import com.cloud.exception.StorageUnavailableException; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; +import com.cloud.server.ManagementServer; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.SnapshotVO; import com.cloud.storage.Storage.ImageFormat; @@ -138,6 +139,11 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { private SwiftManager _swiftMgr; @Inject private S3Manager _s3Mgr; + @Inject + private ManagementServer _mgmtServer; + + protected boolean _executeInSequence; + @Override public boolean canHandle(DataObject srcData, DataObject destData) { @@ -165,7 +171,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { StoragePool destPool = (StoragePool) destData.getDataStore(); CopyVolumeCommand cvCmd = new CopyVolumeCommand(srcData.getId(), volumeUUID, destPool, secondaryStorageURL, false, - _copyvolumewait); + _copyvolumewait, _mgmtServer.getExecuteInSequence()); CopyVolumeAnswer cvAnswer = null; String errMsg = null; try { @@ -321,7 +327,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { null); CreateCommand cmd = new CreateCommand(diskProfile, tmpltStoredOn.getLocalDownloadPath(), - new StorageFilerTO((StoragePool)template.getDataStore())); + new StorageFilerTO((StoragePool)template.getDataStore()), _mgmtServer.getExecuteInSequence()); Answer answer = null; StoragePool pool = (StoragePool)volume.getDataStore(); String errMsg = null; @@ -375,7 +381,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { Integer.parseInt(Config.CopyVolumeWait.getDefaultValue())); CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true, - _copyvolumewait); + _copyvolumewait, _mgmtServer.getExecuteInSequence()); CopyVolumeAnswer cvAnswer; try { cvAnswer = (CopyVolumeAnswer) this.storageMgr.sendToPool(srcPool, cvCmd); @@ -394,7 +400,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { cvCmd = new CopyVolumeCommand(volume.getId(), secondaryStorageVolumePath, destPool, - secondaryStorageURL, false, _copyvolumewait); + secondaryStorageURL, false, _copyvolumewait, _mgmtServer.getExecuteInSequence()); try { cvAnswer = (CopyVolumeAnswer) this.storageMgr.sendToPool(destPool, cvCmd); } catch (StorageUnavailableException e1) { diff --git a/patches/systemvm/debian/config/root/edithosts.sh b/patches/systemvm/debian/config/root/edithosts.sh index fb0c34fbd42..eaa82927803 100755 --- a/patches/systemvm/debian/config/root/edithosts.sh +++ b/patches/systemvm/debian/config/root/edithosts.sh @@ -69,7 +69,9 @@ HOSTS=/etc/hosts source /root/func.sh lock="biglock" -locked=$(getLockFile $lock) +#default timeout value is 30 mins as DhcpEntryCommand is not synchronized on agent side any more, +#and multiple commands can be sent to the same VR at a time +locked=$(getLockFile $lock 1800) if [ "$locked" != "1" ] then exit 1 diff --git a/patches/systemvm/debian/config/root/savepassword.sh b/patches/systemvm/debian/config/root/savepassword.sh index a096b862fce..fc736039c2e 100755 --- a/patches/systemvm/debian/config/root/savepassword.sh +++ b/patches/systemvm/debian/config/root/savepassword.sh @@ -25,7 +25,9 @@ source /root/func.sh lock="passwdlock" -locked=$(getLockFile $lock) +#default timeout value is 30 mins as password reset command is not synchronized on agent side any more, +#and multiple commands can be sent to the same VR at a time +locked=$(getLockFile $lock 1800) if [ "$locked" != "1" ] then exit 1 diff --git a/patches/systemvm/debian/config/root/userdata.sh b/patches/systemvm/debian/config/root/userdata.sh index e5d170b5b23..f9ea644c2fd 100644 --- a/patches/systemvm/debian/config/root/userdata.sh +++ b/patches/systemvm/debian/config/root/userdata.sh @@ -21,7 +21,9 @@ source /root/func.sh lock="biglock" -locked=$(getLockFile $lock) +#default timeout value is 30 mins as userdata command is not synchronized on agent side any more, +#and multiple commands can be sent to the same VR at a time +locked=$(getLockFile $lock 1800) if [ "$locked" != "1" ] then exit 1 diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java index f87bf71ca13..c749211e375 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java @@ -53,6 +53,7 @@ import com.cloud.host.Host.Type; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.network.Network; +import com.cloud.network.NetworkModel; import com.cloud.network.PhysicalNetworkServiceProvider; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; @@ -100,6 +101,8 @@ public class BaremetalDhcpManagerImpl extends ManagerBase implements BaremetalDh PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; @Inject BaremetalDhcpDao _extDhcpDao; + @Inject + NetworkModel _ntwkModel; @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -147,7 +150,7 @@ public class BaremetalDhcpManagerImpl extends ManagerBase implements BaremetalDh dns = nic.getDns2(); } DhcpEntryCommand dhcpCommand = new DhcpEntryCommand(nic.getMacAddress(), nic.getIp4Address(), profile.getVirtualMachine().getHostName(), null, dns, - nic.getGateway(), null); + nic.getGateway(), null, _ntwkModel.getExecuteInSeqNtwkElmtCmd()); String errMsg = String.format("Set dhcp entry on external DHCP %1$s failed(ip=%2$s, mac=%3$s, vmname=%4$s)", h.getPrivateIpAddress(), nic.getIp4Address(), nic.getMacAddress(), profile.getVirtualMachine().getHostName()); // prepareBareMetalDhcpEntry(nic, dhcpCommand); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java index 59a28117cb5..04f5fbc34a7 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java @@ -45,6 +45,7 @@ import com.cloud.deploy.DeployDestination; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; +import com.cloud.network.NetworkModel; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.resource.ResourceManager; @@ -81,6 +82,7 @@ public class BaremetalPxeManagerImpl extends ManagerBase implements BaremetalPxe @Inject NicDao _nicDao; @Inject ConfigurationDao _configDao; @Inject PhysicalNetworkDao _phynwDao; + @Inject NetworkModel _ntwkModel; @Override public boolean configure(String name, Map params) throws ConfigurationException { @@ -184,7 +186,7 @@ public class BaremetalPxeManagerImpl extends ManagerBase implements BaremetalPxe String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getServiceOfferingId()).getDisplayText(); String zoneName = _dcDao.findById(vm.getDataCenterId()).getName(); NicVO nvo = _nicDao.findById(nic.getId()); - VmDataCommand cmd = new VmDataCommand(nvo.getIp4Address(), vm.getInstanceName()); + VmDataCommand cmd = new VmDataCommand(nvo.getIp4Address(), vm.getInstanceName(), _ntwkModel.getExecuteInSeqNtwkElmtCmd()); cmd.addVmData("userdata", "user-data", vm.getUserData()); cmd.addVmData("metadata", "service-offering", StringUtils.unicodeEscape(serviceOffering)); cmd.addVmData("metadata", "availability-zone", StringUtils.unicodeEscape(zoneName)); diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java index 04869020468..fa099d31b9f 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java @@ -49,11 +49,12 @@ import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.exception.StorageUnavailableException; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; +import com.cloud.server.ManagementServer; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.ResizeVolumePayload; +import com.cloud.storage.SnapshotVO; import com.cloud.storage.Storage; import com.cloud.storage.Storage.StoragePoolType; -import com.cloud.storage.SnapshotVO; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.VMTemplateHostVO; @@ -85,6 +86,7 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri @Inject SnapshotDao snapshotDao; @Inject PrimaryDataStoreDao primaryStoreDao; @Inject SnapshotManager snapshotMgr; + @Inject ManagementServer _mgmtSrvr; @Override public String grantAccess(DataObject data, EndPoint ep) { // TODO Auto-generated method stub @@ -152,7 +154,7 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri String fullTmpltUrl = tmpltHostUrl + "/" + tmpltHostOn.getInstallPath(); cmd = new CreateCommand(diskProfile, fullTmpltUrl, - new StorageFilerTO(pool)); + new StorageFilerTO(pool), _mgmtSrvr.getExecuteInSequence()); } else { tmpltStoredOn = templateMgr.prepareTemplateForCreate( template, pool); @@ -166,7 +168,7 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri } cmd = new CreateCommand(diskProfile, tmpltStoredOn.getLocalDownloadPath(), - new StorageFilerTO(pool)); + new StorageFilerTO(pool), _mgmtSrvr.getExecuteInSequence()); } } else { if (template != null @@ -180,7 +182,7 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri } } cmd = new CreateCommand(diskProfile, new StorageFilerTO( - pool)); + pool), _mgmtSrvr.getExecuteInSequence()); } Answer answer = storageMgr.sendToPool(pool, null, cmd); diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 5432ab6dd4e..827b9bbda60 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -422,9 +422,11 @@ public enum Config { BlacklistedRoutes("Advanced", VpcManager.class, String.class, "blacklisted.routes", null, "Routes that are blacklisted, can not be used for Static Routes creation for the VPC Private Gateway", "routes", ConfigurationParameterScope.zone.toString()), - InternalLbVmServiceOfferingId("Advanced", ManagementServer.class, Long.class, "internallbvm.service.offering", null, "Uuid of the service offering used by internal lb vm; if NULL - default system internal lb offering will be used", null); - - + InternalLbVmServiceOfferingId("Advanced", ManagementServer.class, Long.class, "internallbvm.service.offering", null, "Uuid of the service offering used by internal lb vm; if NULL - default system internal lb offering will be used", null), + ExecuteInSequence("Advanced", ManagementServer.class, Boolean.class, "execute.in.sequence.hypervisor.commands", "false", "If set to true, StartCommand, StopCommand, CopyVolumeCommand, CreateCommand will be synchronized on the agent side." + + " If set to false, these commands become asynchronous. Default value is false.", null), + ExecuteInSequenceNetworkElementCommands("Advanced", NetworkManager.class, Boolean.class, "execute.in.sequence.network.element.commands", "false", "If set to true, DhcpEntryCommand, SavePasswordCommand, UserDataCommand, VmDataCommand will be synchronized on the agent side." + + " If set to false, these commands become asynchronous. Default value is false.", null); private final String _category; private final Class _componentClass; diff --git a/server/src/com/cloud/network/NetworkManager.java b/server/src/com/cloud/network/NetworkManager.java index bc43daa9975..306169ebcf6 100755 --- a/server/src/com/cloud/network/NetworkManager.java +++ b/server/src/com/cloud/network/NetworkManager.java @@ -386,4 +386,5 @@ public interface NetworkManager { DhcpServiceProvider getDhcpServiceProvider(Network network); PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List vlanDbIds, Long networkId, String requestedIp, boolean isSystem) throws InsufficientAddressCapacityException; + } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 274e79468e2..745fe2344d4 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1234,7 +1234,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L _configs = _configDao.getConfiguration("AgentManager", params); _networkGcWait = NumbersUtil.parseInt(_configs.get(Config.NetworkGcWait.key()), 600); _networkGcInterval = NumbersUtil.parseInt(_configs.get(Config.NetworkGcInterval.key()), 600); - + _configs = _configDao.getConfiguration("Network", params); _networkLockTimeout = NumbersUtil.parseInt(_configs.get(Config.NetworkLockTimeout.key()), 600); @@ -4364,5 +4364,5 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L nic.setVmType(vmType); return _nicDao.persist(nic); } - + } diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index fa34d65ab1a..4a4da8e3f4f 100755 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -208,11 +208,16 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { private boolean _allowSubdomainNetworkAccess; private Map _configs; + + protected boolean _executeInSequenceNtwkElmtCmd; HashMap _lastNetworkIdsToFree = new HashMap(); static HashMap> s_serviceToImplementedProvidersMap = new HashMap>(); static HashMap s_providerToNetworkElementMap = new HashMap(); + + + /** * */ @@ -1869,6 +1874,7 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { _configs = _configDao.getConfiguration("Network", params); _networkDomain = _configs.get(Config.GuestDomainSuffix.key()); _allowSubdomainNetworkAccess = Boolean.valueOf(_configs.get(Config.SubDomainNetworkAccess.key())); + _executeInSequenceNtwkElmtCmd = Boolean.valueOf(_configs.get(Config.ExecuteInSequenceNetworkElementCommands.key())); NetworkOfferingVO publicNetworkOffering = new NetworkOfferingVO(NetworkOfferingVO.SystemPublicNetwork, TrafficType.Public, true); publicNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(publicNetworkOffering); @@ -2112,4 +2118,9 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { public Networks.IsolationType[] listNetworkIsolationMethods() { return Networks.IsolationType.values(); } + + @Override + public boolean getExecuteInSeqNtwkElmtCmd() { + return _executeInSequenceNtwkElmtCmd; + } } diff --git a/server/src/com/cloud/network/element/CloudZonesNetworkElement.java b/server/src/com/cloud/network/element/CloudZonesNetworkElement.java index 320258b8d37..bdd8e61bbc2 100644 --- a/server/src/com/cloud/network/element/CloudZonesNetworkElement.java +++ b/server/src/com/cloud/network/element/CloudZonesNetworkElement.java @@ -152,7 +152,7 @@ public class CloudZonesNetworkElement extends AdapterBase implements NetworkElem private VmDataCommand generateVmDataCommand(String vmPrivateIpAddress, String userData, String serviceOffering, String zoneName, String guestIpAddress, String vmName, String vmInstanceName, long vmId, String vmUuid, String publicKey) { - VmDataCommand cmd = new VmDataCommand(vmPrivateIpAddress, vmName); + VmDataCommand cmd = new VmDataCommand(vmPrivateIpAddress, vmName, _networkMgr.getExecuteInSeqNtwkElmtCmd()); cmd.addVmData("userdata", "user-data", userData); cmd.addVmData("metadata", "service-offering", serviceOffering); @@ -217,7 +217,7 @@ public class CloudZonesNetworkElement extends AdapterBase implements NetworkElem Commands cmds = new Commands(OnError.Continue); if (password != null && nic.isDefaultNic()) { final String encodedPassword = PasswordGenerator.rot13(password); - SavePasswordCommand cmd = new SavePasswordCommand(encodedPassword, nic.getIp4Address(), uservm.getVirtualMachine().getHostName()); + SavePasswordCommand cmd = new SavePasswordCommand(encodedPassword, nic.getIp4Address(), uservm.getVirtualMachine().getHostName(), _networkMgr.getExecuteInSeqNtwkElmtCmd()); cmds.addCommand("password", cmd); } String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(uservm.getServiceOfferingId()).getDisplayText(); diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 8da51763982..acf73da8127 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -166,6 +166,7 @@ import com.cloud.offering.ServiceOffering; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.resource.ResourceManager; import com.cloud.server.ConfigurationServer; +import com.cloud.server.ManagementServer; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.GuestOSVO; @@ -797,7 +798,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V private VmDataCommand generateVmDataCommand(VirtualRouter router, String vmPrivateIpAddress, String userData, String serviceOffering, String zoneName, String guestIpAddress, String vmName, String vmInstanceName, long vmId, String vmUuid, String publicKey, long guestNetworkId) { - VmDataCommand cmd = new VmDataCommand(vmPrivateIpAddress, vmName); + VmDataCommand cmd = new VmDataCommand(vmPrivateIpAddress, vmName, _networkModel.getExecuteInSeqNtwkElmtCmd()); cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, getRouterIpInNetwork(guestNetworkId, router.getId())); @@ -3359,7 +3360,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V if (router.getIsRedundantRouter() && router.getRedundantState() != RedundantState.MASTER) { encodedPassword = PasswordGenerator.rot13("saved_password"); } - SavePasswordCommand cmd = new SavePasswordCommand(encodedPassword, nic.getIp4Address(), profile.getVirtualMachine().getHostName()); + SavePasswordCommand cmd = new SavePasswordCommand(encodedPassword, nic.getIp4Address(), profile.getVirtualMachine().getHostName(), _networkModel.getExecuteInSeqNtwkElmtCmd()); cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, getRouterControlIp(router.getId())); cmd.setAccessDetail(NetworkElementCommand.ROUTER_GUEST_IP, getRouterIpInNetwork(nic.getNetworkId(), router.getId())); cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); @@ -3399,7 +3400,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V } private void createDhcpEntryCommand(VirtualRouter router, UserVm vm, NicVO nic, Commands cmds) { - DhcpEntryCommand dhcpCommand = new DhcpEntryCommand(nic.getMacAddress(), nic.getIp4Address(), vm.getHostName(), nic.getIp6Address()); + DhcpEntryCommand dhcpCommand = new DhcpEntryCommand(nic.getMacAddress(), nic.getIp4Address(), vm.getHostName(), nic.getIp6Address(), _networkModel.getExecuteInSeqNtwkElmtCmd()); DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); Nic defaultNic = findGatewayIp(vm.getId()); String gatewayIp = defaultNic.getGateway(); diff --git a/server/src/com/cloud/server/ManagementServer.java b/server/src/com/cloud/server/ManagementServer.java index f60ce488e10..aec1be705dc 100755 --- a/server/src/com/cloud/server/ManagementServer.java +++ b/server/src/com/cloud/server/ManagementServer.java @@ -72,4 +72,6 @@ public interface ManagementServer extends ManagementService, PluggableService { String getEncryptionIV(); void resetEncryptionKeyIV(); + boolean getExecuteInSequence(); + } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index dea761df5da..cfc8333e9c8 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -766,6 +766,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe ConfigurationServer _configServer; @Inject UserVmManager _userVmMgr; + @Inject ClusterManager _clusterMgr; + private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker")); private final ScheduledExecutorService _alertExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AlertChecker")); @@ -788,10 +790,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe this._planners = _planners; } - @Inject ClusterManager _clusterMgr; private String _hashKey = null; private String _encryptionKey = null; private String _encryptionIV = null; + protected boolean _executeInSequence; @Inject protected AffinityGroupVMMapDao _affinityGroupVMMapDao; @@ -861,6 +863,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe _availableIdsMap.put(id, true); } + _executeInSequence = Boolean.parseBoolean(_configDao.getValue(Config.ExecuteInSequence.key())); + return true; } @@ -3469,7 +3473,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe String value = _configs.get(Config.CopyVolumeWait.toString()); int copyvolumewait = NumbersUtil.parseInt(value, Integer.parseInt(Config.CopyVolumeWait.getDefaultValue())); // Copy the volume from the source storage pool to secondary storage - CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true, copyvolumewait); + CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volume.getPath(), srcPool, secondaryStorageURL, true, copyvolumewait, _executeInSequence); CopyVolumeAnswer cvAnswer = null; try { cvAnswer = (CopyVolumeAnswer) _storageMgr.sendToPool(srcPool, cvCmd); @@ -4080,5 +4084,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return plannersAvailable; } - + + @Override + public boolean getExecuteInSequence() { + return _executeInSequence; + } } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index f946cd1ebf6..58140750d74 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -130,6 +130,7 @@ import com.cloud.offering.ServiceOffering; import com.cloud.org.Cluster; import com.cloud.resource.ResourceManager; import com.cloud.server.ConfigurationServer; +import com.cloud.server.ManagementServer; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; @@ -259,6 +260,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac protected AffinityGroupVMMapDao _affinityGroupVMMapDao; @Inject protected ConfigurationServer _configServer; + @Inject + protected ManagementServer _mgmtServer; protected List _planners; public List getPlanners() { @@ -857,7 +860,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac VirtualMachineTO vmTO = hvGuru.implement(vmProfile); cmds = new Commands(OnError.Stop); - cmds.addCommand(new StartCommand(vmTO, dest.getHost())); + cmds.addCommand(new StartCommand(vmTO, dest.getHost(), _mgmtServer.getExecuteInSequence())); vmGuru.finalizeDeployment(cmds, vmProfile, dest, ctx); @@ -897,7 +900,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.info("The guru did not like the answers so stopping " + vm); } - StopCommand cmd = new StopCommand(vm); + StopCommand cmd = new StopCommand(vm, _mgmtServer.getExecuteInSequence()); StopAnswer answer = (StopAnswer) _agentMgr.easySend(destHostId, cmd); if (answer == null || !answer.getResult()) { s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers")); @@ -984,7 +987,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac protected boolean sendStop(VirtualMachineGuru guru, VirtualMachineProfile profile, boolean force) { VMInstanceVO vm = profile.getVirtualMachine(); - StopCommand stop = new StopCommand(vm); + StopCommand stop = new StopCommand(vm, _mgmtServer.getExecuteInSequence()); try { Answer answer = _agentMgr.send(vm.getHostId(), stop); if (!answer.getResult()) { @@ -1170,7 +1173,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac vmGuru.prepareStop(profile); - StopCommand stop = new StopCommand(vm); + StopCommand stop = new StopCommand(vm, _mgmtServer.getExecuteInSequence()); boolean stopped = false; StopAnswer answer = null; try { @@ -1923,11 +1926,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } public Command cleanup(VirtualMachine vm) { - return new StopCommand(vm); + return new StopCommand(vm, _mgmtServer.getExecuteInSequence()); } public Command cleanup(String vmName) { - return new StopCommand(vmName); + return new StopCommand(vmName, _mgmtServer.getExecuteInSequence()); } public Commands fullHostSync(final long hostId, StartupRoutingCommand startup) { diff --git a/server/test/com/cloud/network/MockNetworkModelImpl.java b/server/test/com/cloud/network/MockNetworkModelImpl.java index 3a367480a30..bab9df8dd6d 100644 --- a/server/test/com/cloud/network/MockNetworkModelImpl.java +++ b/server/test/com/cloud/network/MockNetworkModelImpl.java @@ -879,4 +879,10 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel { public Nic getNicInNetworkIncludingRemoved(long vmId, long networkId) { return null; } + + @Override + public boolean getExecuteInSeqNtwkElmtCmd() { + // TODO Auto-generated method stub + return false; + } } diff --git a/server/test/com/cloud/vpc/MockNetworkModelImpl.java b/server/test/com/cloud/vpc/MockNetworkModelImpl.java index 3e67f5e76e2..a6ab1261c3c 100644 --- a/server/test/com/cloud/vpc/MockNetworkModelImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkModelImpl.java @@ -892,4 +892,10 @@ public class MockNetworkModelImpl extends ManagerBase implements NetworkModel { return null; } + @Override + public boolean getExecuteInSeqNtwkElmtCmd() { + // TODO Auto-generated method stub + return false; + } + } diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 272fc4276a6..b397559874b 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -1857,3 +1857,7 @@ UPDATE `cloud`.`networks` set name='Shared SG enabled network', display_text='Sh INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'use.system.public.ips', 'true', 'If true, when account has dedicated public ip range(s), once the ips dedicated to the account have been consumed ips will be acquired from the system pool'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'use.system.guest.vlans', 'true', 'If true, when account has dedicated guest vlan range(s), once the vlans dedicated to the account have been consumed vlans will be allocated from the system pool'); + +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'execute.in.sequence.hypervisor.commands', 'false', 'If set to true, StartCommand, StopCommand, CopyVolumeCommand, CreateCommand will be synchronized on the agent side. If set to false, these commands become asynchronous. Default value is false.'); +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'execute.in.sequence.network.element.commands', 'false', 'If set to true, DhcpEntryCommand, SavePasswordCommand, UserDataCommand, VmDataCommand will be synchronized on the agent side. If set to false, these commands become asynchronous. Default value is false.'); +