diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java index 4ee61366ece..443751946aa 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java @@ -10,8 +10,8 @@ // limitations under the License. // // Automatically generated by addcopyright.py at 04/03/2012 -package com.cloud.hypervisor.vmware.mo; - +package com.cloud.hypervisor.vmware.mo; + import java.io.File; import java.net.URI; import java.net.URISyntaxException; @@ -26,6 +26,8 @@ import com.cloud.hypervisor.vmware.util.VmwareHelper; import com.cloud.utils.ActionDelegate; import com.cloud.utils.Pair; import com.cloud.utils.cisco.n1kv.vsm.NetconfHelper; +import com.cloud.utils.cisco.n1kv.vsm.PolicyMap; +import com.cloud.utils.cisco.n1kv.vsm.PortProfile; import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.BindingType; import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.OperationType; import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.PortProfileType; @@ -59,7 +61,8 @@ import com.vmware.vim25.VirtualSCSISharing; public class HypervisorHostHelper { private static final Logger s_logger = Logger.getLogger(HypervisorHostHelper.class); - private static final int DEFAULT_LOCK_TIMEOUT_SECONDS = 600; + private static final int DEFAULT_LOCK_TIMEOUT_SECONDS = 600; + private static final String s_policyNamePrefix = "cloud.policy."; // make vmware-base loosely coupled with cloud-specific stuff, duplicate VLAN.UNTAGGED constant here private static final String UNTAGGED_VLAN_NAME = "untagged"; @@ -109,7 +112,7 @@ public class HypervisorHostHelper { return "cloud.public." + vlanId; } } - + public static String composeCloudNetworkName(String prefix, String vlanId, Integer networkRateMbps, String vSwitchName) { StringBuffer sb = new StringBuffer(prefix); if(vlanId == null || UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId)) @@ -129,43 +132,71 @@ public class HypervisorHostHelper { public static Map getValidatedVsmCredentials(VmwareContext context) throws Exception { Map vsmCredentials = context.getStockObject("vsmcredentials"); - String msg; - if(vsmCredentials == null || vsmCredentials.size() != 3) { - msg = "Failed to retrieve required credentials of Nexus VSM from database."; - s_logger.error(msg); + String msg; + if (vsmCredentials == null || vsmCredentials.size() != 3) { + msg = "Failed to retrieve required credentials of Nexus VSM from database."; + s_logger.error(msg); throw new Exception(msg); - } - - String vsmIp = vsmCredentials.containsKey("vsmip") ? vsmCredentials.get("vsmip") : null; - String vsmUserName = vsmCredentials.containsKey("vsmusername") ? vsmCredentials.get("vsmusername") : null; - String vsmPassword = vsmCredentials.containsKey("vsmpassword") ? vsmCredentials.get("vsmpassword") : null; - if(vsmIp == null || vsmIp.isEmpty() || vsmUserName == null || vsmUserName.isEmpty() || vsmPassword == null || vsmPassword.isEmpty()) { - msg = "Detected invalid credentials for Nexus VSM"; - s_logger.error(msg); - throw new Exception(msg); - } - return vsmCredentials; - } - - public static void createPortProfile(VmwareContext context, String ethPortProfileName, String networkName, Integer vlanId, Integer networkRateMbps) throws Exception { - Map vsmCredentials = getValidatedVsmCredentials(context); - String vsmIp = vsmCredentials.get("vsmip"); - String vsmUserName = vsmCredentials.get("vsmusername"); - String vsmPassword = vsmCredentials.get("vsmpassword"); - String msg; - - NetconfHelper netconfClient; - try { - s_logger.info("Connecting to Nexus VSM : " + vsmIp); - netconfClient = new NetconfHelper(vsmIp, vsmUserName, vsmPassword); - s_logger.info("Successfully connected to Nexus VSM : " + vsmIp); - } catch(CloudRuntimeException e) { - msg = "Failed to connect to Nexus VSM " + vsmIp + " with credentials of user " + vsmUserName; - s_logger.error(msg); - throw new CloudRuntimeException(msg); } - List> params = new ArrayList>(); + String vsmIp = vsmCredentials.containsKey("vsmip") ? vsmCredentials.get("vsmip") : null; + String vsmUserName = vsmCredentials.containsKey("vsmusername") ? vsmCredentials.get("vsmusername") : null; + String vsmPassword = vsmCredentials.containsKey("vsmpassword") ? vsmCredentials.get("vsmpassword") : null; + if (vsmIp == null || vsmIp.isEmpty() || vsmUserName == null || vsmUserName.isEmpty() || vsmPassword == null + || vsmPassword.isEmpty()) { + msg = "Detected invalid credentials for Nexus 1000v."; + s_logger.error(msg); + throw new Exception(msg); + } + return vsmCredentials; + } + + public static void createPortProfile(VmwareContext context, String ethPortProfileName, String networkName, + Integer vlanId, Integer networkRateMbps, long peakBandwidth, long burstSize) throws Exception { + Map vsmCredentials = getValidatedVsmCredentials(context); + String vsmIp = vsmCredentials.get("vsmip"); + String vsmUserName = vsmCredentials.get("vsmusername"); + String vsmPassword = vsmCredentials.get("vsmpassword"); + String msg; + + NetconfHelper netconfClient; + try { + s_logger.info("Connecting to Nexus 1000v: " + vsmIp); + netconfClient = new NetconfHelper(vsmIp, vsmUserName, vsmPassword); + s_logger.info("Successfully connected to Nexus 1000v : " + vsmIp); + } catch (CloudRuntimeException e) { + msg = "Failed to connect to Nexus 1000v " + vsmIp + " with credentials of user " + vsmUserName + + ". Exception: " + e.toString(); + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } + + String policyName = s_policyNamePrefix; + int averageBandwidth = 0; + if (networkRateMbps != null) { + averageBandwidth = networkRateMbps.intValue(); + policyName += averageBandwidth; + } + + try { + // TODO(sateesh): Change the type of peakBandwidth & burstRate in + // PolicyMap to long. + if (averageBandwidth > 0) { + s_logger.debug("Adding policy map " + policyName); + netconfClient.addPolicyMap(policyName, averageBandwidth, (int) peakBandwidth, (int) burstSize); + } + } catch (CloudRuntimeException e) { + msg = "Failed to add policy map of " + policyName + " with parameters " + "committed rate = " + + averageBandwidth + "peak bandwidth = " + peakBandwidth + "burst size = " + burstSize + + ". Exception: " + e.toString(); + s_logger.error(msg); + if (netconfClient != null) { + netconfClient.disconnect(); + s_logger.debug("Disconnected Nexus 1000v session."); + } + } + + List> params = new ArrayList>(); if (vlanId != null) { // No need to update ethernet port profile for untagged vlans params.add(new Pair(OperationType.addvlanid, vlanId.toString())); @@ -174,17 +205,17 @@ public class HypervisorHostHelper { netconfClient.updatePortProfile(ethPortProfileName, SwitchPortMode.trunk, params); s_logger.info("Added " + vlanId + " to Ethernet port profile " + ethPortProfileName); } catch (CloudRuntimeException e) { - msg = "Failed to modify ethernet port profile " + ethPortProfileName + " with parameters " + params.toString(); + msg = "Failed to update Ethernet port profile " + ethPortProfileName + " with VLAN " + vlanId + + ". Exception: " + e.toString(); s_logger.error(msg); if(netconfClient != null) { netconfClient.disconnect(); - s_logger.debug("Disconnected VSM session."); + s_logger.debug("Disconnected Nexus 1000v session."); } - throw new CloudRuntimeException(msg); } } - - try { + + try { if (vlanId == null) { s_logger.info("Adding port profile configured over untagged VLAN."); netconfClient.addPortProfile(networkName, PortProfileType.vethernet, BindingType.portbindingstatic, SwitchPortMode.access, 0); @@ -192,61 +223,150 @@ public class HypervisorHostHelper { s_logger.info("Adding port profile configured over VLAN : " + vlanId.toString()); netconfClient.addPortProfile(networkName, PortProfileType.vethernet, BindingType.portbindingstatic, SwitchPortMode.access, vlanId.intValue()); } - } catch (CloudRuntimeException e) { - msg = "Failed to add vEthernet port profile " + networkName + ". Exception: " + e.toString(); - s_logger.error(msg); - if(vlanId == null) { - s_logger.warn("Ignoring exception : " + e.toString()); - // throw new CloudRuntimeException(msg); - } - } finally { - if(netconfClient != null) { - netconfClient.disconnect(); - s_logger.debug("Disconnected VSM session."); - } - } - } - - public static void updatePortProfile(VmwareContext context, String ethPortProfileName, Integer vlanId, Integer networkRateMbps) throws Exception { + msg = "Failed to add vEthernet port profile " + networkName + "." + ". Exception: " + e.toString(); + s_logger.error(msg); + if(netconfClient != null) { + netconfClient.disconnect(); + s_logger.debug("Disconnected Nexus 1000v session."); + } + } + + try { + if (averageBandwidth > 0) { + s_logger.info("Associating policy map " + policyName + " with port profile " + networkName + "."); + netconfClient.attachServicePolicy(policyName, networkName); + } + } + catch(CloudRuntimeException e) { + msg = "Failed to associate policy map " + policyName + " with port profile " + networkName + + ". Exception: " + e.toString(); + s_logger.error(msg); + } finally { + if (netconfClient != null) { + netconfClient.disconnect(); + s_logger.debug("Disconnected Nexus 1000v session."); + } + } + } + + public static void updatePortProfile(VmwareContext context, String ethPortProfileName, String vethPortProfileName, + Integer vlanId, Integer networkRateMbps, long peakBandwidth, long burstRate) throws Exception { + NetconfHelper netconfClient = null; + Map vsmCredentials = getValidatedVsmCredentials(context); + String vsmIp = vsmCredentials.get("vsmip"); + String vsmUserName = vsmCredentials.get("vsmusername"); + String vsmPassword = vsmCredentials.get("vsmpassword"); + + String msg; + try { + netconfClient = new NetconfHelper(vsmIp, vsmUserName, vsmPassword); + } catch (CloudRuntimeException e) { + msg = "Failed to connect to Nexus 1000v " + vsmIp + " with credentials of user " + vsmUserName + + ". Exception: " + e.toString(); + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } + + PortProfile portProfile = netconfClient.getPortProfileByName(vethPortProfileName); + int averageBandwidth = 0; + String policyName = s_policyNamePrefix; + if (networkRateMbps != null) { + averageBandwidth = networkRateMbps.intValue(); + policyName += averageBandwidth; + } + + if (averageBandwidth > 0) { + PolicyMap policyMap = netconfClient.getPolicyMapByName(portProfile.inputPolicyMap); + if (policyMap.committedRate == averageBandwidth && policyMap.peakRate == peakBandwidth + && policyMap.burstRate == burstRate) { + s_logger.debug("Detected that policy map is already applied to port profile " + vethPortProfileName); + if (netconfClient != null) { + netconfClient.disconnect(); + s_logger.debug("Disconnected Nexus 1000v session."); + } + return; + } else { + try { + // TODO(sateesh): Change the type of peakBandwidth & + // burstRate in PolicyMap to long. + s_logger.info("Adding policy map " + policyName); + netconfClient.addPolicyMap(policyName, averageBandwidth, (int) peakBandwidth, (int) burstRate); + } catch (CloudRuntimeException e) { + msg = "Failed to add policy map of " + policyName + " with parameters " + "committed rate = " + + averageBandwidth + "peak bandwidth = " + peakBandwidth + "burst size = " + burstRate + + ". Exception: " + e.toString(); + s_logger.error(msg); + if (netconfClient != null) { + netconfClient.disconnect(); + s_logger.debug("Disconnected Nexus 1000v session."); + } + } + + try { + s_logger.info("Associating policy map " + policyName + " with port profile " + vethPortProfileName + + "."); + netconfClient.attachServicePolicy(policyName, vethPortProfileName); + } catch (CloudRuntimeException e) { + msg = "Failed to associate policy map " + policyName + " with port profile " + vethPortProfileName + + ". Exception: " + e.toString(); + s_logger.error(msg); + if (netconfClient != null) { + netconfClient.disconnect(); + s_logger.debug("Disconnected Nexus 1000v session."); + } + } + } + } + if (vlanId == null) { - s_logger.info("Skipping update operation over ethernet port profile " + ethPortProfileName + " for untagged VLAN."); + s_logger.info("Skipping update operation over ethernet port profile " + ethPortProfileName + + " for untagged VLAN."); + if (netconfClient != null) { + netconfClient.disconnect(); + s_logger.debug("Disconnected Nexus 1000v session."); + } return; } - s_logger.info("Updating vEthernet port profile with VLAN " + vlanId); - Map vsmCredentials = getValidatedVsmCredentials(context); - String vsmIp = vsmCredentials.get("vsmip"); - String vsmUserName = vsmCredentials.get("vsmusername"); - String vsmPassword = vsmCredentials.get("vsmpassword"); - String msg; - - NetconfHelper netconfClient; - try { - netconfClient = new NetconfHelper(vsmIp, vsmUserName, vsmPassword); - } catch(CloudRuntimeException e) { - msg = "Failed to connect to Nexus VSM " + vsmIp + " with credentials of user " + vsmUserName; - s_logger.error(msg); - throw new CloudRuntimeException(msg); - } - - List> params = new ArrayList>(); - params.add(new Pair(OperationType.addvlanid, vlanId.toString())); - - try { - netconfClient.updatePortProfile(ethPortProfileName, SwitchPortMode.trunk, params); - } catch(CloudRuntimeException e) { - msg = "Failed to modify ethernet port profile " + ethPortProfileName + " with parameters " + params.toString(); - s_logger.error(msg); - throw new CloudRuntimeException(msg); - } finally { - if(netconfClient != null) { - netconfClient.disconnect(); - s_logger.debug("Disconnected VSM session."); - } - } - } - + String currentVlan = portProfile.vlan; + String newVlan = Integer.toString(vlanId.intValue()); + if (currentVlan.equalsIgnoreCase(newVlan)) { + if (netconfClient != null) { + netconfClient.disconnect(); + s_logger.debug("Disconnected Nexus 1000v session."); + } + return; + } + + List> params = new ArrayList>(); + params.add(new Pair(OperationType.addvlanid, newVlan)); + try { + s_logger.info("Updating vEthernet port profile with VLAN " + vlanId.toString()); + netconfClient.updatePortProfile(ethPortProfileName, SwitchPortMode.trunk, params); + } catch (CloudRuntimeException e) { + msg = "Failed to update ethernet port profile " + ethPortProfileName + " with parameters " + + params.toString() + ". Exception: " + e.toString(); + s_logger.error(msg); + if (netconfClient != null) { + netconfClient.disconnect(); + s_logger.debug("Disconnected Nexus 1000v session."); + } + } + + try { + netconfClient.updatePortProfile(vethPortProfileName, SwitchPortMode.access, params); + } catch (CloudRuntimeException e) { + msg = "Failed to update vEthernet port profile " + vethPortProfileName + " with parameters " + + params.toString() + ". Exception: " + e.toString(); + s_logger.error(msg); + if (netconfClient != null) { + netconfClient.disconnect(); + s_logger.debug("Disconnected Nexus 1000v session."); + } + } + } + /** * @param ethPortProfileName * @param namePrefix @@ -258,15 +378,16 @@ public class HypervisorHostHelper { * @return * @throws Exception */ - public static Pair prepareNetwork(String ethPortProfileName, String namePrefix, - HostMO hostMo, String vlanId, Integer networkRateMbps, Integer networkRateMulticastMbps, - long timeOutMs) throws Exception { - ManagedObjectReference morNetwork = null; - VmwareContext context = hostMo.getContext(); - ManagedObjectReference dcMor = hostMo.getHyperHostDatacenter(); - DatacenterMO dataCenterMo = new DatacenterMO(context, dcMor); - ManagedObjectReference morEthernetPortProfile = dataCenterMo.getDvPortGroupMor(ethPortProfileName); + public static Pair prepareNetwork(String ethPortProfileName, String namePrefix, + HostMO hostMo, String vlanId, Integer networkRateMbps, Integer networkRateMulticastMbps, long timeOutMs) + throws Exception { + ManagedObjectReference morNetwork = null; + VmwareContext context = hostMo.getContext(); + ManagedObjectReference dcMor = hostMo.getHyperHostDatacenter(); + DatacenterMO dataCenterMo = new DatacenterMO(context, dcMor); + + ManagedObjectReference morEthernetPortProfile = dataCenterMo.getDvPortGroupMor(ethPortProfileName); if (morEthernetPortProfile == null) { String msg = "Unable to find Ethernet port profile " + ethPortProfileName; @@ -274,7 +395,7 @@ public class HypervisorHostHelper { throw new Exception(msg); } else { - s_logger.info("Found Ethernet port profile " + ethPortProfileName); + s_logger.info("Found Ethernet port profile " + ethPortProfileName); } boolean createGCTag = false; @@ -285,63 +406,53 @@ public class HypervisorHostHelper { createGCTag = true; vid = Integer.parseInt(vlanId); } - - networkName = composeCloudNetworkName(namePrefix, vlanId, networkRateMbps, ethPortProfileName); + + networkName = composeCloudNetworkName(namePrefix, vlanId, networkRateMbps, ethPortProfileName); // TODO(sateesh): Enable this for VMware DVS. - /*DVSTrafficShapingPolicy shapingPolicy = null; - if(networkRateMbps != null && networkRateMbps.intValue() > 0) { - shapingPolicy = new DVSTrafficShapingPolicy(); - BoolPolicy isEnabled = new BoolPolicy(); - LongPolicy averageBandwidth = new LongPolicy(); - LongPolicy peakBandwidth = new LongPolicy(); - LongPolicy burstSize = new LongPolicy(); - - isEnabled.setValue(true); - averageBandwidth.setValue((long)networkRateMbps.intValue()*1024L*1024L); - // We chose 50% higher allocation than average bandwidth. - // TODO(sateesh): Also let user specify the peak coefficient - peakBandwidth.setValue((long)(averageBandwidth.getValue()*1.5)); - // TODO(sateesh): Also let user specify the burst coefficient - burstSize.setValue((long)(5*averageBandwidth.getValue()/8)); - - shapingPolicy.setEnabled(isEnabled); - shapingPolicy.setAverageBandwidth(averageBandwidth); - shapingPolicy.setPeakBandwidth(peakBandwidth); - shapingPolicy.setBurstSize(burstSize); - } - DVPortgroupConfigInfo spec = dataCenterMo.getDvPortGroupSpec(networkName);*/ +// DVSTrafficShapingPolicy shapingPolicy = null; +// if (networkRateMbps != null && networkRateMbps.intValue() > 0) { +// shapingPolicy = new DVSTrafficShapingPolicy(); +// BoolPolicy isEnabled = new BoolPolicy(); +// LongPolicy averageBandwidth = new LongPolicy(); +// LongPolicy peakBandwidth = new LongPolicy(); +// LongPolicy burstSize = new LongPolicy(); +// +// isEnabled.setValue(true); +// averageBandwidth.setValue((long) networkRateMbps.intValue() * 1024L * 1024L); +// // We chose 50% higher allocation than average bandwidth. +// // TODO(sateesh): Also let user specify the peak coefficient +// peakBandwidth.setValue((long) (averageBandwidth.getValue() * 1.5)); +// // TODO(sateesh): Also let user specify the burst coefficient +// burstSize.setValue((long) (5 * averageBandwidth.getValue() / 8)); +// +// shapingPolicy.setEnabled(isEnabled); +// shapingPolicy.setAverageBandwidth(averageBandwidth); +// shapingPolicy.setPeakBandwidth(peakBandwidth); +// shapingPolicy.setBurstSize(burstSize); +// } + DVPortgroupConfigInfo spec = dataCenterMo.getDvPortGroupSpec(networkName); long averageBandwidth = 0L; if (networkRateMbps != null && networkRateMbps.intValue() > 0) { averageBandwidth = (long) (networkRateMbps.intValue() * 1024L * 1024L); } - //We chose 50% higher allocation than average bandwidth. - //TODO(sateesh): Also let user specify the peak coefficient + // We chose 50% higher allocation than average bandwidth. + // TODO(sateesh): Also let user specify the peak coefficient long peakBandwidth = (long) (averageBandwidth * 1.5); - //TODO(sateesh): Also let user specify the burst coefficient - long burstSize = 5 * averageBandwidth / 8; - - boolean bWaitPortGroupReady = false; + // TODO(sateesh): Also let user specify the burst coefficient + long burstSize = 5 * averageBandwidth / 8; + + boolean bWaitPortGroupReady = false; if (!dataCenterMo.hasDvPortGroup(networkName)) { s_logger.info("Port profile " + networkName + " not found."); - createPortProfile(context, ethPortProfileName, networkName, vid, networkRateMbps); + createPortProfile(context, ethPortProfileName, networkName, vid, networkRateMbps, peakBandwidth, burstSize); bWaitPortGroupReady = true; } else { s_logger.info("Port profile " + networkName + " found."); - updatePortProfile(context, ethPortProfileName, vid, networkRateMbps); bWaitPortGroupReady = true; - // TODO(sateesh): Enable port profile policy configuration - // PortProfile portProfile; - // try { - // portProfile = getPortProfileByName(networkName); - // if (portProfile.vlanId != vlanId || - // portProfile.policy.getAverageBandwidth() != averageBandwidth || - // portProfile.policy.getPeakBandwidth() != peakBandwidth || - // portProfile.policy.getBurstRate() != burstRate) { - // updatePortProfile(context, ethPortProfileName, vlanId, averageBandwidth, peakBandwidth, burstSize); - // } + updatePortProfile(context, ethPortProfileName, networkName, vid, networkRateMbps, peakBandwidth, burstSize); } - //Wait for dvPortGroup on vCenter + // Wait for dvPortGroup on vCenter if(bWaitPortGroupReady) morNetwork = waitForDvPortGroupReady(dataCenterMo, networkName, timeOutMs); else @@ -357,10 +468,10 @@ public class HypervisorHostHelper { networkMo.setCustomFieldValue(CustomFieldConstants.CLOUD_GC_DVP, "true"); s_logger.debug("Added custom field : " + CustomFieldConstants.CLOUD_GC_DVP); } - - return new Pair(morNetwork, networkName); - } - + + return new Pair(morNetwork, networkName); + } + private static ManagedObjectReference waitForDvPortGroupReady( DatacenterMO dataCenterMo, String dvPortGroupName, long timeOutMs) throws Exception { ManagedObjectReference morDvPortGroup = null; @@ -380,8 +491,8 @@ public class HypervisorHostHelper { return morDvPortGroup; } - private static boolean isSpecMatch(DVPortgroupConfigInfo spec, Integer vid, - DVSTrafficShapingPolicy shapingPolicy) { + // This method would be used for VMware Distributed Virtual Switch. + private static boolean isSpecMatch(DVPortgroupConfigInfo spec, Integer vid, DVSTrafficShapingPolicy shapingPolicy) { DVSTrafficShapingPolicy currentTrafficShapingPolicy; currentTrafficShapingPolicy = spec.getDefaultPortConfig().getInShapingPolicy(); // TODO(sateesh): Extract and compare vendor specific configuration specification as well. @@ -561,222 +672,222 @@ public class HypervisorHostHelper { return true; } - - public static ManagedObjectReference waitForNetworkReady(HostMO hostMo, - String networkName, long timeOutMs) throws Exception { - - ManagedObjectReference morNetwork = null; - - // if portGroup is just created, getNetwork may fail to retrieve it, we - // need to retry - long startTick = System.currentTimeMillis(); - while (System.currentTimeMillis() - startTick <= timeOutMs) { - morNetwork = hostMo.getNetworkMor(networkName); - if (morNetwork != null) { - break; - } - - s_logger.info("Waiting for network " + networkName + " to be ready"); - Thread.sleep(1000); - } - - return morNetwork; - } - - public static boolean createBlankVm(VmwareHypervisorHost host, String vmName, - int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB, int memoryReserveMB, String guestOsIdentifier, - ManagedObjectReference morDs, boolean snapshotDirToParent) throws Exception { - - if(s_logger.isInfoEnabled()) - s_logger.info("Create blank VM. cpuCount: " + cpuCount + ", cpuSpeed(MHz): " + cpuSpeedMHz + ", mem(Mb): " + memoryMB); - - // VM config basics - VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec(); - vmConfig.setName(vmName); - VmwareHelper.setBasicVmConfig(vmConfig, cpuCount, cpuSpeedMHz, cpuReservedMHz, memoryMB, memoryReserveMB, guestOsIdentifier, limitCpuUse); - - // Scsi controller - VirtualLsiLogicController scsiController = new VirtualLsiLogicController(); - scsiController.setSharedBus(VirtualSCSISharing.noSharing); - scsiController.setBusNumber(0); - scsiController.setKey(1); - VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec(); - scsiControllerSpec.setDevice(scsiController); - scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.add); - - VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo(); - DatastoreMO dsMo = new DatastoreMO(host.getContext(), morDs); - fileInfo.setVmPathName(String.format("[%s]", dsMo.getName())); - vmConfig.setFiles(fileInfo); - - VirtualMachineVideoCard videoCard = new VirtualMachineVideoCard(); - videoCard.setControllerKey(100); - videoCard.setUseAutoDetect(true); - - VirtualDeviceConfigSpec videoDeviceSpec = new VirtualDeviceConfigSpec(); - videoDeviceSpec.setDevice(videoCard); - videoDeviceSpec.setOperation(VirtualDeviceConfigSpecOperation.add); - - vmConfig.setDeviceChange(new VirtualDeviceConfigSpec[] { scsiControllerSpec, videoDeviceSpec }); - if(host.createVm(vmConfig)) { - VirtualMachineMO vmMo = host.findVmOnHyperHost(vmName); - assert(vmMo != null); - - int ideControllerKey = -1; - while(ideControllerKey < 0) { - ideControllerKey = vmMo.tryGetIDEDeviceControllerKey(); - if(ideControllerKey >= 0) - break; - - s_logger.info("Waiting for IDE controller be ready in VM: " + vmName); - Thread.sleep(1000); - } - - if(snapshotDirToParent) { - String snapshotDir = String.format("/vmfs/volumes/%s/", dsMo.getName()); - - s_logger.info("Switch snapshot working directory to " + snapshotDir + " for " + vmName); - vmMo.setSnapshotDirectory(snapshotDir); - - // Don't have a good way to test if the VM is really ready for use through normal API after configuration file manipulation, - // delay 3 seconds - Thread.sleep(3000); - } - - s_logger.info("Blank VM: " + vmName + " is ready for use"); - return true; - } - return false; - } - - public static String resolveHostNameInUrl(DatacenterMO dcMo, String url) { - - s_logger.info("Resolving host name in url through vCenter, url: " + url); - - URI uri; - try { - uri = new URI(url); - } catch (URISyntaxException e) { - s_logger.warn("URISyntaxException on url " + url); - return url; - } - - String host = uri.getHost(); - if(NetUtils.isValidIp(host)) { - s_logger.info("host name in url is already in IP address, url: " + url); - return url; - } - - try { - ManagedObjectReference morHost = dcMo.findHost(host); - if(morHost != null) { + + public static ManagedObjectReference waitForNetworkReady(HostMO hostMo, + String networkName, long timeOutMs) throws Exception { + + ManagedObjectReference morNetwork = null; + + // if portGroup is just created, getNetwork may fail to retrieve it, we + // need to retry + long startTick = System.currentTimeMillis(); + while (System.currentTimeMillis() - startTick <= timeOutMs) { + morNetwork = hostMo.getNetworkMor(networkName); + if (morNetwork != null) { + break; + } + + s_logger.info("Waiting for network " + networkName + " to be ready"); + Thread.sleep(1000); + } + + return morNetwork; + } + + public static boolean createBlankVm(VmwareHypervisorHost host, String vmName, + int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB, int memoryReserveMB, String guestOsIdentifier, + ManagedObjectReference morDs, boolean snapshotDirToParent) throws Exception { + + if(s_logger.isInfoEnabled()) + s_logger.info("Create blank VM. cpuCount: " + cpuCount + ", cpuSpeed(MHz): " + cpuSpeedMHz + ", mem(Mb): " + memoryMB); + + // VM config basics + VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec(); + vmConfig.setName(vmName); + VmwareHelper.setBasicVmConfig(vmConfig, cpuCount, cpuSpeedMHz, cpuReservedMHz, memoryMB, memoryReserveMB, guestOsIdentifier, limitCpuUse); + + // Scsi controller + VirtualLsiLogicController scsiController = new VirtualLsiLogicController(); + scsiController.setSharedBus(VirtualSCSISharing.noSharing); + scsiController.setBusNumber(0); + scsiController.setKey(1); + VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec(); + scsiControllerSpec.setDevice(scsiController); + scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.add); + + VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo(); + DatastoreMO dsMo = new DatastoreMO(host.getContext(), morDs); + fileInfo.setVmPathName(String.format("[%s]", dsMo.getName())); + vmConfig.setFiles(fileInfo); + + VirtualMachineVideoCard videoCard = new VirtualMachineVideoCard(); + videoCard.setControllerKey(100); + videoCard.setUseAutoDetect(true); + + VirtualDeviceConfigSpec videoDeviceSpec = new VirtualDeviceConfigSpec(); + videoDeviceSpec.setDevice(videoCard); + videoDeviceSpec.setOperation(VirtualDeviceConfigSpecOperation.add); + + vmConfig.setDeviceChange(new VirtualDeviceConfigSpec[] { scsiControllerSpec, videoDeviceSpec }); + if(host.createVm(vmConfig)) { + VirtualMachineMO vmMo = host.findVmOnHyperHost(vmName); + assert(vmMo != null); + + int ideControllerKey = -1; + while(ideControllerKey < 0) { + ideControllerKey = vmMo.tryGetIDEDeviceControllerKey(); + if(ideControllerKey >= 0) + break; + + s_logger.info("Waiting for IDE controller be ready in VM: " + vmName); + Thread.sleep(1000); + } + + if(snapshotDirToParent) { + String snapshotDir = String.format("/vmfs/volumes/%s/", dsMo.getName()); + + s_logger.info("Switch snapshot working directory to " + snapshotDir + " for " + vmName); + vmMo.setSnapshotDirectory(snapshotDir); + + // Don't have a good way to test if the VM is really ready for use through normal API after configuration file manipulation, + // delay 3 seconds + Thread.sleep(3000); + } + + s_logger.info("Blank VM: " + vmName + " is ready for use"); + return true; + } + return false; + } + + public static String resolveHostNameInUrl(DatacenterMO dcMo, String url) { + + s_logger.info("Resolving host name in url through vCenter, url: " + url); + + URI uri; + try { + uri = new URI(url); + } catch (URISyntaxException e) { + s_logger.warn("URISyntaxException on url " + url); + return url; + } + + String host = uri.getHost(); + if(NetUtils.isValidIp(host)) { + s_logger.info("host name in url is already in IP address, url: " + url); + return url; + } + + try { + ManagedObjectReference morHost = dcMo.findHost(host); + if(morHost != null) { HostMO hostMo = new HostMO(dcMo.getContext(), morHost); String managementPortGroupName; if(hostMo.getHostType() == VmwareHostType.ESXi) managementPortGroupName = (String)dcMo.getContext().getStockObject("manageportgroup"); else managementPortGroupName = (String)dcMo.getContext().getStockObject("serviceconsole"); - - VmwareHypervisorHostNetworkSummary summary = hostMo.getHyperHostNetworkSummary(managementPortGroupName); - if(summary == null) { - s_logger.warn("Unable to resolve host name in url through vSphere, url: " + url); - return url; - } - - String hostIp = summary.getHostIp(); - - try { - URI resolvedUri = new URI(uri.getScheme(), uri.getUserInfo(), hostIp, uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); - - s_logger.info("url " + url + " is resolved to " + resolvedUri.toString() + " through vCenter"); - return resolvedUri.toString(); - } catch (URISyntaxException e) { - assert(false); - return url; - } - } - } catch(Exception e) { - s_logger.warn("Unexpected exception ", e); - } - - return url; - } - - public static void importVmFromOVF(VmwareHypervisorHost host, String ovfFilePath, String vmName, DatastoreMO dsMo, String diskOption, - ManagedObjectReference morRp, ManagedObjectReference morHost) throws Exception { - - assert(morRp != null); - - OvfCreateImportSpecParams importSpecParams = new OvfCreateImportSpecParams(); - importSpecParams.setHostSystem(morHost); - importSpecParams.setLocale("US"); - importSpecParams.setEntityName(vmName); - importSpecParams.setDeploymentOption(""); - importSpecParams.setDiskProvisioning(diskOption); // diskOption: thin, thick, etc - importSpecParams.setPropertyMapping(null); - - String ovfDescriptor = HttpNfcLeaseMO.readOvfContent(ovfFilePath); - VmwareContext context = host.getContext(); - OvfCreateImportSpecResult ovfImportResult = context.getService().createImportSpec( - context.getServiceContent().getOvfManager(), ovfDescriptor, morRp, - dsMo.getMor(), importSpecParams); - - if(ovfImportResult == null) { - String msg = "createImportSpec() failed. ovfFilePath: " + ovfFilePath + ", vmName: " - + vmName + ", diskOption: " + diskOption; - s_logger.error(msg); - throw new Exception(msg); - } - - DatacenterMO dcMo = new DatacenterMO(context, host.getHyperHostDatacenter()); - ManagedObjectReference morLease = context.getService().importVApp(morRp, - ovfImportResult.getImportSpec(), dcMo.getVmFolder(), morHost); - if(morLease == null) { - String msg = "importVApp() failed. ovfFilePath: " + ovfFilePath + ", vmName: " - + vmName + ", diskOption: " + diskOption; - s_logger.error(msg); - throw new Exception(msg); - } - final HttpNfcLeaseMO leaseMo = new HttpNfcLeaseMO(context, morLease); - HttpNfcLeaseState state = leaseMo.waitState( - new HttpNfcLeaseState[] { HttpNfcLeaseState.ready, HttpNfcLeaseState.error }); - try { - if(state == HttpNfcLeaseState.ready) { - final long totalBytes = HttpNfcLeaseMO.calcTotalBytes(ovfImportResult); - File ovfFile = new File(ovfFilePath); - - HttpNfcLeaseInfo httpNfcLeaseInfo = leaseMo.getLeaseInfo(); - HttpNfcLeaseDeviceUrl[] deviceUrls = httpNfcLeaseInfo.getDeviceUrl(); - long bytesAlreadyWritten = 0; - - final HttpNfcLeaseMO.ProgressReporter progressReporter = leaseMo.createProgressReporter(); - try { - for (HttpNfcLeaseDeviceUrl deviceUrl : deviceUrls) { - String deviceKey = deviceUrl.getImportKey(); - for (OvfFileItem ovfFileItem : ovfImportResult.getFileItem()) { - if (deviceKey.equals(ovfFileItem.getDeviceId())) { - String absoluteFile = ovfFile.getParent() + File.separator + ovfFileItem.getPath(); - String urlToPost = deviceUrl.getUrl(); - urlToPost = resolveHostNameInUrl(dcMo, urlToPost); - - context.uploadVmdkFile(ovfFileItem.isCreate() ? "PUT" : "POST", urlToPost, absoluteFile, - bytesAlreadyWritten, new ActionDelegate () { - public void action(Long param) { - progressReporter.reportProgress((int)(param * 100 / totalBytes)); - } - }); - - bytesAlreadyWritten += ovfFileItem.getSize(); - } - } - } - } finally { - progressReporter.close(); - } - leaseMo.updateLeaseProgress(100); - } - } finally { - leaseMo.completeLease(); - } - } -} + + VmwareHypervisorHostNetworkSummary summary = hostMo.getHyperHostNetworkSummary(managementPortGroupName); + if(summary == null) { + s_logger.warn("Unable to resolve host name in url through vSphere, url: " + url); + return url; + } + + String hostIp = summary.getHostIp(); + + try { + URI resolvedUri = new URI(uri.getScheme(), uri.getUserInfo(), hostIp, uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); + + s_logger.info("url " + url + " is resolved to " + resolvedUri.toString() + " through vCenter"); + return resolvedUri.toString(); + } catch (URISyntaxException e) { + assert(false); + return url; + } + } + } catch(Exception e) { + s_logger.warn("Unexpected exception ", e); + } + + return url; + } + + public static void importVmFromOVF(VmwareHypervisorHost host, String ovfFilePath, String vmName, DatastoreMO dsMo, String diskOption, + ManagedObjectReference morRp, ManagedObjectReference morHost) throws Exception { + + assert(morRp != null); + + OvfCreateImportSpecParams importSpecParams = new OvfCreateImportSpecParams(); + importSpecParams.setHostSystem(morHost); + importSpecParams.setLocale("US"); + importSpecParams.setEntityName(vmName); + importSpecParams.setDeploymentOption(""); + importSpecParams.setDiskProvisioning(diskOption); // diskOption: thin, thick, etc + importSpecParams.setPropertyMapping(null); + + String ovfDescriptor = HttpNfcLeaseMO.readOvfContent(ovfFilePath); + VmwareContext context = host.getContext(); + OvfCreateImportSpecResult ovfImportResult = context.getService().createImportSpec( + context.getServiceContent().getOvfManager(), ovfDescriptor, morRp, + dsMo.getMor(), importSpecParams); + + if(ovfImportResult == null) { + String msg = "createImportSpec() failed. ovfFilePath: " + ovfFilePath + ", vmName: " + + vmName + ", diskOption: " + diskOption; + s_logger.error(msg); + throw new Exception(msg); + } + + DatacenterMO dcMo = new DatacenterMO(context, host.getHyperHostDatacenter()); + ManagedObjectReference morLease = context.getService().importVApp(morRp, + ovfImportResult.getImportSpec(), dcMo.getVmFolder(), morHost); + if(morLease == null) { + String msg = "importVApp() failed. ovfFilePath: " + ovfFilePath + ", vmName: " + + vmName + ", diskOption: " + diskOption; + s_logger.error(msg); + throw new Exception(msg); + } + final HttpNfcLeaseMO leaseMo = new HttpNfcLeaseMO(context, morLease); + HttpNfcLeaseState state = leaseMo.waitState( + new HttpNfcLeaseState[] { HttpNfcLeaseState.ready, HttpNfcLeaseState.error }); + try { + if(state == HttpNfcLeaseState.ready) { + final long totalBytes = HttpNfcLeaseMO.calcTotalBytes(ovfImportResult); + File ovfFile = new File(ovfFilePath); + + HttpNfcLeaseInfo httpNfcLeaseInfo = leaseMo.getLeaseInfo(); + HttpNfcLeaseDeviceUrl[] deviceUrls = httpNfcLeaseInfo.getDeviceUrl(); + long bytesAlreadyWritten = 0; + + final HttpNfcLeaseMO.ProgressReporter progressReporter = leaseMo.createProgressReporter(); + try { + for (HttpNfcLeaseDeviceUrl deviceUrl : deviceUrls) { + String deviceKey = deviceUrl.getImportKey(); + for (OvfFileItem ovfFileItem : ovfImportResult.getFileItem()) { + if (deviceKey.equals(ovfFileItem.getDeviceId())) { + String absoluteFile = ovfFile.getParent() + File.separator + ovfFileItem.getPath(); + String urlToPost = deviceUrl.getUrl(); + urlToPost = resolveHostNameInUrl(dcMo, urlToPost); + + context.uploadVmdkFile(ovfFileItem.isCreate() ? "PUT" : "POST", urlToPost, absoluteFile, + bytesAlreadyWritten, new ActionDelegate () { + public void action(Long param) { + progressReporter.reportProgress((int)(param * 100 / totalBytes)); + } + }); + + bytesAlreadyWritten += ovfFileItem.getSize(); + } + } + } + } finally { + progressReporter.close(); + } + leaseMo.updateLeaseProgress(100); + } + } finally { + leaseMo.completeLease(); + } + } +}