// 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.hypervisor.vmware.mo; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.apache.log4j.Logger; import com.google.gson.Gson; import com.vmware.vim25.AboutInfo; import com.vmware.vim25.AlreadyExistsFaultMsg; import com.vmware.vim25.ClusterDasConfigInfo; import com.vmware.vim25.ComputeResourceSummary; import com.vmware.vim25.CustomFieldStringValue; import com.vmware.vim25.DatastoreSummary; import com.vmware.vim25.DynamicProperty; import com.vmware.vim25.HostConfigManager; import com.vmware.vim25.HostConnectInfo; import com.vmware.vim25.HostFirewallInfo; import com.vmware.vim25.HostFirewallRuleset; import com.vmware.vim25.HostHardwareSummary; import com.vmware.vim25.HostHyperThreadScheduleInfo; import com.vmware.vim25.HostIpConfig; import com.vmware.vim25.HostIpRouteEntry; import com.vmware.vim25.HostListSummaryQuickStats; import com.vmware.vim25.HostNetworkInfo; import com.vmware.vim25.HostNetworkPolicy; import com.vmware.vim25.HostNetworkSecurityPolicy; import com.vmware.vim25.HostNetworkTrafficShapingPolicy; import com.vmware.vim25.HostOpaqueNetworkInfo; import com.vmware.vim25.HostPortGroup; import com.vmware.vim25.HostPortGroupSpec; import com.vmware.vim25.HostRuntimeInfo; import com.vmware.vim25.HostSystemConnectionState; import com.vmware.vim25.HostVirtualNic; import com.vmware.vim25.HostVirtualSwitch; import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.NasDatastoreInfo; import com.vmware.vim25.ObjectContent; import com.vmware.vim25.ObjectSpec; import com.vmware.vim25.OptionValue; import com.vmware.vim25.PropertyFilterSpec; import com.vmware.vim25.PropertySpec; import com.vmware.vim25.TraversalSpec; import com.vmware.vim25.VirtualMachineConfigSpec; import com.vmware.vim25.VirtualNicManagerNetConfig; import com.cloud.hypervisor.vmware.util.VmwareContext; import com.cloud.hypervisor.vmware.util.VmwareHelper; import com.cloud.utils.Pair; public class HostMO extends BaseMO implements VmwareHypervisorHost { private static final Logger s_logger = Logger.getLogger(HostMO.class); Map _vmCache = new HashMap(); //Map _vmInternalNameMapCache = new HashMap(); public HostMO(VmwareContext context, ManagedObjectReference morHost) { super(context, morHost); } public HostMO(VmwareContext context, String morType, String morValue) { super(context, morType, morValue); } public HostHardwareSummary getHostHardwareSummary() throws Exception { HostConnectInfo hostInfo = _context.getService().queryHostConnectionInfo(_mor); HostHardwareSummary hardwareSummary = hostInfo.getHost().getHardware(); return hardwareSummary; } public HostConfigManager getHostConfigManager() throws Exception { return (HostConfigManager)_context.getVimClient().getDynamicProperty(_mor, "configManager"); } public List getHostVirtualNicManagerNetConfig() throws Exception { return _context.getVimClient().getDynamicProperty(_mor, "config.virtualNicManagerInfo.netConfig"); } public List getHostIpRouteEntries() throws Exception { return _context.getVimClient().getDynamicProperty(_mor, "config.network.routeTableInfo.ipRoute"); } public HostListSummaryQuickStats getHostQuickStats() throws Exception { return (HostListSummaryQuickStats)_context.getVimClient().getDynamicProperty(_mor, "summary.quickStats"); } public HostHyperThreadScheduleInfo getHostHyperThreadInfo() throws Exception { return (HostHyperThreadScheduleInfo)_context.getVimClient().getDynamicProperty(_mor, "config.hyperThread"); } public HostNetworkInfo getHostNetworkInfo() throws Exception { return (HostNetworkInfo)_context.getVimClient().getDynamicProperty(_mor, "config.network"); } public HostPortGroupSpec getHostPortGroupSpec(String portGroupName) throws Exception { HostNetworkInfo hostNetInfo = getHostNetworkInfo(); List portGroups = hostNetInfo.getPortgroup(); if (portGroups != null) { for (HostPortGroup portGroup : portGroups) { HostPortGroupSpec spec = portGroup.getSpec(); if (spec.getName().equals(portGroupName)) return spec; } } return null; } @Override public String getHyperHostName() throws Exception { return getName(); } @Override public ClusterDasConfigInfo getDasConfig() throws Exception { ManagedObjectReference morParent = getParentMor(); if (morParent.getType().equals("ClusterComputeResource")) { ClusterMO clusterMo = new ClusterMO(_context, morParent); return clusterMo.getDasConfig(); } return null; } @Override public boolean isHAEnabled() throws Exception { ManagedObjectReference morParent = getParentMor(); if (morParent.getType().equals("ClusterComputeResource")) { ClusterMO clusterMo = new ClusterMO(_context, morParent); return clusterMo.isHAEnabled(); } return false; } @Override public void setRestartPriorityForVM(VirtualMachineMO vmMo, String priority) throws Exception { ManagedObjectReference morParent = getParentMor(); if (morParent.getType().equals("ClusterComputeResource")) { ClusterMO clusterMo = new ClusterMO(_context, morParent); clusterMo.setRestartPriorityForVM(vmMo, priority); } } @Override public String getHyperHostDefaultGateway() throws Exception { List entries = getHostIpRouteEntries(); for (HostIpRouteEntry entry : entries) { if (entry.getNetwork().equalsIgnoreCase("0.0.0.0")) return entry.getGateway(); } throw new Exception("Could not find host default gateway, host is not properly configured?"); } public HostStorageSystemMO getHostStorageSystemMO() throws Exception { return new HostStorageSystemMO(_context, (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "configManager.storageSystem")); } public HostDatastoreSystemMO getHostDatastoreSystemMO() throws Exception { return new HostDatastoreSystemMO(_context, (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "configManager.datastoreSystem")); } public HostDatastoreBrowserMO getHostDatastoreBrowserMO() throws Exception { return new HostDatastoreBrowserMO(_context, (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "datastoreBrowser")); } private DatastoreMO getHostDatastoreMO(String datastoreName) throws Exception { ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {"name"}); if (ocs != null && ocs.length > 0) { for (ObjectContent oc : ocs) { List objProps = oc.getPropSet(); if (objProps != null) { for (DynamicProperty objProp : objProps) { if (objProp.getVal().toString().equals(datastoreName)) return new DatastoreMO(_context, oc.getObj()); } } } } return null; } public HostNetworkSystemMO getHostNetworkSystemMO() throws Exception { HostConfigManager configMgr = getHostConfigManager(); return new HostNetworkSystemMO(_context, configMgr.getNetworkSystem()); } public HostFirewallSystemMO getHostFirewallSystemMO() throws Exception { HostConfigManager configMgr = getHostConfigManager(); ManagedObjectReference morFirewall = configMgr.getFirewallSystem(); // only ESX hosts have firewall manager if (morFirewall != null) return new HostFirewallSystemMO(_context, morFirewall); return null; } @Override public ManagedObjectReference getHyperHostDatacenter() throws Exception { Pair dcPair = DatacenterMO.getOwnerDatacenter(getContext(), getMor()); assert (dcPair != null); return dcPair.first().getMor(); } @Override public ManagedObjectReference getHyperHostOwnerResourcePool() throws Exception { ManagedObjectReference morComputerResource = (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "parent"); return (ManagedObjectReference)_context.getVimClient().getDynamicProperty(morComputerResource, "resourcePool"); } @Override public ManagedObjectReference getHyperHostCluster() throws Exception { ManagedObjectReference morParent = (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "parent"); if (morParent.getType().equalsIgnoreCase("ClusterComputeResource")) { return morParent; } assert (false); throw new Exception("Standalone host is not supported"); } public ManagedObjectReference[] getHostLocalDatastore() throws Exception { List datastores = _context.getVimClient().getDynamicProperty(_mor, "datastore"); List l = new ArrayList(); if (datastores != null) { for (ManagedObjectReference mor : datastores) { DatastoreSummary summary = (DatastoreSummary)_context.getVimClient().getDynamicProperty(mor, "summary"); if (summary.getType().equalsIgnoreCase("VMFS") && !summary.isMultipleHostAccess()) l.add(mor); } } return l.toArray(new ManagedObjectReference[1]); } public HostVirtualSwitch getHostVirtualSwitchByName(String name) throws Exception { List switches = _context.getVimClient().getDynamicProperty(_mor, "config.network.vswitch"); if (switches != null) { for (HostVirtualSwitch vswitch : switches) { if (vswitch.getName().equals(name)) return vswitch; } } return null; } public List getHostVirtualSwitch() throws Exception { return _context.getVimClient().getDynamicProperty(_mor, "config.network.vswitch"); } public AboutInfo getHostAboutInfo() throws Exception { return (AboutInfo)_context.getVimClient().getDynamicProperty(_mor, "config.product"); } public VmwareHostType getHostType() throws Exception { AboutInfo aboutInfo = getHostAboutInfo(); if ("VMware ESXi".equals(aboutInfo.getName())) return VmwareHostType.ESXi; else if ("VMware ESX".equals(aboutInfo.getName())) return VmwareHostType.ESX; throw new Exception("Unrecognized VMware host type " + aboutInfo.getName()); } // default virtual switch is which management network residents on public HostVirtualSwitch getHostDefaultVirtualSwitch() throws Exception { String managementPortGroup = getPortGroupNameByNicType(HostVirtualNicType.management); if (managementPortGroup != null) return getPortGroupVirtualSwitch(managementPortGroup); return null; } public HostVirtualSwitch getPortGroupVirtualSwitch(String portGroupName) throws Exception { String vSwitchName = getPortGroupVirtualSwitchName(portGroupName); if (vSwitchName != null) return getVirtualSwitchByName(vSwitchName); return null; } public HostVirtualSwitch getVirtualSwitchByName(String vSwitchName) throws Exception { List vSwitchs = getHostVirtualSwitch(); if (vSwitchs != null) { for (HostVirtualSwitch vSwitch : vSwitchs) { if (vSwitch.getName().equals(vSwitchName)) return vSwitch; } } return null; } public String getPortGroupVirtualSwitchName(String portGroupName) throws Exception { HostNetworkInfo hostNetInfo = getHostNetworkInfo(); List portGroups = hostNetInfo.getPortgroup(); if (portGroups != null) { for (HostPortGroup portGroup : portGroups) { HostPortGroupSpec spec = portGroup.getSpec(); if (spec.getName().equals(portGroupName)) return spec.getVswitchName(); } } return null; } public HostPortGroupSpec getPortGroupSpec(String portGroupName) throws Exception { HostNetworkInfo hostNetInfo = getHostNetworkInfo(); List portGroups = hostNetInfo.getPortgroup(); if (portGroups != null) { for (HostPortGroup portGroup : portGroups) { HostPortGroupSpec spec = portGroup.getSpec(); if (spec.getName().equals(portGroupName)) return spec; } } return null; } public String getPortGroupNameByNicType(HostVirtualNicType nicType) throws Exception { assert (nicType != null); List netConfigs = _context.getVimClient().getDynamicProperty(_mor, "config.virtualNicManagerInfo.netConfig"); if (netConfigs != null) { for (VirtualNicManagerNetConfig netConfig : netConfigs) { if (netConfig.getNicType().equals(nicType.toString())) { List nics = netConfig.getCandidateVnic(); if (nics != null) { for (HostVirtualNic nic : nics) { return nic.getPortgroup(); } } } } } if (nicType == HostVirtualNicType.management) { // ESX management network is configured in service console HostNetworkInfo netInfo = getHostNetworkInfo(); assert (netInfo != null); List nics = netInfo.getConsoleVnic(); if (nics != null) { for (HostVirtualNic nic : nics) { return nic.getPortgroup(); } } } return null; } public boolean hasOpaqueNSXNetwork() throws Exception{ HostNetworkInfo netInfo = getHostNetworkInfo(); List opaqueNetworks = netInfo.getOpaqueNetwork(); if (opaqueNetworks != null){ for (HostOpaqueNetworkInfo opaqueNetwork : opaqueNetworks){ if (opaqueNetwork.getOpaqueNetworkId() != null && opaqueNetwork.getOpaqueNetworkId().equals("br-int") && opaqueNetwork.getOpaqueNetworkType() != null && opaqueNetwork.getOpaqueNetworkType().equals("nsx.network")){ return true; } } throw new Exception("NSX API VERSION >= 4.2 BUT br-int (nsx.network) NOT FOUND"); } else { throw new Exception("NSX API VERSION >= 4.2 BUT br-int (nsx.network) NOT FOUND"); } } public boolean hasPortGroup(HostVirtualSwitch vSwitch, String portGroupName) throws Exception { ManagedObjectReference morNetwork = getNetworkMor(portGroupName); if (morNetwork != null) return true; return false; } public void createPortGroup(HostVirtualSwitch vSwitch, String portGroupName, Integer vlanId, HostNetworkSecurityPolicy secPolicy, HostNetworkTrafficShapingPolicy shapingPolicy) throws Exception { assert (portGroupName != null); HostNetworkSystemMO hostNetMo = getHostNetworkSystemMO(); assert (hostNetMo != null); HostPortGroupSpec spec = new HostPortGroupSpec(); spec.setName(portGroupName); if (vlanId != null) spec.setVlanId(vlanId.intValue()); HostNetworkPolicy policy = new HostNetworkPolicy(); if (secPolicy != null) policy.setSecurity(secPolicy); policy.setShapingPolicy(shapingPolicy); spec.setPolicy(policy); spec.setVswitchName(vSwitch.getName()); hostNetMo.addPortGroup(spec); } public void updatePortGroup(HostVirtualSwitch vSwitch, String portGroupName, Integer vlanId, HostNetworkSecurityPolicy secPolicy, HostNetworkTrafficShapingPolicy shapingPolicy) throws Exception { assert (portGroupName != null); HostNetworkSystemMO hostNetMo = getHostNetworkSystemMO(); assert (hostNetMo != null); HostPortGroupSpec spec = new HostPortGroupSpec(); spec.setName(portGroupName); if (vlanId != null) spec.setVlanId(vlanId.intValue()); HostNetworkPolicy policy = new HostNetworkPolicy(); if (secPolicy != null) policy.setSecurity(secPolicy); policy.setShapingPolicy(shapingPolicy); spec.setPolicy(policy); spec.setVswitchName(vSwitch.getName()); hostNetMo.updatePortGroup(portGroupName, spec); } public void deletePortGroup(String portGroupName) throws Exception { assert (portGroupName != null); HostNetworkSystemMO hostNetMo = getHostNetworkSystemMO(); assert (hostNetMo != null); hostNetMo.removePortGroup(portGroupName); } public ManagedObjectReference getNetworkMor(String portGroupName) throws Exception { PropertySpec pSpec = new PropertySpec(); pSpec.setType("Network"); pSpec.getPathSet().add("summary.name"); TraversalSpec host2NetworkTraversal = new TraversalSpec(); host2NetworkTraversal.setType("HostSystem"); host2NetworkTraversal.setPath("network"); host2NetworkTraversal.setName("host2NetworkTraversal"); ObjectSpec oSpec = new ObjectSpec(); oSpec.setObj(_mor); oSpec.setSkip(Boolean.TRUE); oSpec.getSelectSet().add(host2NetworkTraversal); PropertyFilterSpec pfSpec = new PropertyFilterSpec(); pfSpec.getPropSet().add(pSpec); pfSpec.getObjectSet().add(oSpec); List pfSpecArr = new ArrayList(); pfSpecArr.add(pfSpec); List ocs = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); if (ocs != null) { for (ObjectContent oc : ocs) { List props = oc.getPropSet(); if (props != null) { for (DynamicProperty prop : props) { if (prop.getVal().equals(portGroupName)) return oc.getObj(); } } } } return null; } public List getVmMorsOnNetwork(String portGroupName) throws Exception { ManagedObjectReference morNetwork = getNetworkMor(portGroupName); if (morNetwork != null) return _context.getVimClient().getDynamicProperty(morNetwork, "vm"); return null; } public String getHostName() throws Exception { return (String)_context.getVimClient().getDynamicProperty(_mor, "name"); } @Override public synchronized VirtualMachineMO findVmOnHyperHost(String vmName) throws Exception { if (s_logger.isDebugEnabled()) s_logger.debug("find VM " + vmName + " on host"); VirtualMachineMO vmMo = _vmCache.get(vmName); if (vmMo != null) { if (s_logger.isDebugEnabled()) s_logger.debug("VM " + vmName + " found in host cache"); return vmMo; } s_logger.info("VM " + vmName + " not found in host cache"); loadVmCache(); return _vmCache.get(vmName); } private boolean isUserVMInternalCSName(String vmInternalCSName) { // CS generated internal names for user VMs are always of the format i-x-y. String internalCSUserVMNamingPattern = "^[i][-][0-9]+[-][0-9]+[-]"; Pattern p = Pattern.compile(internalCSUserVMNamingPattern); java.util.regex.Matcher m = p.matcher(vmInternalCSName); if (m.find()) { return true; } else { return false; } } private void loadVmCache() throws Exception { if (s_logger.isDebugEnabled()) s_logger.debug("load VM cache on host"); _vmCache.clear(); int key = getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); if (key == 0) { s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); } // name is the name of the VM as it appears in vCenter. The CLOUD_VM_INTERNAL_NAME custom // field value contains the name of the VM as it is maintained internally by cloudstack (i-x-y). ObjectContent[] ocs = getVmPropertiesOnHyperHost(new String[] {"name", "value[" + key + "]"}); if (ocs != null && ocs.length > 0) { for (ObjectContent oc : ocs) { List props = oc.getPropSet(); if (props != null) { String vmVcenterName = null; String vmInternalCSName = null; for (DynamicProperty prop : props) { if (prop.getName().equals("name")) { vmVcenterName = prop.getVal().toString(); } else if (prop.getName().startsWith("value[")) { if (prop.getVal() != null) vmInternalCSName = ((CustomFieldStringValue)prop.getVal()).getValue(); } } String vmName = null; if (vmInternalCSName != null && isUserVMInternalCSName(vmInternalCSName)) { vmName = vmInternalCSName; } else { vmName = vmVcenterName; } if (s_logger.isTraceEnabled()) s_logger.trace("put " + vmName + " into host cache"); _vmCache.put(vmName, new VirtualMachineMO(_context, oc.getObj())); } } } } @Override public VirtualMachineMO findVmOnPeerHyperHost(String name) throws Exception { ManagedObjectReference morParent = getParentMor(); if (morParent.getType().equals("ClusterComputeResource")) { ClusterMO clusterMo = new ClusterMO(_context, morParent); return clusterMo.findVmOnHyperHost(name); } else { // we don't support standalone host, all hosts have to be managed by // a cluster within vCenter assert (false); return null; } } @Override public boolean createVm(VirtualMachineConfigSpec vmSpec) throws Exception { assert (vmSpec != null); DatacenterMO dcMo = new DatacenterMO(_context, getHyperHostDatacenter()); ManagedObjectReference morPool = getHyperHostOwnerResourcePool(); ManagedObjectReference morTask = _context.getService().createVMTask(dcMo.getVmFolder(), vmSpec, morPool, _mor); boolean result = _context.getVimClient().waitForTask(morTask); if (result) { _context.waitForTaskProgressDone(morTask); return true; } else { s_logger.error("VMware createVM_Task failed due to " + TaskMO.getTaskFailureInfo(_context, morTask)); } return false; } public HashMap getVmVncPortsOnHost() throws Exception { int key = getCustomFieldKey("VirtualMachine", CustomFieldConstants.CLOUD_VM_INTERNAL_NAME); if (key == 0) { s_logger.warn("Custom field " + CustomFieldConstants.CLOUD_VM_INTERNAL_NAME + " is not registered ?!"); } ObjectContent[] ocs = getVmPropertiesOnHyperHost(new String[] {"name", "config.extraConfig[\"RemoteDisplay.vnc.port\"]", "value[" + key + "]"}); HashMap portInfo = new HashMap(); if (ocs != null && ocs.length > 0) { for (ObjectContent oc : ocs) { List objProps = oc.getPropSet(); if (objProps != null) { String vmName = null; String value = null; String vmInternalCSName = null; for (DynamicProperty objProp : objProps) { if (objProp.getName().equals("name")) { vmName = (String)objProp.getVal(); } else if (objProp.getName().startsWith("value[")) { if (objProp.getVal() != null) vmInternalCSName = ((CustomFieldStringValue)objProp.getVal()).getValue(); } else { OptionValue optValue = (OptionValue)objProp.getVal(); value = (String)optValue.getValue(); } } if (vmInternalCSName != null && isUserVMInternalCSName(vmInternalCSName)) vmName = vmInternalCSName; if (vmName != null && value != null) { portInfo.put(vmName, Integer.parseInt(value)); } } } } return portInfo; } @Override public ObjectContent[] getVmPropertiesOnHyperHost(String[] propertyPaths) throws Exception { if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - retrieveProperties() for VM properties. target MOR: " + _mor.getValue() + ", properties: " + new Gson().toJson(propertyPaths)); PropertySpec pSpec = new PropertySpec(); pSpec.setType("VirtualMachine"); pSpec.getPathSet().addAll(Arrays.asList(propertyPaths)); TraversalSpec host2VmTraversal = new TraversalSpec(); host2VmTraversal.setType("HostSystem"); host2VmTraversal.setPath("vm"); host2VmTraversal.setName("host2VmTraversal"); ObjectSpec oSpec = new ObjectSpec(); oSpec.setObj(_mor); oSpec.setSkip(Boolean.TRUE); oSpec.getSelectSet().add(host2VmTraversal); PropertyFilterSpec pfSpec = new PropertyFilterSpec(); pfSpec.getPropSet().add(pSpec); pfSpec.getObjectSet().add(oSpec); List pfSpecArr = new ArrayList(); pfSpecArr.add(pfSpec); List properties = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - retrieveProperties() done"); return properties.toArray(new ObjectContent[properties.size()]); } @Override public ObjectContent[] getDatastorePropertiesOnHyperHost(String[] propertyPaths) throws Exception { if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - retrieveProperties() on Datastore properties. target MOR: " + _mor.getValue() + ", properties: " + new Gson().toJson(propertyPaths)); PropertySpec pSpec = new PropertySpec(); pSpec.setType("Datastore"); pSpec.getPathSet().addAll(Arrays.asList(propertyPaths)); TraversalSpec host2DatastoreTraversal = new TraversalSpec(); host2DatastoreTraversal.setType("HostSystem"); host2DatastoreTraversal.setPath("datastore"); host2DatastoreTraversal.setName("host2DatastoreTraversal"); ObjectSpec oSpec = new ObjectSpec(); oSpec.setObj(_mor); oSpec.setSkip(Boolean.TRUE); oSpec.getSelectSet().add(host2DatastoreTraversal); PropertyFilterSpec pfSpec = new PropertyFilterSpec(); pfSpec.getPropSet().add(pSpec); pfSpec.getObjectSet().add(oSpec); List pfSpecArr = new ArrayList(); pfSpecArr.add(pfSpec); List properties = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - retrieveProperties() done"); return properties.toArray(new ObjectContent[properties.size()]); } public List> getDatastoreMountsOnHost() throws Exception { List> mounts = new ArrayList>(); ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {String.format("host[\"%s\"].mountInfo.path", _mor.getValue())}); if (ocs != null) { for (ObjectContent oc : ocs) { Pair mount = new Pair(oc.getObj(), oc.getPropSet().get(0).getVal().toString()); mounts.add(mount); } } return mounts; } public List> getLocalDatastoreOnHost() throws Exception { List> dsList = new ArrayList>(); ObjectContent[] ocs = getDatastorePropertiesOnHyperHost(new String[] {"name", "summary"}); if (ocs != null) { for (ObjectContent oc : ocs) { DatastoreSummary dsSummary = (DatastoreSummary)VmwareHelper.getPropValue(oc, "summary"); if (dsSummary.isMultipleHostAccess() == false && dsSummary.isAccessible() && dsSummary.getType().equalsIgnoreCase("vmfs")) { ManagedObjectReference morDs = oc.getObj(); String name = (String)VmwareHelper.getPropValue(oc, "name"); if (!name.startsWith("-iqn.") && !name.startsWith("_iqn.")) { dsList.add(new Pair(morDs, name)); } } } } return dsList; } public void importVmFromOVF(String ovfFilePath, String vmName, String datastoreName, String diskOption) throws Exception { if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - importVmFromOVF(). target MOR: " + _mor.getValue() + ", ovfFilePath: " + ovfFilePath + ", vmName: " + vmName + ",datastoreName: " + datastoreName + ", diskOption: " + diskOption); DatastoreMO dsMo = getHostDatastoreMO(datastoreName); if (dsMo == null) throw new Exception("Invalid datastore name: " + datastoreName); importVmFromOVF(ovfFilePath, vmName, dsMo, diskOption); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - importVmFromOVF() done"); } @Override public void importVmFromOVF(String ovfFilePath, String vmName, DatastoreMO dsMo, String diskOption) throws Exception { ManagedObjectReference morRp = getHyperHostOwnerResourcePool(); assert (morRp != null); HypervisorHostHelper.importVmFromOVF(this, ovfFilePath, vmName, dsMo, diskOption, morRp, _mor); } @Override public boolean createBlankVm(String vmName, String vmInternalCSName, int cpuCount, int cpuSpeedMHz, int cpuReservedMHz, boolean limitCpuUse, int memoryMB, int memoryReserveMB, String guestOsIdentifier, ManagedObjectReference morDs, boolean snapshotDirToParent, Pair controllerInfo, Boolean systemVm) throws Exception { if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - createBlankVm(). target MOR: " + _mor.getValue() + ", vmName: " + vmName + ", cpuCount: " + cpuCount + ", cpuSpeedMhz: " + cpuSpeedMHz + ", cpuReservedMHz: " + cpuReservedMHz + ", limitCpu: " + limitCpuUse + ", memoryMB: " + memoryMB + ", guestOS: " + guestOsIdentifier + ", datastore: " + morDs.getValue() + ", snapshotDirToParent: " + snapshotDirToParent + ", controllerInfo:[" + controllerInfo.first() + "," + controllerInfo.second() + "], systemvm: " + systemVm); boolean result = HypervisorHostHelper.createBlankVm(this, vmName, vmInternalCSName, cpuCount, cpuSpeedMHz, cpuReservedMHz, limitCpuUse, memoryMB, memoryReserveMB, guestOsIdentifier, morDs, snapshotDirToParent, controllerInfo, systemVm); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - createBlankVm() done"); return result; } public ManagedObjectReference getExistingDataStoreOnHost(boolean vmfsDatastore, String hostAddress, int hostPort, String path, String uuid, HostDatastoreSystemMO hostDatastoreSystemMo) { // First retrieve the list of Datastores on the host. List morArray; try { morArray = hostDatastoreSystemMo.getDatastores(); } catch (Exception e) { s_logger.info("Failed to retrieve list of Managed Object References"); return null; } // Next, get all the NAS datastores from this array of datastores. if (morArray.size() > 0) { int i; for (i = 0; i < morArray.size(); i++) { NasDatastoreInfo nasDS; try { nasDS = hostDatastoreSystemMo.getNasDatastoreInfo(morArray.get(i)); if (nasDS != null) { //DatastoreInfo info = (DatastoreInfo)_context.getServiceUtil().getDynamicProperty(morDatastore, "info"); if (nasDS.getNas().getRemoteHost().equalsIgnoreCase(hostAddress) && nasDS.getNas().getRemotePath().equalsIgnoreCase(path)) { return morArray.get(i); } } } catch (Exception e) { s_logger.info("Encountered exception when retrieving nas datastore info"); return null; } } } return null; } @Override public ManagedObjectReference mountDatastore(boolean vmfsDatastore, String poolHostAddress, int poolHostPort, String poolPath, String poolUuid) throws Exception { if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - mountDatastore(). target MOR: " + _mor.getValue() + ", vmfs: " + vmfsDatastore + ", poolHost: " + poolHostAddress + ", poolHostPort: " + poolHostPort + ", poolPath: " + poolPath + ", poolUuid: " + poolUuid); HostDatastoreSystemMO hostDatastoreSystemMo = getHostDatastoreSystemMO(); ManagedObjectReference morDatastore = hostDatastoreSystemMo.findDatastore(poolUuid); if (morDatastore == null) { if (!vmfsDatastore) { try { morDatastore = hostDatastoreSystemMo.createNfsDatastore(poolHostAddress, poolHostPort, poolPath, poolUuid); } catch (AlreadyExistsFaultMsg e) { s_logger.info("Creation of NFS datastore on vCenter failed since datastore already exists." + " Details: vCenter API trace - mountDatastore(). target MOR: " + _mor.getValue() + ", vmfs: " + vmfsDatastore + ", poolHost: " + poolHostAddress + ", poolHostPort: " + poolHostPort + ", poolPath: " + poolPath + ", poolUuid: " + poolUuid); // Retrieve the morDatastore and return it. return (getExistingDataStoreOnHost(vmfsDatastore, poolHostAddress, poolHostPort, poolPath, poolUuid, hostDatastoreSystemMo)); } catch (Exception e) { s_logger.info("Creation of NFS datastore on vCenter failed. " + " Details: vCenter API trace - mountDatastore(). target MOR: " + _mor.getValue() + ", vmfs: " + vmfsDatastore + ", poolHost: " + poolHostAddress + ", poolHostPort: " + poolHostPort + ", poolPath: " + poolPath + ", poolUuid: " + poolUuid + ". Exception mesg: " + e.getMessage()); throw new Exception("Creation of NFS datastore on vCenter failed."); } if (morDatastore == null) { String msg = "Unable to create NFS datastore. host: " + poolHostAddress + ", port: " + poolHostPort + ", path: " + poolPath + ", uuid: " + poolUuid; s_logger.error(msg); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - mountDatastore() done(failed)"); throw new Exception(msg); } } else { morDatastore = _context.getDatastoreMorByPath(poolPath); if (morDatastore == null) { String msg = "Unable to create VMFS datastore. host: " + poolHostAddress + ", port: " + poolHostPort + ", path: " + poolPath + ", uuid: " + poolUuid; s_logger.error(msg); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - mountDatastore() done(failed)"); throw new Exception(msg); } DatastoreMO dsMo = new DatastoreMO(_context, morDatastore); dsMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, poolUuid); } } if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - mountDatastore() done(successfully)"); return morDatastore; } @Override public void unmountDatastore(String uuid) throws Exception { if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - unmountDatastore(). target MOR: " + _mor.getValue() + ", uuid: " + uuid); HostDatastoreSystemMO hostDatastoreSystemMo = getHostDatastoreSystemMO(); if (!hostDatastoreSystemMo.deleteDatastore(uuid)) { String msg = "Unable to unmount datastore. uuid: " + uuid; s_logger.error(msg); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - unmountDatastore() done(failed)"); throw new Exception(msg); } if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - unmountDatastore() done"); } @Override public ManagedObjectReference findDatastore(String poolUuid) throws Exception { HostDatastoreSystemMO hostDsMo = getHostDatastoreSystemMO(); return hostDsMo.findDatastore(poolUuid); } @Override public ManagedObjectReference findDatastoreByExportPath(String exportPath) throws Exception { HostDatastoreSystemMO datastoreSystemMo = getHostDatastoreSystemMO(); return datastoreSystemMo.findDatastoreByExportPath(exportPath); } @Override public ManagedObjectReference findDatastoreByName(String datastoreName) throws Exception { HostDatastoreSystemMO hostDsMo = getHostDatastoreSystemMO(); return hostDsMo.findDatastoreByName(datastoreName); } @Override public ManagedObjectReference findMigrationTarget(VirtualMachineMO vmMo) throws Exception { return _mor; } @Override public VmwareHypervisorHostResourceSummary getHyperHostResourceSummary() throws Exception { if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - getHyperHostResourceSummary(). target MOR: " + _mor.getValue()); VmwareHypervisorHostResourceSummary summary = new VmwareHypervisorHostResourceSummary(); HostHardwareSummary hardwareSummary = getHostHardwareSummary(); // TODO: not sure how hyper-thread is counted in VMware resource pool summary.setCpuCount(hardwareSummary.getNumCpuThreads()); summary.setMemoryBytes(hardwareSummary.getMemorySize()); summary.setCpuSpeed(hardwareSummary.getCpuMhz()); summary.setCpuSockets((int)hardwareSummary.getNumCpuPkgs()); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - getHyperHostResourceSummary() done"); return summary; } @Override public VmwareHypervisorHostNetworkSummary getHyperHostNetworkSummary(String managementPortGroup) throws Exception { if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - getHyperHostNetworkSummary(). target MOR: " + _mor.getValue() + ", mgmtPortgroup: " + managementPortGroup); VmwareHypervisorHostNetworkSummary summary = new VmwareHypervisorHostNetworkSummary(); if (getHostType() == VmwareHostType.ESXi) { List netConfigs = _context.getVimClient().getDynamicProperty(_mor, "config.virtualNicManagerInfo.netConfig"); assert (netConfigs != null); String dvPortGroupKey; String portGroup; for (VirtualNicManagerNetConfig netConfig : netConfigs) { if (netConfig.getNicType().equals("management")) { for (HostVirtualNic nic : netConfig.getCandidateVnic()) { portGroup = nic.getPortgroup(); if (portGroup == null || portGroup.isEmpty()) { dvPortGroupKey = nic.getSpec().getDistributedVirtualPort().getPortgroupKey(); portGroup = getNetworkName(dvPortGroupKey); } if (portGroup.equalsIgnoreCase(managementPortGroup)) { summary.setHostIp(nic.getSpec().getIp().getIpAddress()); summary.setHostNetmask(nic.getSpec().getIp().getSubnetMask()); summary.setHostMacAddress(nic.getSpec().getMac()); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - getHyperHostNetworkSummary() done(successfully)"); return summary; } } } } } else { // try with ESX path List hostVNics = _context.getVimClient().getDynamicProperty(_mor, "config.network.consoleVnic"); if (hostVNics != null) { for (HostVirtualNic vnic : hostVNics) { if (vnic.getPortgroup().equals(managementPortGroup)) { summary.setHostIp(vnic.getSpec().getIp().getIpAddress()); summary.setHostNetmask(vnic.getSpec().getIp().getSubnetMask()); summary.setHostMacAddress(vnic.getSpec().getMac()); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - getHyperHostNetworkSummary() done(successfully)"); return summary; } } } } if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - getHyperHostNetworkSummary() done(failed)"); throw new Exception("Uanble to find management port group " + managementPortGroup); } @Override public ComputeResourceSummary getHyperHostHardwareSummary() throws Exception { if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - getHyperHostHardwareSummary(). target MOR: " + _mor.getValue()); // // This is to adopt the model when using Cluster as a big host while ComputeResourceSummary is used // directly from VMware resource pool // // When we break cluster hosts into individual hosts used in our resource allocator, // we will have to populate ComputeResourceSummary by ourselves here // HostHardwareSummary hardwareSummary = getHostHardwareSummary(); ComputeResourceSummary resourceSummary = new ComputeResourceSummary(); // TODO: not sure how hyper-threading is counted in VMware resourceSummary.setNumCpuCores(hardwareSummary.getNumCpuCores()); // Note: memory here is in Byte unit resourceSummary.setTotalMemory(hardwareSummary.getMemorySize()); // Total CPU is based on (# of cores) x Mhz int totalCpu = hardwareSummary.getCpuMhz() * hardwareSummary.getNumCpuCores(); resourceSummary.setTotalCpu(totalCpu); HostListSummaryQuickStats stats = getHostQuickStats(); if (stats.getOverallCpuUsage() == null || stats.getOverallMemoryUsage() == null) throw new Exception("Unable to get valid overal CPU/Memory usage data, host may be disconnected"); resourceSummary.setEffectiveCpu(totalCpu - stats.getOverallCpuUsage()); // Note effective memory is in MB unit resourceSummary.setEffectiveMemory(hardwareSummary.getMemorySize() / (1024 * 1024) - stats.getOverallMemoryUsage()); if (s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - getHyperHostHardwareSummary() done"); return resourceSummary; } @Override public boolean isHyperHostConnected() throws Exception { HostRuntimeInfo runtimeInfo = (HostRuntimeInfo)_context.getVimClient().getDynamicProperty(_mor, "runtime"); return runtimeInfo.getConnectionState() == HostSystemConnectionState.CONNECTED; } public boolean revertToSnapshot(ManagedObjectReference morSnapshot) throws Exception { ManagedObjectReference morTask = _context.getService().revertToSnapshotTask(morSnapshot, _mor, false); boolean result = _context.getVimClient().waitForTask(morTask); if (result) { _context.waitForTaskProgressDone(morTask); return true; } else { s_logger.error("VMware revert to snapshot failed due to " + TaskMO.getTaskFailureInfo(_context, morTask)); } return false; } @Override public LicenseAssignmentManagerMO getLicenseAssignmentManager() throws Exception { ManagedObjectReference licenseMgr; ManagedObjectReference licenseAssignmentManager; LicenseManagerMO licenseMgrMo; licenseMgr = _context.getServiceContent().getLicenseManager(); licenseMgrMo = new LicenseManagerMO(_context, licenseMgr); licenseAssignmentManager = licenseMgrMo.getLicenseAssignmentManager(); return new LicenseAssignmentManagerMO(_context, licenseAssignmentManager); } public void enableVncOnHostFirewall() throws Exception { HostFirewallSystemMO firewallMo = getHostFirewallSystemMO(); boolean bRefresh = false; if (firewallMo != null) { HostFirewallInfo firewallInfo = firewallMo.getFirewallInfo(); if (firewallInfo != null && firewallInfo.getRuleset() != null) { for (HostFirewallRuleset rule : firewallInfo.getRuleset()) { if ("vncServer".equalsIgnoreCase(rule.getKey())) { bRefresh = true; firewallMo.enableRuleset("vncServer"); } else if ("gdbserver".equalsIgnoreCase(rule.getKey())) { bRefresh = true; firewallMo.enableRuleset("gdbserver"); } } } if (bRefresh) firewallMo.refreshFirewall(); } } @Override public String getRecommendedDiskController(String guestOsId) throws Exception { ManagedObjectReference morParent = getParentMor(); if (morParent.getType().equals("ClusterComputeResource")) { ClusterMO clusterMo = new ClusterMO(_context, morParent); return clusterMo.getRecommendedDiskController(guestOsId); } return null; } public String getHostManagementIp(String managementPortGroup) throws Exception { HostNetworkInfo netInfo = getHostNetworkInfo(); List nics = netInfo.getVnic(); for (HostVirtualNic nic : nics) { if (nic.getPortgroup().equals(managementPortGroup)) { HostIpConfig ipConfig = nic.getSpec().getIp(); return ipConfig.getIpAddress(); } } return null; } public List getHostNetworks() throws Exception { return _context.getVimClient().getDynamicProperty(_mor, "network"); } public String getNetworkName(String netMorVal) throws Exception { String networkName = ""; List hostNetworks = getHostNetworks(); for (ManagedObjectReference hostNetwork : hostNetworks) { if (hostNetwork.getValue().equals(netMorVal)) { networkName = _context.getVimClient().getDynamicProperty(hostNetwork, "name"); break; } } return networkName; } public void createPortGroup(HostVirtualSwitch vSwitch, String portGroupName, Integer vlanId, HostNetworkSecurityPolicy secPolicy, HostNetworkTrafficShapingPolicy shapingPolicy, long timeOutMs) throws Exception { assert (portGroupName != null); // Prepare lock to avoid simultaneous execution of the synchronized block for // duplicate port groups on the ESXi host it's being created on. String hostPortGroup = _mor.getValue() + "-" + portGroupName; synchronized (hostPortGroup.intern()) { // Check if port group exists already if (hasPortGroup(vSwitch, portGroupName)) { if (s_logger.isDebugEnabled()) { s_logger.debug("Found port group " + portGroupName + " in vSwitch " + vSwitch.getName() + ". Not attempting to create port group as it already exists."); } return; } else { if (s_logger.isDebugEnabled()) { s_logger.debug("Port group " + portGroupName + " doesn't exist in vSwitch " + vSwitch.getName() + ". Attempting to create port group in this vSwitch."); } } // Create port group if not exists already createPortGroup(vSwitch, portGroupName, vlanId, secPolicy, shapingPolicy); // Wait for port group to turn up ready on vCenter upto timeout of timeOutMs milli seconds waitForPortGroup(portGroupName, timeOutMs); } if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully created port group " + portGroupName + " in vSwitch " + vSwitch.getName() + " on host " + getHostName()); } } public ManagedObjectReference waitForPortGroup(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 = getNetworkMor(networkName); if (morNetwork != null) { break; } if (s_logger.isInfoEnabled()) { s_logger.info("Waiting for network " + networkName + " to be ready"); } Thread.sleep(1000); } return morNetwork; } }