From 2691970f280c0d997f294510a7244a625151f3da Mon Sep 17 00:00:00 2001 From: Hugo Trippaers Date: Wed, 10 Jul 2013 17:48:33 +0200 Subject: [PATCH] CLOUDSTACK-728 Get the framework in place the support the removal of the portgroup that is created for a nic connected to an lswitch. Add a command to tell a hypervisor guru to take some action when expunging a nic --- .../com/cloud/hypervisor/HypervisorGuru.java | 9 +- .../cloud/agent/api/UnregisterNicCommand.java | 55 +++ .../com/cloud/hypervisor/guru/VMwareGuru.java | 80 ++-- .../vmware/resource/VmwareResource.java | 377 ++++++++++------- .../cloud/hypervisor/HypervisorGuruBase.java | 28 +- .../cloud/vm/VirtualMachineManagerImpl.java | 381 +++++++++--------- 6 files changed, 550 insertions(+), 380 deletions(-) create mode 100644 core/src/com/cloud/agent/api/UnregisterNicCommand.java diff --git a/api/src/com/cloud/hypervisor/HypervisorGuru.java b/api/src/com/cloud/hypervisor/HypervisorGuru.java index eab4e4e4ebd..47ca17a84a3 100644 --- a/api/src/com/cloud/hypervisor/HypervisorGuru.java +++ b/api/src/com/cloud/hypervisor/HypervisorGuru.java @@ -59,11 +59,18 @@ public interface HypervisorGuru extends Adapter { * @return */ NicTO toNicTO(NicProfile profile); - + /** * Give hypervisor guru opportunity to decide if certain command needs to be done after expunge VM from DB * @param vm * @return a list of Commands */ List finalizeExpunge(VirtualMachine vm); + + /** + * Give the hypervisor guru the opportinity to decide if additional clean is + * required for nics before expunging the VM + * + */ + List finalizeExpungeNics(VirtualMachine vm, List nics); } diff --git a/core/src/com/cloud/agent/api/UnregisterNicCommand.java b/core/src/com/cloud/agent/api/UnregisterNicCommand.java new file mode 100644 index 00000000000..0256d64728c --- /dev/null +++ b/core/src/com/cloud/agent/api/UnregisterNicCommand.java @@ -0,0 +1,55 @@ +// 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.api; + +import java.util.UUID; + +/** + * This command will tell the hypervisor to cleanup any resources dedicated for + * this particular nic. Orginally implemented to cleanup dedicated portgroups + * from a vmware standard switch + * + */ +public class UnregisterNicCommand extends Command { + private String vmName; + private String trafficLabel; + private UUID nicUuid; + + public UnregisterNicCommand(String vmName, String trafficLabel, UUID nicUuid) { + this.nicUuid = nicUuid; + this.vmName = vmName; + this.trafficLabel = trafficLabel; + } + + public UUID getNicUuid() { + return nicUuid; + } + + public String getVmName() { + return vmName; + } + + public String getTrafficLabel() { + return trafficLabel; + } + + @Override + public boolean executeInSequence() { + return false; + } + +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java index 95521e8f83d..4c4d8dfab6e 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java @@ -12,7 +12,7 @@ // 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 +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.hypervisor.guru; @@ -23,20 +23,19 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import javax.ejb.Local; import javax.inject.Inject; -import org.apache.cloudstack.api.ApiConstants.VMDetails; -import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import com.cloud.agent.api.BackupSnapshotCommand; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; +import com.cloud.agent.api.UnregisterNicCommand; import com.cloud.agent.api.UnregisterVMCommand; import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateVolumeOVACommand; @@ -60,11 +59,15 @@ import com.cloud.hypervisor.HypervisorGuruBase; import com.cloud.hypervisor.vmware.manager.VmwareManager; import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType; import com.cloud.network.Network.Provider; -import com.cloud.network.NetworkModel; import com.cloud.network.Network.Service; +import com.cloud.network.NetworkModel; +import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao; +import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO; import com.cloud.secstorage.CommandExecLogDao; import com.cloud.secstorage.CommandExecLogVO; import com.cloud.storage.DataStoreRole; @@ -79,10 +82,14 @@ import com.cloud.utils.net.NetUtils; import com.cloud.vm.ConsoleProxyVO; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.NicProfile; +import com.cloud.vm.NicVO; import com.cloud.vm.SecondaryStorageVmVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VmDetailConstants; +import com.cloud.vm.dao.NicDao; + +import org.apache.cloudstack.storage.command.CopyCommand; @Local(value=HypervisorGuru.class) public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { @@ -98,6 +105,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { @Inject SecondaryStorageVmManager _secStorageMgr; @Inject NetworkModel _networkMgr; @Inject ConfigurationDao _configDao; + @Inject + NicDao _nicDao; + @Inject + PhysicalNetworkDao _physicalNetworkDao; + @Inject + PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao; protected VMwareGuru() { super(); @@ -118,7 +131,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { details = new HashMap(); String nicDeviceType = details.get(VmDetailConstants.NIC_ADAPTER); - if(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO + if(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO || vm.getVirtualMachine() instanceof SecondaryStorageVmVO) { if(nicDeviceType == null) { @@ -144,13 +157,13 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { } } } - + String diskDeviceType = details.get(VmDetailConstants.ROOK_DISK_CONTROLLER); - if (!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO - || vm.getVirtualMachine() instanceof SecondaryStorageVmVO)){ + if (!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO + || vm.getVirtualMachine() instanceof SecondaryStorageVmVO)){ // user vm if (diskDeviceType == null){ - details.put(VmDetailConstants.ROOK_DISK_CONTROLLER, _vmwareMgr.getRootDiskController()); + details.put(VmDetailConstants.ROOK_DISK_CONTROLLER, _vmwareMgr.getRootDiskController()); } } @@ -236,19 +249,19 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { sbMacSequence.deleteCharAt(sbMacSequence.length() - 1); String bootArgs = to.getBootArgs(); to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString()); - + } - + // Don't do this if the virtual machine is one of the special types // Should only be done on user machines - if(!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO + if(!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO || vm.getVirtualMachine() instanceof SecondaryStorageVmVO)) { String nestedVirt = _configDao.getValue(Config.VmwareEnableNestedVirtualization.key()); if (nestedVirt != null) { s_logger.debug("Nested virtualization requested, adding flag to vm configuration"); details.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, nestedVirt); to.setDetails(details); - + } } // Determine the VM's OS description @@ -284,7 +297,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { public long getCommandHostDelegation(long hostId, Command cmd) { boolean needDelegation = false; - if(cmd instanceof PrimaryStorageDownloadCommand || + if(cmd instanceof PrimaryStorageDownloadCommand || cmd instanceof BackupSnapshotCommand || cmd instanceof CreatePrivateTemplateFromVolumeCommand || cmd instanceof CreatePrivateTemplateFromSnapshotCommand || @@ -299,7 +312,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { DataStoreTO srcStoreTO = srcData.getDataStore(); DataTO destData = cpyCommand.getDestTO(); DataStoreTO destStoreTO = destData.getDataStore(); - + if (destData.getObjectType() == DataObjectType.VOLUME && destStoreTO.getRole() == DataStoreRole.Primary && srcData.getObjectType() == DataObjectType.TEMPLATE && srcStoreTO.getRole() == DataStoreRole.Primary) { needDelegation = false; @@ -309,14 +322,14 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { } else { needDelegation = true; } - + } /* Fang: remove this before checking in */ // needDelegation = false; if (cmd instanceof PrepareOVAPackingCommand || cmd instanceof CreateVolumeOVACommand ) { - cmd.setContextParam("hypervisor", HypervisorType.VMware.toString()); + cmd.setContextParam("hypervisor", HypervisorType.VMware.toString()); } if(needDelegation) { HostVO host = _hostDao.findById(hostId); @@ -339,8 +352,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { _cmdExecLogDao.persist(execLog); cmd.setContextParam("execid", String.valueOf(execLog.getId())); - if(cmd instanceof BackupSnapshotCommand || - cmd instanceof CreatePrivateTemplateFromVolumeCommand || + if(cmd instanceof BackupSnapshotCommand || + cmd instanceof CreatePrivateTemplateFromVolumeCommand || cmd instanceof CreatePrivateTemplateFromSnapshotCommand || cmd instanceof CopyVolumeCommand || cmd instanceof CreateVolumeOVACommand || @@ -349,14 +362,14 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { String workerName = _vmwareMgr.composeWorkerName(); long checkPointId = 1; -// FIXME: Fix long checkPointId = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName)); + // FIXME: Fix long checkPointId = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName)); cmd.setContextParam("worker", workerName); cmd.setContextParam("checkpoint", String.valueOf(checkPointId)); // some commands use 2 workers String workerName2 = _vmwareMgr.composeWorkerName(); long checkPointId2 = 1; -// FIXME: Fix long checkPointId2 = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName2)); + // FIXME: Fix long checkPointId2 = _checkPointMgr.pushCheckPoint(new VmwareCleanupMaid(hostDetails.get("guid"), workerName2)); cmd.setContextParam("worker2", workerName2); cmd.setContextParam("checkpoint2", String.valueOf(checkPointId2)); } @@ -388,7 +401,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { return tokens[0] + "@" + vCenterIp; } - + @Override public List finalizeExpunge(VirtualMachine vm) { UnregisterVMCommand unregisterVMCommand = new UnregisterVMCommand(vm.getInstanceName()); @@ -396,4 +409,25 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { commands.add(unregisterVMCommand); return commands; } + + @Override + public List finalizeExpungeNics(VirtualMachine vm, List nics) { + List commands = new ArrayList(); + List nicVOs = _nicDao.listByVmId(vm.getId()); + for (NicVO nic : nicVOs) { + NetworkVO network = _networkDao.findById(nic.getNetworkId()); + if (network.getBroadcastDomainType() == BroadcastDomainType.Lswitch) { + s_logger.debug("Nic " + nic.toString() + " is connected to an lswitch, cleanup required"); + NetworkVO networkVO = _networkDao.findById(nic.getNetworkId()); + // We need the traffic label to figure out which vSwitch has the + // portgroup + PhysicalNetworkTrafficTypeVO trafficTypeVO = _physicalNetworkTrafficTypeDao.findBy( + networkVO.getPhysicalNetworkId(), networkVO.getTrafficType()); + UnregisterNicCommand unregisterNicCommand = new UnregisterNicCommand(vm.getInstanceName(), + trafficTypeVO.getVmwareNetworkLabel(), UUID.fromString(nic.getUuid())); + commands.add(unregisterNicCommand); + } + } + return commands; + } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 04978b52ee2..35735006aab 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -193,6 +193,7 @@ import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.StoragePoolInfo; import com.cloud.agent.api.UnPlugNicAnswer; import com.cloud.agent.api.UnPlugNicCommand; +import com.cloud.agent.api.UnregisterNicCommand; import com.cloud.agent.api.UnregisterVMCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.ValidateSnapshotAnswer; @@ -391,7 +392,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } public Gson getGson() { - return _gson; + return _gson; } public VmwareResource() { @@ -545,12 +546,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } else if (clz == SetNetworkACLCommand.class) { answer = execute((SetNetworkACLCommand) cmd); } else if (cmd instanceof CreateVMSnapshotCommand) { - return execute((CreateVMSnapshotCommand)cmd); + return execute((CreateVMSnapshotCommand)cmd); } else if(cmd instanceof DeleteVMSnapshotCommand){ - return execute((DeleteVMSnapshotCommand)cmd); + return execute((DeleteVMSnapshotCommand)cmd); } else if(cmd instanceof RevertToVMSnapshotCommand){ - return execute((RevertToVMSnapshotCommand)cmd); - }else if (clz == SetPortForwardingRulesVpcCommand.class) { + return execute((RevertToVMSnapshotCommand)cmd); + }else if (clz == SetPortForwardingRulesVpcCommand.class) { answer = execute((SetPortForwardingRulesVpcCommand) cmd); } else if (clz == Site2SiteVpnCfgCommand.class) { answer = execute((Site2SiteVpnCfgCommand) cmd); @@ -561,13 +562,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } else if (clz == UnregisterVMCommand.class) { return execute((UnregisterVMCommand) cmd); } else if (cmd instanceof StorageSubSystemCommand) { - return storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd); + return storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd); } else if (clz == ScaleVmCommand.class) { return execute((ScaleVmCommand) cmd); } else if (clz == PvlanSetupCommand.class) { return execute((PvlanSetupCommand) cmd); } else if (clz == SetStaticRouteCommand.class) { answer = execute((SetStaticRouteCommand) cmd); + } else if (clz == UnregisterNicCommand.class) { + answer = execute((UnregisterNicCommand) cmd); } else { answer = Answer.createUnsupportedCommandAnswer(cmd); } @@ -873,8 +876,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa null, "/root/firewallRule_egress.sh " + args); } else { result = SshHelper.sshExecute(controlIp, - DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), - null, "/root/firewall_rule.sh " + args); + DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), + null, "/root/firewall_rule.sh " + args); } if (s_logger.isDebugEnabled()) { @@ -882,10 +885,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.debug("Executing script on domain router " + controlIp + ": /root/firewallRule_egress.sh " + args); } else { - s_logger.debug("Executing script on domain router " + controlIp - + ": /root/firewall_rule.sh " + args); - } - } + s_logger.debug("Executing script on domain router " + controlIp + + ": /root/firewall_rule.sh " + args); + } + } if (!result.first()) { @@ -1126,21 +1129,21 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return -1; } -// -// find mac address of a specified ethx device -// ip address show ethx | grep link/ether | sed -e 's/^[ \t]*//' | cut -d' ' -f2 -// returns -// eth0:xx.xx.xx.xx + // + // find mac address of a specified ethx device + // ip address show ethx | grep link/ether | sed -e 's/^[ \t]*//' | cut -d' ' -f2 + // returns + // eth0:xx.xx.xx.xx -// -// list IP with eth devices -// ifconfig ethx |grep -B1 "inet addr" | awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' -// | awk -F: '{ print $1 ": " $3 }' -// -// returns -// eth0:xx.xx.xx.xx -// -// + // + // list IP with eth devices + // ifconfig ethx |grep -B1 "inet addr" | awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' + // | awk -F: '{ print $1 ": " $3 }' + // + // returns + // eth0:xx.xx.xx.xx + // + // private int findRouterEthDeviceIndex(String domrName, String routerIp, String mac) throws Exception { VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); @@ -1982,7 +1985,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa String args = " -m " + cmd.getVmMac(); if (cmd.getVmIpAddress() != null) { - args += " -4 " + cmd.getVmIpAddress(); + args += " -4 " + cmd.getVmIpAddress(); } args += " -h " + cmd.getVmName(); @@ -1999,12 +2002,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } if (cmd.getVmIp6Address() != null) { - args += " -6 " + cmd.getVmIp6Address(); - args += " -u " + cmd.getDuid(); + args += " -6 " + cmd.getVmIp6Address(); + args += " -u " + cmd.getDuid(); } if (!cmd.isDefault()) { - args += " -N"; + args += " -N"; } if (s_logger.isDebugEnabled()) { @@ -2413,16 +2416,16 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa for (DiskTO vol : disks) { if (vol.getType() != Volume.Type.ISO) { - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); - PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); - if (primaryStore.getUuid() != null && !primaryStore.getUuid().isEmpty()) { - validatedDisks.add(vol); - } + VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); + if (primaryStore.getUuid() != null && !primaryStore.getUuid().isEmpty()) { + validatedDisks.add(vol); + } } else if (vol.getType() == Volume.Type.ISO) { - TemplateObjectTO templateTO = (TemplateObjectTO)vol.getData(); - if (templateTO.getPath() != null && !templateTO.getPath().isEmpty()) { - validatedDisks.add(vol); - } + TemplateObjectTO templateTO = (TemplateObjectTO)vol.getData(); + if (templateTO.getPath() != null && !templateTO.getPath().isEmpty()) { + validatedDisks.add(vol); + } } else { if (s_logger.isDebugEnabled()) { s_logger.debug("Drop invalid disk option, volumeTO: " + _gson.toJson(vol)); @@ -2468,7 +2471,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa // Check if license supports the feature VmwareHelper.isFeatureLicensed(hyperHost, FeatureKeyConstants.HOTPLUG); VmwareHelper - .setVmScaleUpConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), vmSpec.getMinSpeed(), (int)requestedMaxMemoryInMb, ramMb, vmSpec.getLimitCpuUse()); + .setVmScaleUpConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), vmSpec.getMinSpeed(), (int)requestedMaxMemoryInMb, ramMb, vmSpec.getLimitCpuUse()); if(!vmMo.configureVm(vmConfigSpec)) { throw new Exception("Unable to execute ScaleVmCommand"); @@ -2543,15 +2546,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa Pair rootDiskDataStoreDetails = null; for (DiskTO vol : disks) { if (vol.getType() == Volume.Type.ROOT) { - PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getData().getDataStore(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getData().getDataStore(); rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid()); } } assert (vmSpec.getMinSpeed() != null) && (rootDiskDataStoreDetails != null); if (!hyperHost.createBlankVm(vmName, vmSpec.getCpus(), vmSpec.getMaxSpeed().intValue(), - vmSpec.getMinSpeed(), vmSpec.getLimitCpuUse(),(int)(vmSpec.getMaxRam()/(1024*1024)), ramMb, - translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(), rootDiskDataStoreDetails.first(), false)) { + vmSpec.getMinSpeed(), vmSpec.getLimitCpuUse(),(int)(vmSpec.getMaxRam()/(1024*1024)), ramMb, + translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(), rootDiskDataStoreDetails.first(), false)) { throw new Exception("Failed to create VM. vmName: " + vmName); } } @@ -2582,8 +2585,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec(); int ramMb = (int) (vmSpec.getMinRam() / (1024 * 1024)); VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), - vmSpec.getMinSpeed(),(int) (vmSpec.getMaxRam()/(1024*1024)), ramMb, - translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(), vmSpec.getLimitCpuUse()); + vmSpec.getMinSpeed(),(int) (vmSpec.getMaxRam()/(1024*1024)), ramMb, + translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(), vmSpec.getLimitCpuUse()); String guestOsId = translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(); // Check for hotadd settings vmConfigSpec.setMemoryHotAddEnabled(vmMo.isMemoryHotAddSupported(guestOsId)); @@ -2601,8 +2604,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa vmConfigSpec.setNestedHVEnabled(true); } else { - s_logger.warn("Hypervisor doesn't support nested virtualization, unable to set config for VM " +vmSpec.getName()); - vmConfigSpec.setNestedHVEnabled(false); + s_logger.warn("Hypervisor doesn't support nested virtualization, unable to set config for VM " +vmSpec.getName()); + vmConfigSpec.setNestedHVEnabled(false); } } @@ -2650,33 +2653,33 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa // we will always plugin a CDROM device if (volIso != null) { - TemplateObjectTO iso = (TemplateObjectTO)volIso.getData(); + TemplateObjectTO iso = (TemplateObjectTO)volIso.getData(); - if (iso.getPath() != null && !iso.getPath().isEmpty()) { - DataStoreTO imageStore = iso.getDataStore(); - if (!(imageStore instanceof NfsTO)) { - s_logger.debug("unsupported protocol"); - throw new Exception("unsupported protocol"); - } - NfsTO nfsImageStore = (NfsTO)imageStore; - String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath(); - Pair isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, isoPath); - assert (isoDatastoreInfo != null); - assert (isoDatastoreInfo.second() != null); + if (iso.getPath() != null && !iso.getPath().isEmpty()) { + DataStoreTO imageStore = iso.getDataStore(); + if (!(imageStore instanceof NfsTO)) { + s_logger.debug("unsupported protocol"); + throw new Exception("unsupported protocol"); + } + NfsTO nfsImageStore = (NfsTO)imageStore; + String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath(); + Pair isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, isoPath); + assert (isoDatastoreInfo != null); + assert (isoDatastoreInfo.second() != null); - deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); - Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, ideUnitNumber++, i + 1); - deviceConfigSpecArray[i].setDevice(isoInfo.first()); - if (isoInfo.second()) { - if(s_logger.isDebugEnabled()) - s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first())); - deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD); - } else { - if(s_logger.isDebugEnabled()) - s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first())); - deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT); - } - } + deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); + Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, ideUnitNumber++, i + 1); + deviceConfigSpecArray[i].setDevice(isoInfo.first()); + if (isoInfo.second()) { + if(s_logger.isDebugEnabled()) + s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first())); + deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD); + } else { + if(s_logger.isDebugEnabled()) + s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first())); + deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT); + } + } } else { deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, null, true, true, ideUnitNumber++, i + 1); @@ -2718,8 +2721,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } if (vol.getType() != Volume.Type.ISO) { - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); - PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); + VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); Pair volumeDsDetails = dataStoresDetails.get(primaryStore.getUuid()); assert (volumeDsDetails != null); VirtualDevice device; @@ -2731,7 +2734,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if (diskChain == null || diskChain.length < 1) { s_logger.warn("Empty previously-saved chain info, fall back to the original"); device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), - (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); + (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); } else { s_logger.info("Attach the disk with stored chain info: " + chainInfo); for (int j = 0; j < diskChain.length; j++) { @@ -2739,11 +2742,11 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, diskChain, volumeDsDetails.first(), - (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); + (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); } } else { device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), - (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); + (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); } deviceConfigSpecArray[i].setDevice(device); deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD); @@ -2807,7 +2810,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa newVal.setKey("devices.hotplug"); newVal.setValue("true"); extraOptions.add(newVal); - + /** * Extra Config : nvp.vm-uuid = uuid * - Required for Nicira NVP integration @@ -2816,7 +2819,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa newVal.setKey("nvp.vm-uuid"); newVal.setValue(vmSpec.getUuid()); extraOptions.add(newVal); - + /** * Extra Config : nvp.iface-id. = uuid * - Required for Nicira NVP integration @@ -2829,7 +2832,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa extraOptions.add(newVal); nicNum++; } - + for(Map.Entry entry : validateVmDetails(vmSpec.getDetails()).entrySet()) { newVal = new OptionValue(); newVal.setKey(entry.getKey()); @@ -2848,49 +2851,71 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMask)); + /** + * We need to configure the port on the DV switch after the host is + * connected. So make this happen between the configure and start of + * the VM + */ int nicIndex = 0; for (NicTO nicTo : sortNicsByDeviceId(nics)) { - s_logger.debug("Checking for port configuration on NIC device : " + nicTo.toString()); if (nicTo.getBroadcastType() == BroadcastDomainType.Lswitch) { // We need to create a port with a unique vlan and pass the key to the nic device - s_logger.debug("Nic " + nicTo.toString() + " needs to be configured for NVP"); + s_logger.trace("Nic " + nicTo.toString() + " is connected to an NVP logicalswitch"); VirtualDevice nicVirtualDevice = vmMo.getNicDeviceByIndex(nicIndex); if (nicVirtualDevice == null) { throw new Exception("Failed to find a VirtualDevice for nic " + nicIndex); //FIXME Generic exceptions are bad } VirtualDeviceBackingInfo backing = nicVirtualDevice.getBacking(); if (backing instanceof VirtualEthernetCardDistributedVirtualPortBackingInfo) { + // This NIC is connected to a Distributed Virtual Switch VirtualEthernetCardDistributedVirtualPortBackingInfo portInfo = (VirtualEthernetCardDistributedVirtualPortBackingInfo) backing; DistributedVirtualSwitchPortConnection port = portInfo.getPort(); String portKey = port.getPortKey(); String portGroupKey = port.getPortgroupKey(); String dvSwitchUuid = port.getSwitchUuid(); - + s_logger.debug("NIC " + nicTo.toString() + " is connected to dvSwitch " + dvSwitchUuid + " pg " + portGroupKey + " port " + portKey); - + ManagedObjectReference dvSwitchManager = vmMo.getContext().getVimClient().getServiceContent().getDvSwitchManager(); ManagedObjectReference dvSwitch = vmMo.getContext().getVimClient().getService().queryDvsByUuid(dvSwitchManager, dvSwitchUuid); - + + // Get all ports DistributedVirtualSwitchPortCriteria criteria = new DistributedVirtualSwitchPortCriteria(); criteria.setInside(true); criteria.getPortgroupKey().add(portGroupKey); - criteria.getPortKey().add(portKey); List dvPorts = vmMo.getContext().getVimClient().getService().fetchDVPorts(dvSwitch, criteria); - - if (dvPorts.isEmpty()) { - throw new Exception("Empty port list from dvSwitch for nic " + nicTo.toString()); - } else if (dvPorts.size() > 1) { - throw new Exception("Expected only one port in the list from dvSwitch for nic " + nicTo.toString()); + + DistributedVirtualPort vmDvPort = null; + List usedVlans = new ArrayList(); + for (DistributedVirtualPort dvPort : dvPorts) { + // Find the port for this NIC by portkey + if (portKey.equals(dvPort.getKey())) { + vmDvPort = dvPort; + } + VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPort + .getConfig().getSetting(); + VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings + .getVlan(); + s_logger.trace("Found port " + dvPort.getKey() + + " with vlan " + vlanId.getVlanId()); + if (vlanId.getVlanId() > 0 + && vlanId.getVlanId() < 4095) { + usedVlans.add(vlanId.getVlanId()); + } } - DistributedVirtualPort dvPort = dvPorts.get(0); - DVPortConfigInfo dvPortConfigInfo = dvPort.getConfig(); + if (vmDvPort == null) { + throw new Exception("Empty port list from dvSwitch for nic " + nicTo.toString()); + } + + DVPortConfigInfo dvPortConfigInfo = vmDvPort + .getConfig(); VMwareDVSPortSetting settings = (VMwareDVSPortSetting) dvPortConfigInfo.getSetting(); - + VmwareDistributedVirtualSwitchVlanIdSpec vlanId = (VmwareDistributedVirtualSwitchVlanIdSpec) settings.getVlan(); BoolPolicy blocked = settings.getBlocked(); if (blocked.isValue() == Boolean.TRUE) { - s_logger.debug("Port is blocked, we need to set a vlanid and unblock"); + s_logger.trace("Port is blocked, set a vlanid and unblock"); DVPortConfigSpec dvPortConfigSpec = new DVPortConfigSpec(); VMwareDVSPortSetting edittedSettings = new VMwareDVSPortSetting(); // Unblock @@ -2898,10 +2923,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa blocked.setInherited(Boolean.FALSE); edittedSettings.setBlocked(blocked); // Set vlan - vlanId.setVlanId(100); //FIXME should be a determined based on usage + for (i = 1; i < 4095; i++) { + if (!usedVlans.contains(i)) + break; + } + vlanId.setVlanId(i); // FIXME should be a determined + // based on usage vlanId.setInherited(false); edittedSettings.setVlan(vlanId); - + dvPortConfigSpec.setSetting(edittedSettings); dvPortConfigSpec.setOperation("edit"); dvPortConfigSpec.setKey(portKey); @@ -2909,11 +2939,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa dvPortConfigSpecs.add(dvPortConfigSpec); ManagedObjectReference task = vmMo.getContext().getVimClient().getService().reconfigureDVPortTask(dvSwitch, dvPortConfigSpecs); if (!vmMo.getContext().getVimClient().waitForTask(task)) { - s_logger.error("Failed to configure the dvSwitch port for nic " + nicTo.toString()); + throw new Exception( + "Failed to configure the dvSwitch port for nic " + + nicTo.toString()); } + s_logger.debug("NIC " + nicTo.toString() + + " connected to vlan " + i); } else { s_logger.trace("Port already configured and set to vlan " + vlanId.getVlanId()); } + } else if (backing instanceof VirtualEthernetCardNetworkBackingInfo) { + // This NIC is connected to a Virtual Switch + // Nothing to do } else { s_logger.error("nic device backing is of type " + backing.getClass().getName()); @@ -2926,8 +2963,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if (!vmMo.powerOn()) { throw new Exception("Failed to start VM. vmName: " + vmName); } - - state = State.Running; return new StartAnswer(cmd); @@ -3030,8 +3065,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa assert (hyperHost != null) && (context != null); for (DiskTO vol : disks) { if (vol.getType() != Volume.Type.ISO) { - VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); - PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); + VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData(); + PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore(); String poolUuid = primaryStore.getUuid(); if(poolMors.get(poolUuid) == null) { ManagedObjectReference morDataStore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid); @@ -3063,7 +3098,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if (nicTo.getBroadcastUri() != null) { if (nicTo.getBroadcastType() == BroadcastDomainType.Vlan) // For vlan, the broadcast uri is of the form vlan:// - return nicTo.getBroadcastUri().getHost(); + return nicTo.getBroadcastUri().getHost(); else // for pvlan, the broacast uri will be of the form pvlan://-i return NetUtils.getPrimaryPvlanFromUri(nicTo.getBroadcastUri()); @@ -3120,7 +3155,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa svlanId = getPvlanInfo(nicTo); } networkInfo = HypervisorHostHelper.prepareNetwork(switchName.first(), namePrefix, hostMo, vlanId, svlanId, - nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout, switchType, + nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout, switchType, _portsPerDvPortGroup, nicTo.getGateway(), configureVServiceInNexus, nicTo.getBroadcastType()); } @@ -4038,9 +4073,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if (cmd.getAttach()) { morDs = createVmfsDatastore(hyperHost, iqn, - cmd.getStorageHost(), cmd.getStoragePort(), iqn, - cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(), - cmd.getChapTargetUsername(), cmd.getChapTargetPassword()); + cmd.getStorageHost(), cmd.getStoragePort(), iqn, + cmd.getChapInitiatorUsername(), cmd.getChapInitiatorPassword(), + cmd.getChapTargetUsername(), cmd.getChapTargetPassword()); DatastoreMO dsMo = new DatastoreMO(context, morDs); @@ -4056,15 +4091,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } vmMo.createDisk(volumeDatastorePath, getMBsFromBytes(dsMo.getSummary().getFreeSpace()), - morDs, vmMo.getScsiDeviceControllerKey()); + morDs, vmMo.getScsiDeviceControllerKey()); vmMo.detachDisk(volumeDatastorePath, false); - } + } } else { - deleteVmfsDatastore(hyperHost, iqn, cmd.getStorageHost(), cmd.getStoragePort(), iqn); + deleteVmfsDatastore(hyperHost, iqn, cmd.getStorageHost(), cmd.getStoragePort(), iqn); } - return morDs; + return morDs; } protected Answer execute(AttachVolumeCommand cmd) { @@ -4089,10 +4124,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa ManagedObjectReference morDs = null; if (cmd.getAttach() && cmd.isManaged()) { - morDs = handleDatastoreAndVmdk(cmd); + morDs = handleDatastoreAndVmdk(cmd); } else { - morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getPoolUuid()); + morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, cmd.getPoolUuid()); } if (morDs == null) { @@ -4115,7 +4150,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa vmMo.detachDisk(datastoreVolumePath, false); if (cmd.isManaged()) { - handleDatastoreAndVmdk(cmd); + handleDatastoreAndVmdk(cmd); } } @@ -4515,14 +4550,14 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } protected Answer execute(RevertToVMSnapshotCommand cmd){ - try{ - VmwareContext context = getServiceContext(); - VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); - return mgr.getStorageManager().execute(this, cmd); - }catch (Exception e){ - e.printStackTrace(); - return new RevertToVMSnapshotAnswer(cmd,false,""); - } + try{ + VmwareContext context = getServiceContext(); + VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); + return mgr.getStorageManager().execute(this, cmd); + }catch (Exception e){ + e.printStackTrace(); + return new RevertToVMSnapshotAnswer(cmd,false,""); + } } protected Answer execute(CreateVolumeFromSnapshotCommand cmd) { if (s_logger.isInfoEnabled()) { @@ -4814,6 +4849,36 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } + /** + * UnregisterNicCommand is used to remove a portgroup created for this + * specific nic. The portgroup will have the name set to the UUID of the + * nic. Introduced to cleanup the portgroups created for each nic that is + * plugged into an lswitch (Nicira NVP plugin) + * + * @param cmd + * @return + */ + protected Answer execute(UnregisterNicCommand cmd) { + if (s_logger.isInfoEnabled()) { + s_logger.info("Executing resource UnregisterNicCommand: " + _gson.toJson(cmd)); + } + + VmwareContext context = getServiceContext(); + getHyperHost(context); + try { + return new Answer(cmd, true, "Not implemented yet"); + } catch (Exception e) { + if (e instanceof RemoteException) { + s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context"); + invalidateServiceContext(); + } + + String msg = "UnregisterVMCommand failed due to " + VmwareHelper.getExceptionMessage(e); + s_logger.error(msg); + return new Answer(cmd, false, msg); + } + } + public Answer execute(DeleteCommand cmd) { if (s_logger.isInfoEnabled()) { s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd)); @@ -4889,9 +4954,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true); } else { if (s_logger.isInfoEnabled()) { - s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk"); + s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk"); } - dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true); + dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true); } return new Answer(cmd, true, "Success"); } @@ -6051,10 +6116,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa CustomFieldsManagerMO cfmMo = new CustomFieldsManagerMO(context, context.getServiceContent().getCustomFieldsManager()); cfmMo.ensureCustomFieldDef("Datastore", CustomFieldConstants.CLOUD_UUID); if (_publicTrafficInfo != null && _publicTrafficInfo.getVirtualSwitchType() != VirtualSwitchType.StandardVirtualSwitch || - _guestTrafficInfo != null && _guestTrafficInfo.getVirtualSwitchType() != VirtualSwitchType.StandardVirtualSwitch) { + _guestTrafficInfo != null && _guestTrafficInfo.getVirtualSwitchType() != VirtualSwitchType.StandardVirtualSwitch) { cfmMo.ensureCustomFieldDef("DistributedVirtualPortgroup", CustomFieldConstants.CLOUD_GC_DVP); } - cfmMo.ensureCustomFieldDef("Network", CustomFieldConstants.CLOUD_GC); + cfmMo.ensureCustomFieldDef("Network", CustomFieldConstants.CLOUD_GC); cfmMo.ensureCustomFieldDef("VirtualMachine", CustomFieldConstants.CLOUD_UUID); cfmMo.ensureCustomFieldDef("VirtualMachine", CustomFieldConstants.CLOUD_NIC_MASK); @@ -6063,7 +6128,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa Map vsmCredentials; if (_guestTrafficInfo.getVirtualSwitchType() == VirtualSwitchType.NexusDistributedVirtualSwitch || - _publicTrafficInfo.getVirtualSwitchType() == VirtualSwitchType.NexusDistributedVirtualSwitch) { + _publicTrafficInfo.getVirtualSwitchType() == VirtualSwitchType.NexusDistributedVirtualSwitch) { vsmCredentials = mgr.getNexusVSMCredentialsByClusterId(Long.parseLong(_cluster)); if (vsmCredentials != null) { s_logger.info("Stocking credentials while configuring resource."); @@ -6118,8 +6183,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa int timeout = NumbersUtil.parseInt(value, 1440) * 1000; VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); VmwareStorageProcessor storageProcessor = new VmwareStorageProcessor((VmwareHostService)this, _fullCloneFlag, (VmwareStorageMount)mgr, - timeout, this, _shutdown_waitMs - ); + timeout, this, _shutdown_waitMs + ); storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor); return true; @@ -6216,41 +6281,41 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return vmName; } - @Override - public void setName(String name) { - // TODO Auto-generated method stub + @Override + public void setName(String name) { + // TODO Auto-generated method stub - } + } - @Override - public void setConfigParams(Map params) { - // TODO Auto-generated method stub + @Override + public void setConfigParams(Map params) { + // TODO Auto-generated method stub - } + } - @Override - public Map getConfigParams() { - // TODO Auto-generated method stub - return null; - } + @Override + public Map getConfigParams() { + // TODO Auto-generated method stub + return null; + } - @Override - public int getRunLevel() { - // TODO Auto-generated method stub - return 0; - } + @Override + public int getRunLevel() { + // TODO Auto-generated method stub + return 0; + } - @Override - public void setRunLevel(int level) { - // TODO Auto-generated method stub + @Override + public void setRunLevel(int level) { + // TODO Auto-generated method stub - } + } - @Override - public Answer execute(DestroyCommand cmd) { - // TODO Auto-generated method stub - return null; - } + @Override + public Answer execute(DestroyCommand cmd) { + // TODO Auto-generated method stub + return null; + } private boolean isVMWareToolsInstalled(VirtualMachineMO vmMo) throws Exception{ GuestInfo guestInfo = vmMo.getVmGuestInfo(); return (guestInfo != null && guestInfo.getGuestState() != null && guestInfo.getGuestState().equalsIgnoreCase("running")); diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java index 50bfb3068d0..769648a002d 100644 --- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -5,7 +5,7 @@ // 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, @@ -22,17 +22,13 @@ import java.util.Map; import javax.inject.Inject; import com.cloud.agent.api.Command; -import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.agent.api.to.VolumeTO; import com.cloud.configuration.Config; import com.cloud.offering.ServiceOffering; import com.cloud.server.ConfigurationServer; import com.cloud.storage.dao.VMTemplateDetailsDao; -import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.VMTemplateVO; import com.cloud.utils.component.AdapterBase; import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; @@ -41,12 +37,11 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.NicSecondaryIpDao; -import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; public abstract class HypervisorGuruBase extends AdapterBase implements HypervisorGuru { - - @Inject VMTemplateDetailsDao _templateDetailsDao; + + @Inject VMTemplateDetailsDao _templateDetailsDao; @Inject NicDao _nicDao; @Inject VMInstanceDao _virtualMachineDao; @Inject NicSecondaryIpDao _nicSecIpDao; @@ -74,7 +69,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis to.setNetworkRateMbps(profile.getNetworkRate()); to.setName(profile.getName()); to.setSecurityGroupEnabled(profile.isSecurityGroupEnabled()); - + // Workaround to make sure the TO has the UUID we need for Niciri integration NicVO nicVO = _nicDao.findById(profile.getId()); to.setUuid(nicVO.getUuid()); @@ -92,7 +87,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) { - ServiceOffering offering = vmProfile.getServiceOffering(); + ServiceOffering offering = vmProfile.getServiceOffering(); VirtualMachine vm = vmProfile.getVirtualMachine(); Long minMemory = (long) (offering.getRamSize() / vmProfile.getMemoryOvercommitRatio()); int minspeed = (int) (offering.getSpeed() / vmProfile.getCpuOvercommitRatio()); @@ -116,13 +111,13 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis } else { to.setArch("x86_64"); } - + long templateId = vm.getTemplateId(); Map details = _templateDetailsDao.findDetails(templateId); assert(details != null); Map detailsInVm = vm.getDetails(); if(detailsInVm != null) { - details.putAll(detailsInVm); + details.putAll(detailsInVm); } if (details.get(VirtualMachine.IsDynamicScalingEnabled) == null || details.get(VirtualMachine.IsDynamicScalingEnabled).isEmpty()) { to. setEnableDynamicallyScaleVm(false); @@ -134,7 +129,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis // Workaround to make sure the TO has the UUID we need for Niciri integration VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId()); to.setUuid(vmInstance.getUuid()); - + // return to; } @@ -143,9 +138,14 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis public long getCommandHostDelegation(long hostId, Command cmd) { return hostId; } - + @Override public List finalizeExpunge(VirtualMachine vm) { return null; } + + @Override + public List finalizeExpungeNics(VirtualMachine vm, List nics) { + return null; + } } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index cddd32e5770..827e2335959 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -36,12 +36,6 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; -import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -168,7 +162,6 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExecutionException; import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; -import com.cloud.vm.UserVmDetailVO; import com.cloud.vm.ItWorkVO.Step; import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.VirtualMachine.State; @@ -181,6 +174,13 @@ import com.cloud.vm.snapshot.VMSnapshotManager; import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; + @Local(value = VirtualMachineManager.class) public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMachineManager, Listener { private static final Logger s_logger = Logger.getLogger(VirtualMachineManagerImpl.class); @@ -266,19 +266,19 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac protected List _planners; public List getPlanners() { - return _planners; - } - public void setPlanners(List _planners) { - this._planners = _planners; - } + return _planners; + } + public void setPlanners(List _planners) { + this._planners = _planners; + } protected List _hostAllocators; public List getHostAllocators() { - return _hostAllocators; - } - public void setHostAllocators(List _hostAllocators) { - this._hostAllocators = _hostAllocators; - } + return _hostAllocators; + } + public void setHostAllocators(List _hostAllocators) { + this._hostAllocators = _hostAllocators; + } @Inject protected List _storagePoolAllocators; @@ -369,15 +369,15 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } if (template.getFormat() == ImageFormat.ISO) { - this.volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), rootDiskOffering.second(), vm, owner); + volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), rootDiskOffering.second(), vm, owner); } else if (template.getFormat() == ImageFormat.BAREMETAL) { // Do nothing } else { - this.volumeMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), template, vm, owner); + volumeMgr.allocateTemplatedVolume(Type.ROOT, "ROOT-" + vm.getId(), rootDiskOffering.first(), template, vm, owner); } for (Pair offering : dataDiskOfferings) { - this.volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner); + volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vm.getId(), offering.first(), offering.second(), vm, owner); } txn.commit(); @@ -457,11 +457,16 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + + HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType()); + s_logger.debug("Cleaning up NICS"); + List nicExpungeCommands = hvGuru.finalizeExpungeNics(vm, profile.getNics()); _networkMgr.cleanupNics(profile); + // Clean up volumes based on the vm's instance id List rootVol = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.ROOT); - this.volumeMgr.cleanupVolumes(vm.getId()); + volumeMgr.cleanupVolumes(vm.getId()); VirtualMachineGuru guru = getVmGuru(vm); guru.finalizeExpunge(vm); @@ -469,7 +474,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac _uservmDetailsDao.deleteDetails(vm.getId()); // send hypervisor-dependent commands before removing - HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType()); List finalizeExpungeCommands = hvGuru.finalizeExpunge(vm); if(finalizeExpungeCommands != null && finalizeExpungeCommands.size() > 0){ Long hostId = vm.getHostId() != null ? vm.getHostId() : vm.getLastHostId(); @@ -478,6 +482,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac for (Command command : finalizeExpungeCommands) { cmds.addCommand(command); } + if (nicExpungeCommands != null) { + for (Command command : nicExpungeCommands) { + cmds.addCommand(command); + } + } _agentMgr.send(hostId, cmds); if(!cmds.isSuccessful()){ for (Answer answer : cmds.getAnswers()){ @@ -849,7 +858,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } _networkMgr.prepare(vmProfile, dest, ctx); if (vm.getHypervisorType() != HypervisorType.BareMetal) { - this.volumeMgr.prepare(vmProfile, dest); + volumeMgr.prepare(vmProfile, dest); } //since StorageMgr succeeded in volume creation, reuse Volume for further tries until current cluster has capacity if(!reuseVolume){ @@ -972,7 +981,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (startedVm == null) { throw new CloudRuntimeException("Unable to start instance '" + vm.getHostName() - + "' (" + vm.getUuid() + "), see management server log for details"); + + "' (" + vm.getUuid() + "), see management server log for details"); } return startedVm; @@ -1071,7 +1080,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.warn("Unable to release some network resources.", e); } - this.volumeMgr.release(profile); + volumeMgr.release(profile); s_logger.debug("Successfully cleanued up resources for the vm " + vm + " in " + state + " state"); return true; } @@ -1231,7 +1240,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac try { if (vm.getHypervisorType() != HypervisorType.BareMetal) { - this.volumeMgr.release(profile); + volumeMgr.release(profile); s_logger.debug("Successfully released storage resources for the vm " + vm); } } catch (Exception e) { @@ -1350,7 +1359,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); boolean migrationResult = false; try { - migrationResult = this.volumeMgr.storageMigration(profile, destPool); + migrationResult = volumeMgr.storageMigration(profile, destPool); if (migrationResult) { //if the vm is migrated to different pod in basic mode, need to reallocate ip @@ -1437,10 +1446,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac for(NicProfile nic: _networkMgr.getNicProfiles(vm)){ vmSrc.addNic(nic); } - + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); _networkMgr.prepareNicForMigration(profile, dest); - this.volumeMgr.prepareForMigration(profile, dest); + volumeMgr.prepareForMigration(profile, dest); VirtualMachineTO to = toVmTO(profile); PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to); @@ -1675,7 +1684,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } _networkMgr.prepareNicForMigration(profile, destination); - this.volumeMgr.prepareForMigration(profile, destination); + volumeMgr.prepareForMigration(profile, destination); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType()); VirtualMachineTO to = hvGuru.implement(profile); @@ -1692,7 +1701,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac boolean migrated = false; try { // Migrate the vm and its volume. - this.volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPool); + volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPool); // Put the vm back to running state. moveVmOutofMigratingStateOnSuccess(vm, destHost.getId(), work); @@ -2105,7 +2114,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } if ((info == null && (vm.getState() == State.Running || vm.getState() == State.Starting )) - || (info != null && (info.state == State.Running && vm.getState() == State.Starting))) + || (info != null && (info.state == State.Running && vm.getState() == State.Starting))) { s_logger.info("Found vm " + vm.getInstanceName() + " in inconsistent state. " + vm.getState() + " on CS while " + (info == null ? "Stopped" : "Running") + " on agent"); info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped); @@ -2625,7 +2634,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac StartupRoutingCommand startup = (StartupRoutingCommand) cmd; HashMap> allStates = startup.getClusterVMStateChanges(); if (allStates != null){ - this.fullSync(clusterId, allStates); + fullSync(clusterId, allStates); } // initiate the cron job @@ -2713,7 +2722,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac this.state = state; this.vm = vm; this.guru = (VirtualMachineGuru) guru; - this.hostUuid = host; + hostUuid = host; } public AgentVmInfo(String name, VirtualMachineGuru guru, VMInstanceVO vm, State state) { @@ -2846,7 +2855,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac VirtualMachineGuru vmGuru = getVmGuru(vmVO); s_logger.debug("Plugging nic for vm " + vm + " in network " + network); - + boolean result = false; try{ result = vmGuru.plugNic(network, nicTO, vmTO, context, dest); @@ -2856,17 +2865,17 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac // insert nic's Id into DB as resource_name UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmVO.getAccountId(), vmVO.getDataCenterId(), vmVO.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), - null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid()); + null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid()); return nic; } else { s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network); return null; - } + } }finally{ if(!result){ _networkMgr.removeNic(vmProfile, _nicsDao.findById(nic.getId())); } - } + } } else if (vm.getState() == State.Stopped) { //1) allocate nic return _networkMgr.createNicForVm(network, requested, context, vmProfile, false); @@ -2907,10 +2916,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.warn("Failed to remove nic from " + vm + " in " + network + ", nic is default."); throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default."); } - + // if specified nic is associated with PF/LB/Static NAT if(rulesMgr.listAssociatedRulesForGuestNic(nic).size() > 0){ - throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic has associated Port forwarding or Load balancer or Static NAT rules."); } @@ -2928,7 +2937,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network ); long isDefault = (nic.isDefaultNic()) ? 1 : 0; UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), - vm.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null, + vm.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); } else { s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network); @@ -3081,160 +3090,160 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } - @Override - public T migrateForScale(T vm, long srcHostId, DeployDestination dest, Long oldSvcOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, - VirtualMachineMigrationException { - s_logger.info("Migrating " + vm + " to " + dest); + @Override + public T migrateForScale(T vm, long srcHostId, DeployDestination dest, Long oldSvcOfferingId) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, + VirtualMachineMigrationException { + s_logger.info("Migrating " + vm + " to " + dest); - Long newSvcOfferingId = vm.getServiceOfferingId(); - long dstHostId = dest.getHost().getId(); - Host fromHost = _hostDao.findById(srcHostId); - if (fromHost == null) { - s_logger.info("Unable to find the host to migrate from: " + srcHostId); - throw new CloudRuntimeException("Unable to find the host to migrate from: " + srcHostId); + vm.getServiceOfferingId(); + long dstHostId = dest.getHost().getId(); + Host fromHost = _hostDao.findById(srcHostId); + if (fromHost == null) { + s_logger.info("Unable to find the host to migrate from: " + srcHostId); + throw new CloudRuntimeException("Unable to find the host to migrate from: " + srcHostId); + } + + if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) { + s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId()); + throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId()); + } + + VirtualMachineGuru vmGuru = getVmGuru(vm); + + long vmId = vm.getId(); + vm = vmGuru.findById(vmId); + if (vm == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Unable to find the vm " + vm); } + throw new ManagementServerException("Unable to find a virtual machine with id " + vmId); + } - if (fromHost.getClusterId().longValue() != dest.getCluster().getId()) { - s_logger.info("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId()); - throw new CloudRuntimeException("Source and destination host are not in same cluster, unable to migrate to host: " + dest.getHost().getId()); + if (vm.getState() != State.Running) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("VM is not Running, unable to migrate the vm " + vm); } + throw new VirtualMachineMigrationException("VM is not Running, unable to migrate the vm currently " + vm + " , current state: " + vm.getState().toString()); + } - VirtualMachineGuru vmGuru = getVmGuru(vm); + short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE; + if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) { + alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER_MIGRATE; + } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) { + alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE; + } - long vmId = vm.getId(); - vm = vmGuru.findById(vmId); - if (vm == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Unable to find the vm " + vm); - } - throw new ManagementServerException("Unable to find a virtual machine with id " + vmId); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + _networkMgr.prepareNicForMigration(profile, dest); + volumeMgr.prepareForMigration(profile, dest); + + VirtualMachineTO to = toVmTO(profile); + PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to); + + ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId()); + work.setStep(Step.Prepare); + work.setResourceType(ItWorkVO.ResourceType.Host); + work.setResourceId(dstHostId); + work = _workDao.persist(work); + + PrepareForMigrationAnswer pfma = null; + try { + pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc); + if (!pfma.getResult()) { + String msg = "Unable to prepare for migration due to " + pfma.getDetails(); + pfma = null; + throw new AgentUnavailableException(msg, dstHostId); } - - if (vm.getState() != State.Running) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("VM is not Running, unable to migrate the vm " + vm); - } - throw new VirtualMachineMigrationException("VM is not Running, unable to migrate the vm currently " + vm + " , current state: " + vm.getState().toString()); - } - - short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE; - if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) { - alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER_MIGRATE; - } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) { - alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE; - } - - VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); - _networkMgr.prepareNicForMigration(profile, dest); - this.volumeMgr.prepareForMigration(profile, dest); - - VirtualMachineTO to = toVmTO(profile); - PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(to); - - ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId()); - work.setStep(Step.Prepare); - work.setResourceType(ItWorkVO.ResourceType.Host); - work.setResourceId(dstHostId); - work = _workDao.persist(work); - - PrepareForMigrationAnswer pfma = null; - try { - pfma = (PrepareForMigrationAnswer) _agentMgr.send(dstHostId, pfmc); - if (!pfma.getResult()) { - String msg = "Unable to prepare for migration due to " + pfma.getDetails(); - pfma = null; - throw new AgentUnavailableException(msg, dstHostId); - } - } catch (OperationTimedoutException e1) { - throw new AgentUnavailableException("Operation timed out", dstHostId); - } finally { - if (pfma == null) { - work.setStep(Step.Done); - _workDao.update(work.getId(), work); - } - } - - vm.setLastHostId(srcHostId); - try { - if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) { - s_logger.info("Migration cancelled because state has changed: " + vm); - throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm); - } - } catch (NoTransitionException e1) { - s_logger.info("Migration cancelled because " + e1.getMessage()); - throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage()); - } - - boolean migrated = false; - try { - boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows"); - MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows); - mc.setHostGuid(dest.getHost().getGuid()); - - try { - MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc); - if (!ma.getResult()) { - s_logger.error("Unable to migrate due to " + ma.getDetails()); - return null; - } - } catch (OperationTimedoutException e) { - if (e.isActive()) { - s_logger.warn("Active migration command so scheduling a restart for " + vm); - _haMgr.scheduleRestart(vm, true); - } - throw new AgentUnavailableException("Operation timed out on migrating " + vm, dstHostId); - } - - try { - long newServiceOfferingId = vm.getServiceOfferingId(); - vm.setServiceOfferingId(oldSvcOfferingId); // release capacity for the old service offering only - if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) { - throw new ConcurrentOperationException("Unable to change the state for " + vm); - } - vm.setServiceOfferingId(newServiceOfferingId); - } catch (NoTransitionException e1) { - throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage()); - } - - try { - if (!checkVmOnHost(vm, dstHostId)) { - s_logger.error("Unable to complete migration for " + vm); - try { - _agentMgr.send(srcHostId, new Commands(cleanup(vm.getInstanceName())), null); - } catch (AgentUnavailableException e) { - s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId); - } - cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); - return null; - } - } catch (OperationTimedoutException e) { - } - - migrated = true; - return vm; - } finally { - if (!migrated) { - s_logger.info("Migration was unsuccessful. Cleaning up: " + vm); - - _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone " - + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed. Please check logs."); - try { - _agentMgr.send(dstHostId, new Commands(cleanup(vm.getInstanceName())), null); - } catch (AgentUnavailableException ae) { - s_logger.info("Looks like the destination Host is unavailable for cleanup"); - } - - try { - stateTransitTo(vm, Event.OperationFailed, srcHostId); - } catch (NoTransitionException e) { - s_logger.warn(e.getMessage()); - } - } - + } catch (OperationTimedoutException e1) { + throw new AgentUnavailableException("Operation timed out", dstHostId); + } finally { + if (pfma == null) { work.setStep(Step.Done); _workDao.update(work.getId(), work); } } + + vm.setLastHostId(srcHostId); + try { + if (vm == null || vm.getHostId() == null || vm.getHostId() != srcHostId || !changeState(vm, Event.MigrationRequested, dstHostId, work, Step.Migrating)) { + s_logger.info("Migration cancelled because state has changed: " + vm); + throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm); + } + } catch (NoTransitionException e1) { + s_logger.info("Migration cancelled because " + e1.getMessage()); + throw new ConcurrentOperationException("Migration cancelled because " + e1.getMessage()); + } + + boolean migrated = false; + try { + boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows"); + MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows); + mc.setHostGuid(dest.getHost().getGuid()); + + try { + MigrateAnswer ma = (MigrateAnswer) _agentMgr.send(vm.getLastHostId(), mc); + if (!ma.getResult()) { + s_logger.error("Unable to migrate due to " + ma.getDetails()); + return null; + } + } catch (OperationTimedoutException e) { + if (e.isActive()) { + s_logger.warn("Active migration command so scheduling a restart for " + vm); + _haMgr.scheduleRestart(vm, true); + } + throw new AgentUnavailableException("Operation timed out on migrating " + vm, dstHostId); + } + + try { + long newServiceOfferingId = vm.getServiceOfferingId(); + vm.setServiceOfferingId(oldSvcOfferingId); // release capacity for the old service offering only + if (!changeState(vm, VirtualMachine.Event.OperationSucceeded, dstHostId, work, Step.Started)) { + throw new ConcurrentOperationException("Unable to change the state for " + vm); + } + vm.setServiceOfferingId(newServiceOfferingId); + } catch (NoTransitionException e1) { + throw new ConcurrentOperationException("Unable to change state due to " + e1.getMessage()); + } + + try { + if (!checkVmOnHost(vm, dstHostId)) { + s_logger.error("Unable to complete migration for " + vm); + try { + _agentMgr.send(srcHostId, new Commands(cleanup(vm.getInstanceName())), null); + } catch (AgentUnavailableException e) { + s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId); + } + cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + return null; + } + } catch (OperationTimedoutException e) { + } + + migrated = true; + return vm; + } finally { + if (!migrated) { + s_logger.info("Migration was unsuccessful. Cleaning up: " + vm); + + _alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone " + + dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed. Please check logs."); + try { + _agentMgr.send(dstHostId, new Commands(cleanup(vm.getInstanceName())), null); + } catch (AgentUnavailableException ae) { + s_logger.info("Looks like the destination Host is unavailable for cleanup"); + } + + try { + stateTransitTo(vm, Event.OperationFailed, srcHostId); + } catch (NoTransitionException e) { + s_logger.warn(e.getMessage()); + } + } + + work.setStep(Step.Done); + _workDao.update(work.getId(), work); + } + } @Override public VMInstanceVO reConfigureVm(VMInstanceVO vm , ServiceOffering oldServiceOffering, boolean reconfiguringOnExistingHost) throws ResourceUnavailableException, ConcurrentOperationException { @@ -3283,7 +3292,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } catch (AgentUnavailableException e) { throw e; } finally{ - // work.setStep(Step.Done); + // work.setStep(Step.Done); //_workDao.update(work.getId(), work); if(!success){ _capacityMgr.releaseVmCapacity(vm, false, false, vm.getHostId()); // release the new capacity @@ -3297,4 +3306,4 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } - } +}