From 205f4a2192fad3b11f95e3ae709e4da80d7861bf Mon Sep 17 00:00:00 2001 From: Sateesh Chodapuneedi Date: Thu, 10 May 2012 03:24:56 +0530 Subject: [PATCH] CS-9919 - Support for Nexus Swiches (Cisco Vswitches) Description: Code changes to manage Cisco Nexus 1000v in CloudStack. VmwareResource has been modified to leverage Nexus vSwitch. Providing following global configuration parameters, vmware.use.nexus.vswitch - This would decide whether Nexus vSwitch in the VMware cluster environment would be used/managed by CloudStack for it's network infrastructure needs. vmware.guest.network.vswitch.type - This setting would enable CloudStack to use Nexus vSwitch in the VMware cluster environment for guest traffic. vmware.private.network.vswitch.type - This setting would enable CloudStack to use Nexus vSwitch in the VMware cluster environment for private traffic. vmware.public.network.vswitch.type - This setting would enable CloudStack to use Nexus vSwitch in the VMware cluster environment for private traffic. Functional Specification - http://wiki.cloudstack.org/display/RelOps/Cisco+Nexus+1000v+Support+in+CloudStack+-+Functional+Specification Documentation / README for usage instructions - http://wiki.cloudstack.org/display/RelOps/Configuration+instructions+for+CloudStack+Deployment+with+Nexus+vSwitch Conflicts: core/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java --- .../vmware/manager/VmwareManager.java | 2 + .../vmware/resource/VmwareResource.java | 220 +++++--- .../src/com/cloud/configuration/Config.java | 4 + .../hypervisor/vmware/VmwareManagerImpl.java | 92 +++- .../vmware/VmwareServerDiscoverer.java | 57 +- .../cloud/network/PortProfileManagerImpl.java | 9 +- .../cloud/hypervisor/vmware/mo/HostMO.java | 104 +++- .../vmware/mo/HypervisorHostHelper.java | 235 +++++++- .../hypervisor/vmware/util/VmwareContext.java | 509 +++++++++--------- 9 files changed, 848 insertions(+), 384 deletions(-) diff --git a/core/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java b/core/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java index 67c0e6fffa3..3d10adc067f 100755 --- a/core/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java +++ b/core/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java @@ -60,4 +60,6 @@ public interface VmwareManager { boolean beginExclusiveOperation(int timeOutSeconds); void endExclusiveOperation(); + + Map getNexusVSMCredentials(String hostGuid); } diff --git a/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 18c4de2b9ca..3c1848f3064 100755 --- a/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -161,6 +161,7 @@ import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper; import com.cloud.hypervisor.vmware.mo.NetworkDetails; import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType; import com.cloud.hypervisor.vmware.mo.VirtualMachineMO; +import com.cloud.hypervisor.vmware.mo.VirtualSwitchType; import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost; import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostNetworkSummary; import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHostResourceSummary; @@ -258,14 +259,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa protected String _privateNetworkVSwitchName; protected String _publicNetworkVSwitchName; protected String _guestNetworkVSwitchName; - + protected VirtualSwitchType _privateNetworkVSwitchType = VirtualSwitchType.StandardVirtualSwitch; + protected VirtualSwitchType _publicNetworkVSwitchType = VirtualSwitchType.StandardVirtualSwitch; + protected VirtualSwitchType _guestNetworkVSwitchType = VirtualSwitchType.StandardVirtualSwitch; + protected boolean _nexusVSwitch = false; + protected float _cpuOverprovisioningFactor = 1; protected boolean _reserveCpu = false; protected float _memOverprovisioningFactor = 1; protected boolean _reserveMem = false; protected boolean _recycleHungWorker = false; - protected DiskControllerType _rootDiskController = DiskControllerType.ide; + protected DiskControllerType _rootDiskController = DiskControllerType.ide; protected ManagedObjectReference _morHyperHost; protected VmwareContext _serviceContext; @@ -787,27 +792,35 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa int nicMasks = Integer.parseInt(nicMasksStr); nicMasks &= ~(1 << publicNicInfo.first().intValue()); vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMasks)); - - HostMO hostMo = vmMo.getRunningHost(); - List networks = vmMo.getNetworksWithDetails(); - for (NetworkDetails netDetails : networks) { - if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) { - if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) { - cleanupNetwork(hostMo, netDetails); - } - } - } - } - if (s_logger.isInfoEnabled()) { - s_logger.info("ipassoc command on domain router " + privateIpAddress + " completed"); - } - } - - private void plugPublicNic(VirtualMachineMO vmMo, final String vlanId, final String vifMacAddress) throws Exception { + HostMO hostMo = vmMo.getRunningHost(); + List networks = vmMo.getNetworksWithDetails(); + for (NetworkDetails netDetails : networks) { + if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) { + if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) { + cleanupNetwork(hostMo, netDetails); + } + } + } + } + + if (s_logger.isInfoEnabled()) { + s_logger.info("ipassoc command on domain router " + privateIpAddress + " completed"); + } + } + + private void plugPublicNic(VirtualMachineMO vmMo, final String vlanId, final String vifMacAddress) throws Exception { // TODO : probably need to set traffic shaping - Pair networkInfo = HypervisorHostHelper.prepareNetwork(this._publicNetworkVSwitchName, "cloud.public", - vmMo.getRunningHost(), vlanId, null, null, this._ops_timeout, true); + Pair networkInfo = null; + + if(!_nexusVSwitch) { + networkInfo = HypervisorHostHelper.prepareNetwork(this._publicNetworkVSwitchName, "cloud.public", + vmMo.getRunningHost(), vlanId, null, null, this._ops_timeout, true); + } + else { + networkInfo = HypervisorHostHelper.prepareNetwork(this._publicNetworkVSwitchName, "cloud.public", + vmMo.getRunningHost(), vlanId, null, null, this._ops_timeout); + } int nicIndex = allocPublicNicIndex(vmMo); @@ -1674,11 +1687,21 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa Pair switchName = getTargetSwitch(nicTo); String namePrefix = getNetworkNamePrefix(nicTo); + Pair networkInfo = null; + + s_logger.info("Prepare network on vSwitch: " + switchName + " with name prefix: " + namePrefix); - s_logger.info("Prepare network on vSwitch: " + switchName.first() + " with name prefix: " + namePrefix); - return HypervisorHostHelper.prepareNetwork(switchName.first(), namePrefix, hostMo, getVlanInfo(nicTo, switchName.second()), - nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout, - !namePrefix.startsWith("cloud.private")); + if(!_nexusVSwitch) { + networkInfo = HypervisorHostHelper.prepareNetwork(switchName.first(), namePrefix, hostMo, getVlanInfo(nicTo, switchName.second()), + nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout, + !namePrefix.startsWith("cloud.private")); + } + else { + networkInfo = HypervisorHostHelper.prepareNetwork(switchName.first(), namePrefix, hostMo, getVlanInfo(nicTo, switchName.second()), + nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout); + } + + return networkInfo; } // return Pair @@ -4009,7 +4032,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa _privateNetworkVSwitchName = (String) params.get("private.network.vswitch.name"); _publicNetworkVSwitchName = (String) params.get("public.network.vswitch.name"); _guestNetworkVSwitchName = (String) params.get("guest.network.vswitch.name"); - + String value = (String) params.get("cpu.overprovisioning.factor"); if(value != null) _cpuOverprovisioningFactor = Float.parseFloat(value); @@ -4036,42 +4059,70 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa else _rootDiskController = DiskControllerType.ide; - s_logger.info("VmwareResource network configuration info. private vSwitch: " + _privateNetworkVSwitchName + ", public vSwitch: " + _publicNetworkVSwitchName + ", guest network: " - + _guestNetworkVSwitchName); - - return true; - } - - @Override - public String getName() { - return _name; - } - - @Override - public boolean start() { - return true; - } - - @Override - public boolean stop() { - return true; - } - - private VmwareContext getServiceContext() { - return getServiceContext(null); - } - - private void invalidateServiceContext() { - invalidateServiceContext(null); - } - - private VmwareHypervisorHost getHyperHost(VmwareContext context) { - return getHyperHost(context, null); - } - - @Override - public synchronized VmwareContext getServiceContext(Command cmd) { - if (_serviceContext == null) { + value = params.get("vmware.use.nexus.vswitch").toString(); + if(value != null && value.equalsIgnoreCase("true")) + _nexusVSwitch = true; + + value = (String)params.get("private.network.vswitch.type"); + if(value != null && value.equalsIgnoreCase("standard")) + _privateNetworkVSwitchType = VirtualSwitchType.StandardVirtualSwitch; + else if(value != null && value.equalsIgnoreCase("nexus")) + _privateNetworkVSwitchType = VirtualSwitchType.NexusDistributedVirtualSwitch; + else + _privateNetworkVSwitchType = VirtualSwitchType.VMwareDistributedVirtualSwitch; + + value = (String)params.get("public.network.vswitch.type"); + if(value != null && value.equalsIgnoreCase("standard")) + _publicNetworkVSwitchType = VirtualSwitchType.StandardVirtualSwitch; + else if(value != null && value.equalsIgnoreCase("nexus")) + _publicNetworkVSwitchType = VirtualSwitchType.NexusDistributedVirtualSwitch; + else + _publicNetworkVSwitchType = VirtualSwitchType.VMwareDistributedVirtualSwitch; + + value = (String)params.get("guest.network.vswitch.type"); + if(value != null && value.equalsIgnoreCase("standard")) + _guestNetworkVSwitchType = VirtualSwitchType.StandardVirtualSwitch; + else if(value != null && value.equalsIgnoreCase("nexus")) + _guestNetworkVSwitchType = VirtualSwitchType.NexusDistributedVirtualSwitch; + else + _guestNetworkVSwitchType = VirtualSwitchType.VMwareDistributedVirtualSwitch; + + s_logger.info("VmwareResource network configuration info. private vSwitch: " + _privateNetworkVSwitchName + ", public vSwitch: " + _publicNetworkVSwitchName + ", guest network: " + + _guestNetworkVSwitchName); + + return true; + } + + @Override + public String getName() { + return _name; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } + + private VmwareContext getServiceContext() { + return getServiceContext(null); + } + + private void invalidateServiceContext() { + invalidateServiceContext(null); + } + + private VmwareHypervisorHost getHyperHost(VmwareContext context) { + return getHyperHost(context, null); + } + + @Override + public synchronized VmwareContext getServiceContext(Command cmd) { + if (_serviceContext == null) { try { _serviceContext = VmwareContextFactory.create(_vCenterAddress, _username, _password); VmwareHypervisorHost hyperHost = getHyperHost(_serviceContext, cmd); @@ -4096,24 +4147,35 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa if(bRefresh) firewallMo.refreshFirewall(); } - } catch (Exception e) { - s_logger.error("Unable to connect to vSphere server: " + _vCenterAddress, e); - throw new CloudRuntimeException("Unable to connect to vSphere server: " + _vCenterAddress); + } catch (Exception e) { + s_logger.error("Unable to connect to vSphere server: " + _vCenterAddress, e); + throw new CloudRuntimeException("Unable to connect to vSphere server: " + _vCenterAddress); } - } - - return _serviceContext; - } - - @Override - public synchronized void invalidateServiceContext(VmwareContext context) { - if (_serviceContext == null) { - _serviceContext.close(); - } - _serviceContext = null; - } - - @Override + if(_nexusVSwitch) + { + VmwareManager mgr = _serviceContext.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); + Map nexusVSwitchCredentials = mgr.getNexusVSMCredentials(_guid); + if(nexusVSwitchCredentials != null) + { + _serviceContext.registerStockObject("vsmcredentials", nexusVSwitchCredentials); + //_serviceContext.registerStockObject("vsmip", nexusVSwitchCredentials.get("vsmip")); + //_serviceContext.registerStockObject("vsmusername", nexusVSwitchCredentials.get("vsmusername")); + //_serviceContext.registerStockObject("vsmpassword", nexusVSwitchCredentials.get("vsmpassword")); + } + } + } + return _serviceContext; + } + + @Override + public synchronized void invalidateServiceContext(VmwareContext context) { + if (_serviceContext == null) { + _serviceContext.close(); + } + _serviceContext = null; + } + + @Override public VmwareHypervisorHost getHyperHost(VmwareContext context, Command cmd) { if (_morHyperHost.getType().equalsIgnoreCase("HostSystem")) { return new HostMO(context, _morHyperHost); diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index e9d553be74f..844de26f17e 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -242,6 +242,10 @@ public enum Config { VmwarePrivateNetworkVSwitch("Hidden", ManagementServer.class, String.class, "vmware.private.vswitch", null, "Specify the vSwitch on host for private network", null), VmwarePublicNetworkVSwitch("Hidden", ManagementServer.class, String.class, "vmware.public.vswitch", null, "Specify the vSwitch on host for public network", null), VmwareGuestNetworkVSwitch("Hidden", ManagementServer.class, String.class, "vmware.guest.vswitch", null, "Specify the vSwitch on host for guest network", null), + VmwareUseNexusVSwitch("Network", ManagementServer.class, Boolean.class, "vmware.use.nexus.vswitch", "false", "Enable/Disable Cisco Nexus 1000v vSwitch in VMware environment", null), + VmwarePrivateNetworkVSwitchType("Advanced", ManagementServer.class, String.class, "vmware.private.network.vswitch.type", null, "Specify type of (standard/nexus) virtual switch designated for private traffic", null), + VmwarePublicNetworkVSwitchType("Advanced", ManagementServer.class, String.class, "vmware.public.network.vswitch.type", null, "Specify type of (standard/nexus) virtual switch designated for public traffic", null), + VmwareGuestNetworkVSwitchType("Advanced", ManagementServer.class, String.class, "vmware.guest.network.vswitch.type", null, "Specify type of (standard/nexus) virtual switch designated for guest traffic", null), VmwareServiceConsole("Advanced", ManagementServer.class, String.class, "vmware.service.console", "Service Console", "Specify the service console network name(for ESX hosts)", null), VmwareManagementPortGroup("Advanced", ManagementServer.class, String.class, "vmware.management.portgroup", "Management Network", "Specify the management network name(for ESXi hosts)", null), VmwareAdditionalVncPortRangeStart("Advanced", ManagementServer.class, Integer.class, "vmware.additional.vnc.portrange.start", "50000", "Start port number of additional VNC port range", null), diff --git a/server/src/com/cloud/hypervisor/vmware/VmwareManagerImpl.java b/server/src/com/cloud/hypervisor/vmware/VmwareManagerImpl.java index 9a9c71609ec..b7c7abab1e1 100755 --- a/server/src/com/cloud/hypervisor/vmware/VmwareManagerImpl.java +++ b/server/src/com/cloud/hypervisor/vmware/VmwareManagerImpl.java @@ -46,7 +46,9 @@ import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterVO; +import com.cloud.dc.ClusterVSMMapVO; import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.ClusterVSMMapDao; import com.cloud.exception.DiscoveredWithErrorException; import com.cloud.host.HostVO; import com.cloud.host.Status; @@ -66,6 +68,8 @@ import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType; import com.cloud.hypervisor.vmware.mo.VmwareHostType; import com.cloud.hypervisor.vmware.resource.SshHelper; import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.cloud.network.CiscoNexusVSMDeviceVO; +import com.cloud.network.dao.CiscoNexusVSMDeviceDao; import com.cloud.network.router.VirtualNetworkApplianceManager; import com.cloud.org.Cluster.ClusterType; import com.cloud.secstorage.CommandExecLogDao; @@ -114,6 +118,8 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis @Inject CheckPointManager _checkPointMgr; @Inject VirtualNetworkApplianceManager _routerMgr; @Inject SecondaryStorageVmManager _ssvmMgr; + @Inject CiscoNexusVSMDeviceDao _nexusDao; + @Inject ClusterVSMMapDao _vsmMapDao; ConfigurationServer _configServer; @@ -123,6 +129,10 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis String _privateNetworkVSwitchName; String _publicNetworkVSwitchName; String _guestNetworkVSwitchName; + String _privateNetworkVSwitchType; + String _publicNetworkVSwitchType; + String _guestNetworkVSwitchType; + Boolean _nexusVSwitchActive; String _serviceConsoleName; String _managemetPortGroupName; String _defaultSystemVmNicAdapterType = VirtualEthernetCardType.E1000.toString(); @@ -207,22 +217,52 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis throw new ConfigurationException("Unable to find class " + value); } } + + value = configDao.getValue(Config.VmwareUseNexusVSwitch.key()); + if(value == null) { + _nexusVSwitchActive = false; + } + else + { + _nexusVSwitchActive = Boolean.parseBoolean(value); + } _privateNetworkVSwitchName = configDao.getValue(Config.VmwarePrivateNetworkVSwitch.key()); + _privateNetworkVSwitchType = configDao.getValue(Config.VmwarePrivateNetworkVSwitchType.key()); if(_privateNetworkVSwitchName == null) { - _privateNetworkVSwitchName = "vSwitch0"; + if(_privateNetworkVSwitchType == null || _privateNetworkVSwitchType.equalsIgnoreCase("standard")) { + _privateNetworkVSwitchName = "vSwitch0"; + } + else + { + _privateNetworkVSwitchName = "privateEthernetPortProfile"; + } } _publicNetworkVSwitchName = configDao.getValue(Config.VmwarePublicNetworkVSwitch.key()); + _publicNetworkVSwitchType = configDao.getValue(Config.VmwarePublicNetworkVSwitchType.key()); if(_publicNetworkVSwitchName == null) { - _publicNetworkVSwitchName = "vSwitch0"; - } + if(_publicNetworkVSwitchType == null || _publicNetworkVSwitchType.equalsIgnoreCase("standard")) { + _publicNetworkVSwitchName = "vSwitch0"; + } + else + { + _publicNetworkVSwitchName = "publicEthernetPortProfile"; + } + } _guestNetworkVSwitchName = configDao.getValue(Config.VmwareGuestNetworkVSwitch.key()); + _guestNetworkVSwitchType = configDao.getValue(Config.VmwareGuestNetworkVSwitchType.key()); if(_guestNetworkVSwitchName == null) { - _guestNetworkVSwitchName = "vSwitch0"; + if(_guestNetworkVSwitchType == null || _guestNetworkVSwitchType.equalsIgnoreCase("standard")) { + _guestNetworkVSwitchName = "vSwitch0"; + } + else + { + _guestNetworkVSwitchName = "guestEthernetPortProfile"; + } } - + _serviceConsoleName = configDao.getValue(Config.VmwareServiceConsole.key()); if(_serviceConsoleName == null) { _serviceConsoleName = "Service Console"; @@ -352,8 +392,13 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis if(spec.getVlanId() != 0) { vlanId = String.valueOf(spec.getVlanId()); } - - HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false); + + if(!_nexusVSwitchActive) { + HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false); + } + else { + HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000); + } returnedHostList.add(hosts[0]); return returnedHostList; } else if(mor.getType().equals("ClusterComputeResource")) { @@ -386,7 +431,12 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis } // prepare at least one network on the vswitch to enable OVF importing - HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false); + if(!_nexusVSwitchActive) { + HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false); + } + else { + HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000); + } returnedHostList.add(morHost); } return returnedHostList; @@ -410,7 +460,12 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis } // prepare at least one network on the vswitch to enable OVF importing - HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false); + if(!_nexusVSwitchActive) { + HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false); + } + else { + HypervisorHostHelper.prepareNetwork(_privateNetworkVSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000); + } returnedHostList.add(mor); return returnedHostList; } else { @@ -490,6 +545,10 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis params.put("private.network.vswitch.name", _privateNetworkVSwitchName); params.put("public.network.vswitch.name", _publicNetworkVSwitchName); params.put("guest.network.vswitch.name", _guestNetworkVSwitchName); + params.put("private.network.vswitch.type", _privateNetworkVSwitchType); + params.put("public.network.vswitch.type", _publicNetworkVSwitchType); + params.put("guest.network.vswitch.type", _guestNetworkVSwitchType); + params.put("vmware.use.nexus.vswitch", _nexusVSwitchActive); params.put("service.console.name", _serviceConsoleName); params.put("management.portgroup.name", _managemetPortGroupName); params.put("cpu.overprovisioning.factor", _cpuOverprovisioningFactor); @@ -765,6 +824,21 @@ public class VmwareManagerImpl implements VmwareManager, VmwareStorageMount, Lis } } } + + @DB + public Map getNexusVSMCredentials(String hostGuid) { + //Get clusterId from host guid + HostVO host = _hostDao.findByGuid(hostGuid); + ClusterVSMMapVO vsmMapVO = _vsmMapDao.findByClusterId(host.getClusterId()); + CiscoNexusVSMDeviceVO nexusVSM = _nexusDao.findById(vsmMapVO.getVsmId()); + if(nexusVSM == null) + return null; + Map nexusVSMCredentials = new HashMap(); + nexusVSMCredentials.put("vsmip", nexusVSM.getipaddr()); + nexusVSMCredentials.put("vsmusername", nexusVSM.getUserName()); + nexusVSMCredentials.put("vsmpassword", nexusVSM.getPassword()); + return nexusVSMCredentials; + } @Override @DB public boolean processAnswers(long agentId, long seq, Answer[] answers) { diff --git a/server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java b/server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java index 5dc006d3494..ee75b9e175f 100755 --- a/server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java +++ b/server/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java @@ -35,15 +35,16 @@ import com.cloud.exception.DiscoveredWithErrorException; import com.cloud.exception.DiscoveryException; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; -import com.cloud.hypervisor.Hypervisor; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.hypervisor.vmware.manager.VmwareManager; -import com.cloud.hypervisor.vmware.mo.ClusterMO; -import com.cloud.hypervisor.vmware.mo.HostMO; -import com.cloud.hypervisor.vmware.resource.VmwareContextFactory; -import com.cloud.hypervisor.vmware.resource.VmwareResource; -import com.cloud.hypervisor.vmware.util.VmwareContext; -import com.cloud.resource.Discoverer; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.vmware.manager.VmwareManager; +import com.cloud.hypervisor.vmware.mo.ClusterMO; +import com.cloud.hypervisor.vmware.mo.HostMO; +import com.cloud.hypervisor.vmware.resource.VmwareContextFactory; +import com.cloud.hypervisor.vmware.resource.VmwareResource; +import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.cloud.network.dao.CiscoNexusVSMDeviceDao; +import com.cloud.resource.Discoverer; import com.cloud.resource.DiscovererBase; import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceStateAdapter; @@ -72,24 +73,26 @@ public class VmwareServerDiscoverer extends DiscovererBase implements Discoverer @Inject ClusterDetailsDao _clusterDetailsDao; @Inject HostDao _hostDao; @Inject ResourceManager _resourceMgr; - - @Override - public Map> find(long dcId, Long podId, Long clusterId, URI url, - String username, String password, List hostTags) throws DiscoveryException { - - if(s_logger.isInfoEnabled()) - s_logger.info("Discover host. dc: " + dcId + ", pod: " + podId + ", cluster: " + clusterId + ", uri host: " + url.getHost()); - - if(podId == null) { - if(s_logger.isInfoEnabled()) - s_logger.info("No pod is assigned, assuming that it is not for vmware and skip it to next discoverer"); - return null; - } - - ClusterVO cluster = _clusterDao.findById(clusterId); - if(cluster == null || cluster.getHypervisorType() != HypervisorType.VMware) { - if(s_logger.isInfoEnabled()) - s_logger.info("invalid cluster id or cluster is not for VMware hypervisors"); + + @Inject CiscoNexusVSMDeviceDao _nexusDao; + + @Override + public Map> find(long dcId, Long podId, Long clusterId, URI url, + String username, String password, List hostTags) throws DiscoveryException { + + if(s_logger.isInfoEnabled()) + s_logger.info("Discover host. dc: " + dcId + ", pod: " + podId + ", cluster: " + clusterId + ", uri host: " + url.getHost()); + + if(podId == null) { + if(s_logger.isInfoEnabled()) + s_logger.info("No pod is assigned, assuming that it is not for vmware and skip it to next discoverer"); + return null; + } + + ClusterVO cluster = _clusterDao.findById(clusterId); + if(cluster == null || cluster.getHypervisorType() != HypervisorType.VMware) { + if(s_logger.isInfoEnabled()) + s_logger.info("invalid cluster id or cluster is not for VMware hypervisors"); return null; } diff --git a/server/src/com/cloud/network/PortProfileManagerImpl.java b/server/src/com/cloud/network/PortProfileManagerImpl.java index d5272304867..4771865e654 100644 --- a/server/src/com/cloud/network/PortProfileManagerImpl.java +++ b/server/src/com/cloud/network/PortProfileManagerImpl.java @@ -15,8 +15,6 @@ package com.cloud.network; import org.apache.log4j.Logger; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.hypervisor.vmware.manager.VmwareManager; -import com.cloud.utils.component.Inject; import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; @@ -25,12 +23,7 @@ import com.cloud.network.PortProfileVO.PortType; import com.cloud.network.dao.PortProfileDaoImpl; public class PortProfileManagerImpl { - - //@Inject - //static PortProfileDao _portProfileDao; - @Inject - VmwareManager _vmwareMgr; - + private PortProfileDaoImpl _portProfileDao; private static final org.apache.log4j.Logger s_logger = Logger.getLogger(PortProfileManagerImpl.class); diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java index 36221383bc3..8ea4c5f50e6 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HostMO.java @@ -27,7 +27,9 @@ import com.vmware.apputils.vim25.ServiceUtil; import com.vmware.vim25.AboutInfo; import com.vmware.vim25.ClusterDasConfigInfo; import com.vmware.vim25.ComputeResourceSummary; +import com.vmware.vim25.DVPortgroupConfigSpec; import com.vmware.vim25.DatastoreSummary; +import com.vmware.vim25.DistributedVirtualSwitchInfo; import com.vmware.vim25.DynamicProperty; import com.vmware.vim25.HostConfigManager; import com.vmware.vim25.HostConnectInfo; @@ -884,12 +886,104 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { if(s_logger.isTraceEnabled()) s_logger.trace("vCenter API trace - getHyperHostHardwareSummary() done"); - return resourceSummary; + + return resourceSummary; + } + + @Override + public boolean isHyperHostConnected() throws Exception { + HostRuntimeInfo runtimeInfo = (HostRuntimeInfo)_context.getServiceUtil().getDynamicProperty(_mor, "runtime"); + return runtimeInfo.getConnectionState() == HostSystemConnectionState.connected; } - @Override - public boolean isHyperHostConnected() throws Exception { - HostRuntimeInfo runtimeInfo = (HostRuntimeInfo)_context.getServiceUtil().getDynamicProperty(_mor, "runtime"); - return runtimeInfo.getConnectionState() == HostSystemConnectionState.connected; + public DVPortgroupConfigSpec getDvPortGroupSpec(String dvPortGroupName) throws Exception { + DVPortgroupConfigSpec configSpec = null; + String nameProperty = null; + PropertySpec pSpec = new PropertySpec(); + pSpec.setType("DistributedVirtualPortgroup"); + pSpec.setPathSet(new String[] {"summary.name", "config"}); + + TraversalSpec host2DvPortGroupTraversal = new TraversalSpec(); + host2DvPortGroupTraversal.setType("HostSystem"); + host2DvPortGroupTraversal.setPath("network"); + host2DvPortGroupTraversal.setName("host2DvPortgroupTraversal"); + + ObjectSpec oSpec = new ObjectSpec(); + oSpec.setObj(_mor); + oSpec.setSkip(Boolean.TRUE); + oSpec.setSelectSet(new SelectionSpec[] { host2DvPortGroupTraversal }); + + PropertyFilterSpec pfSpec = new PropertyFilterSpec(); + pfSpec.setPropSet(new PropertySpec[] { pSpec }); + pfSpec.setObjectSet(new ObjectSpec[] { oSpec }); + + ObjectContent[] ocs = _context.getService().retrieveProperties( + _context.getServiceContent().getPropertyCollector(), + new PropertyFilterSpec[] { pfSpec }); + + if(ocs != null) { + for(ObjectContent oc : ocs) { + DynamicProperty[] props = oc.getPropSet(); + if(props != null) { + assert(props.length == 2); + for(DynamicProperty prop : props) { + if(prop.getName().equals("config")) { + configSpec = (DVPortgroupConfigSpec) prop.getVal(); + } + else { + nameProperty = prop.getVal().toString(); + } + if(nameProperty.equalsIgnoreCase(dvPortGroupName)) { + return configSpec; + } + } + } + } + } + return null; } + + public ManagedObjectReference getDvPortGroupMor(String dvPortGroupName) throws Exception { + PropertySpec pSpec = new PropertySpec(); + pSpec.setType("DistributedVirtualPortgroup"); + pSpec.setPathSet(new String[] {"summary.name"}); + + TraversalSpec host2DvPortGroupTraversal = new TraversalSpec(); + host2DvPortGroupTraversal.setType("HostSystem"); + host2DvPortGroupTraversal.setPath("network"); + host2DvPortGroupTraversal.setName("host2DvPortgroupTraversal"); + + ObjectSpec oSpec = new ObjectSpec(); + oSpec.setObj(_mor); + oSpec.setSkip(Boolean.TRUE); + oSpec.setSelectSet(new SelectionSpec[] { host2DvPortGroupTraversal }); + + PropertyFilterSpec pfSpec = new PropertyFilterSpec(); + pfSpec.setPropSet(new PropertySpec[] { pSpec }); + pfSpec.setObjectSet(new ObjectSpec[] { oSpec }); + + ObjectContent[] ocs = _context.getService().retrieveProperties( + _context.getServiceContent().getPropertyCollector(), + new PropertyFilterSpec[] { pfSpec }); + + if(ocs != null) { + for(ObjectContent oc : ocs) { + DynamicProperty[] props = oc.getPropSet(); + if(props != null) { + for(DynamicProperty prop : props) { + if(prop.getVal().equals(dvPortGroupName)) + return oc.getObj(); + } + } + } + } + return null; + } + + public boolean hasDvPortGroup(String dvPortGroupName) throws Exception { + ManagedObjectReference morNetwork = getDvPortGroupMor(dvPortGroupName); + if(morNetwork != null) + return true; + return false; + } } 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 1bf531a0ccb..6adb3022620 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java @@ -15,15 +15,29 @@ package com.cloud.hypervisor.vmware.mo; import java.io.File; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import org.apache.log4j.Logger; +import org.mortbay.jetty.servlet.Context; import com.cloud.hypervisor.vmware.util.VmwareContext; 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.VsmCommand.BindingType; +import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.OperationType; +import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.PortProfileType; +import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.SwitchPortMode; import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; +import com.vmware.vim25.BoolPolicy; +import com.vmware.vim25.DVPortgroupConfigSpec; +import com.vmware.vim25.DVSTrafficShapingPolicy; +//import com.vmware.vim25.DistributedVirtualSwitchKeyedOpaqueBlob; import com.vmware.vim25.DynamicProperty; import com.vmware.vim25.HostNetworkTrafficShapingPolicy; import com.vmware.vim25.HostPortGroupSpec; @@ -31,6 +45,7 @@ import com.vmware.vim25.HostVirtualSwitch; import com.vmware.vim25.HttpNfcLeaseDeviceUrl; import com.vmware.vim25.HttpNfcLeaseInfo; import com.vmware.vim25.HttpNfcLeaseState; +import com.vmware.vim25.LongPolicy; import com.vmware.vim25.ManagedObjectReference; import com.vmware.vim25.ObjectContent; import com.vmware.vim25.OvfCreateImportSpecParams; @@ -114,7 +129,225 @@ public class HypervisorHostHelper { return sb.toString(); } - public static Pair prepareNetwork(String vSwitchName, String namePrefix, + public static Map getValidatedVsmCredentials(VmwareContext context) throws Exception, CloudRuntimeException { + 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); + 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 CloudRuntimeException(msg); + } + return vsmCredentials; + } + + public static void createPortProfile(VmwareContext context, String ethPortProfileName, String networkName, Integer vid, Integer networkRateMbps) throws Exception, CloudRuntimeException { + 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, vid.toString())); + params.add(new Pair(OperationType.setrate, networkRateMbps.toString())); + + try { + netconfClient.updatePortProfile(ethPortProfileName, SwitchPortMode.access, params); + } catch(CloudRuntimeException e) { + msg = "Failed to modify ethernet port profile " + ethPortProfileName + " with parameters " + params.toString(); + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } + + try { + netconfClient.addPortProfile(networkName, PortProfileType.vethernet, BindingType.portbindingstatic, SwitchPortMode.access, vid, networkRateMbps); + } catch(CloudRuntimeException e) { + msg = "Failed to add vethernet port profile " + networkName + " with parameters " + params.toString(); + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } + } + + public static void updatePortProfile(VmwareContext context, String ethPortProfileName, Integer vid, Integer networkRateMbps) throws CloudRuntimeException, 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 { + 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, vid.toString())); + params.add(new Pair(OperationType.setrate, networkRateMbps.toString())); + + try { + netconfClient.updatePortProfile(ethPortProfileName, SwitchPortMode.access, params); + } catch(CloudRuntimeException e) { + msg = "Failed to modify ethernet port profile " + ethPortProfileName + " with parameters " + params.toString(); + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } + } + + public static Pair prepareNetwork(String ethPortProfileName, String namePrefix, + HostMO hostMo, String vlanId, Integer networkRateMbps, Integer networkRateMulticastMbps, + long timeOutMs) throws Exception, CloudRuntimeException { + ManagedObjectReference morNetwork = null; + VmwareContext context = hostMo.getContext(); + + ManagedObjectReference morEthernetPortProfile = hostMo.getDvPortGroupMor(ethPortProfileName); + + if (morEthernetPortProfile == null) { + String msg = "Unable to find Ethernet port profile " + ethPortProfileName; + s_logger.error(msg); + throw new Exception(msg); + } + + boolean createGCTag = false; + String networkName; + Integer vid = null; + + if(vlanId != null && !UNTAGGED_VLAN_NAME.equalsIgnoreCase(vlanId)) { + createGCTag = true; + vid = Integer.parseInt(vlanId); + } + + networkName = composeCloudNetworkName(namePrefix, vlanId, networkRateMbps, ethPortProfileName); + + 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); + } + boolean bWaitPortGroupReady = false; + if (!hostMo.hasDvPortGroup(networkName)) { + createPortProfile(context, ethPortProfileName, networkName, vid, networkRateMbps); + bWaitPortGroupReady = true; + } else { + DVPortgroupConfigSpec spec = hostMo.getDvPortGroupSpec(networkName); + if(!isSpecMatch(spec, vid, shapingPolicy)) { + updatePortProfile(context, ethPortProfileName, vid, networkRateMbps); + bWaitPortGroupReady = true; + } + } + //Wait for dvPortGroup on vCenter + if(bWaitPortGroupReady) + morNetwork = waitForDvPortGroupReady(hostMo, networkName, timeOutMs); + else + morNetwork = hostMo.getDvPortGroupMor(networkName); + if (morNetwork == null) { + String msg = "Failed to create guest network " + networkName; + s_logger.error(msg); + throw new Exception(msg); + } + + if(createGCTag) { + NetworkMO networkMo = new NetworkMO(hostMo.getContext(), morNetwork); + networkMo.setCustomFieldValue(CustomFieldConstants.CLOUD_GC, "true"); + } + + return new Pair(morNetwork, networkName); + } + + private static ManagedObjectReference waitForDvPortGroupReady( + HostMO hostMo, String dvPortGroupName, long timeOutMs) throws Exception { + ManagedObjectReference morDvPortGroup = null; + + // if DvPortGroup is just created, we may fail to retrieve it, we + // need to retry + long startTick = System.currentTimeMillis(); + while (System.currentTimeMillis() - startTick <= timeOutMs) { + morDvPortGroup = hostMo.getDvPortGroupMor(dvPortGroupName); + if (morDvPortGroup != null) { + break; + } + + s_logger.info("Waiting for dvPortGroup " + dvPortGroupName + " to be ready"); + Thread.sleep(1000); + } + return morDvPortGroup; + } + + private static boolean isSpecMatch(DVPortgroupConfigSpec spec, Integer vid, + DVSTrafficShapingPolicy shapingPolicy) { + DVSTrafficShapingPolicy currentTrafficShapingPolicy; + currentTrafficShapingPolicy = spec.getDefaultPortConfig().getInShapingPolicy(); + // TODO(sateesh): Extract and compare vendor specific configuration specification as well. + // DistributedVirtualSwitchKeyedOpaqueBlob[] vendorSpecificConfig = spec.getVendorSpecificConfig(); + + assert(currentTrafficShapingPolicy != null); + + LongPolicy averageBandwidth = currentTrafficShapingPolicy.getAverageBandwidth(); + LongPolicy burstSize = currentTrafficShapingPolicy.getBurstSize(); + LongPolicy peakBandwidth = currentTrafficShapingPolicy.getPeakBandwidth(); + BoolPolicy isEnabled = currentTrafficShapingPolicy.getEnabled(); + + if(!isEnabled.getValue()) + return false; + + if(averageBandwidth != null && !averageBandwidth.equals(shapingPolicy.getAverageBandwidth())) { + if(s_logger.isInfoEnabled()) { + s_logger.info("Average bandwidth setting in shaping policy doesn't match with existing setting."); + } + return false; + } else if(burstSize != null && !burstSize.equals(shapingPolicy.getBurstSize())) { + if(s_logger.isInfoEnabled()) { + s_logger.info("Burst size setting in shaping policy doesn't match with existing setting."); + } + return false; + } else if(peakBandwidth != null && !peakBandwidth.equals(shapingPolicy.getPeakBandwidth())) { + if(s_logger.isInfoEnabled()) { + s_logger.info("Peak bandwidth setting in shaping policy doesn't match with existing setting."); + } + return false; + } + + return true; + } + + public static Pair prepareNetwork(String vSwitchName, String namePrefix, HostMO hostMo, String vlanId, Integer networkRateMbps, Integer networkRateMulticastMbps, long timeOutMs, boolean syncPeerHosts) throws Exception { diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java index d72e5c84265..332ecff8bbf 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareContext.java @@ -23,38 +23,38 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ConnectException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSession; - -import org.apache.log4j.Logger; - -import com.cloud.hypervisor.vmware.mo.DatacenterMO; -import com.cloud.hypervisor.vmware.mo.DatastoreFile; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; + +import org.apache.log4j.Logger; + +import com.cloud.hypervisor.vmware.mo.DatacenterMO; +import com.cloud.hypervisor.vmware.mo.DatastoreFile; import com.cloud.utils.ActionDelegate; -import com.vmware.apputils.version.ExtendedAppUtil; -import com.vmware.apputils.vim25.ServiceConnection; -import com.vmware.apputils.vim25.ServiceUtil; -import com.vmware.vim25.ManagedObjectReference; -import com.vmware.vim25.ObjectContent; -import com.vmware.vim25.ObjectSpec; -import com.vmware.vim25.PropertyFilterSpec; -import com.vmware.vim25.PropertySpec; -import com.vmware.vim25.SelectionSpec; -import com.vmware.vim25.ServiceContent; -import com.vmware.vim25.TaskInfo; -import com.vmware.vim25.TraversalSpec; -import com.vmware.vim25.VimPortType; - -public class VmwareContext { +import com.vmware.apputils.version.ExtendedAppUtil; +import com.vmware.apputils.vim25.ServiceConnection; +import com.vmware.apputils.vim25.ServiceUtil; +import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.ObjectContent; +import com.vmware.vim25.ObjectSpec; +import com.vmware.vim25.PropertyFilterSpec; +import com.vmware.vim25.PropertySpec; +import com.vmware.vim25.SelectionSpec; +import com.vmware.vim25.ServiceContent; +import com.vmware.vim25.TaskInfo; +import com.vmware.vim25.TraversalSpec; +import com.vmware.vim25.VimPortType; + +public class VmwareContext { private static final Logger s_logger = Logger.getLogger(VmwareContext.class); private static int MAX_CONNECT_RETRY = 5; @@ -65,230 +65,229 @@ public class VmwareContext { private Map _stockMap = new HashMap(); private int _CHUNKSIZE = 1*1024*1024; // 1M - - - static { - try { - javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; - javax.net.ssl.TrustManager tm = new TrustAllManager(); - trustAllCerts[0] = tm; - javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL"); - sc.init(null, trustAllCerts, null); - javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); - } catch (Exception e) { - s_logger.error("Unexpected exception ", e); - } - } - - public VmwareContext(ExtendedAppUtil appUtil, String address) { - assert(appUtil != null) : "Invalid parameter in constructing VmwareContext object"; - - _appUtil = appUtil; - _serverAddress = address; - } - - public void registerStockObject(String name, Object obj) { - synchronized(_stockMap) { - _stockMap.put(name, obj); - } - } - - public void uregisterStockObject(String name) { - synchronized(_stockMap) { - _stockMap.remove(name); - } - } - - @SuppressWarnings("unchecked") - public T getStockObject(String name) { - synchronized(_stockMap) { - return (T)_stockMap.get(name); - } - } - - public String getServerAddress() { - return _serverAddress; - } - - public ServiceConnection getServiceConnection() { - return _appUtil.getServiceConnection3(); - } - - public VimPortType getService() { - return getServiceConnection().getService(); - } - - public ServiceContent getServiceContent() { - return getServiceConnection().getServiceContent(); - } - - public ServiceUtil getServiceUtil() { - return _appUtil.getServiceUtil3(); - } - - public ManagedObjectReference getRootFolder() { - return getServiceContent().getRootFolder(); - } - - public ManagedObjectReference getHostMorByPath(String inventoryPath) throws Exception { - assert(inventoryPath != null); - - String[] tokens; - if(inventoryPath.startsWith("/")) - tokens = inventoryPath.substring(1).split("/"); - else - tokens = inventoryPath.split("/"); - - ManagedObjectReference mor = getRootFolder(); - for(int i=0; i < tokens.length;i++) { - String token = tokens[i]; - ObjectContent[] ocs; - if(mor.getType().equalsIgnoreCase("Datacenter")) { - PropertySpec pSpec = new PropertySpec(); - pSpec.setType("ManagedEntity"); - pSpec.setPathSet(new String[] { "name" }); - - TraversalSpec dcHostFolderTraversal = new TraversalSpec(); - dcHostFolderTraversal.setType("Datacenter"); - dcHostFolderTraversal.setPath("hostFolder"); - dcHostFolderTraversal.setName("dcHostFolderTraversal"); - - ObjectSpec oSpec = new ObjectSpec(); - oSpec.setObj(mor); - oSpec.setSkip(Boolean.TRUE); - oSpec.setSelectSet(new SelectionSpec[] { dcHostFolderTraversal }); - - PropertyFilterSpec pfSpec = new PropertyFilterSpec(); - pfSpec.setPropSet(new PropertySpec[] { pSpec }); - pfSpec.setObjectSet(new ObjectSpec[] { oSpec }); - ocs = getService().retrieveProperties( - getServiceContent().getPropertyCollector(), - new PropertyFilterSpec[] { pfSpec }); - - } else if(mor.getType().equalsIgnoreCase("Folder")) { - PropertySpec pSpec = new PropertySpec(); - pSpec.setType("ManagedEntity"); - pSpec.setPathSet(new String[] { "name" }); - - TraversalSpec folderChildrenTraversal = new TraversalSpec(); - folderChildrenTraversal.setType("Folder"); - folderChildrenTraversal.setPath("childEntity"); - folderChildrenTraversal.setName("folderChildrenTraversal"); - - ObjectSpec oSpec = new ObjectSpec(); - oSpec.setObj(mor); - oSpec.setSkip(Boolean.TRUE); - oSpec.setSelectSet(new SelectionSpec[] { folderChildrenTraversal }); - - PropertyFilterSpec pfSpec = new PropertyFilterSpec(); - pfSpec.setPropSet(new PropertySpec[] { pSpec }); - pfSpec.setObjectSet(new ObjectSpec[] { oSpec }); - - ocs = getService().retrieveProperties( - getServiceContent().getPropertyCollector(), - new PropertyFilterSpec[] { pfSpec }); - } else if(mor.getType().equalsIgnoreCase("ClusterComputeResource")) { - PropertySpec pSpec = new PropertySpec(); - pSpec.setType("ManagedEntity"); - pSpec.setPathSet(new String[] { "name" }); - - TraversalSpec clusterHostTraversal = new TraversalSpec(); - clusterHostTraversal.setType("ClusterComputeResource"); - clusterHostTraversal.setPath("host"); - clusterHostTraversal.setName("folderChildrenTraversal"); - - ObjectSpec oSpec = new ObjectSpec(); - oSpec.setObj(mor); - oSpec.setSkip(Boolean.TRUE); - oSpec.setSelectSet(new SelectionSpec[] { clusterHostTraversal }); - - PropertyFilterSpec pfSpec = new PropertyFilterSpec(); - pfSpec.setPropSet(new PropertySpec[] { pSpec }); - pfSpec.setObjectSet(new ObjectSpec[] { oSpec }); - - ocs = getService().retrieveProperties( - getServiceContent().getPropertyCollector(), - new PropertyFilterSpec[] { pfSpec }); - } else { - s_logger.error("Invalid inventory path, path element can only be datacenter and folder"); - return null; - } - - if(ocs != null && ocs.length > 0) { - boolean found = false; - for(ObjectContent oc : ocs) { - String name = oc.getPropSet()[0].getVal().toString(); - if(name.equalsIgnoreCase(token) || name.equalsIgnoreCase("host")) { - mor = oc.getObj(); - found = true; - if (name.equalsIgnoreCase("host")) - i--; - break; - } - } - if(!found) { - s_logger.error("Path element points to an un-existing inventory entity"); - return null; - } - } else { - s_logger.error("Path element points to an un-existing inventory entity"); - return null; - } - } - return mor; - } - - // path in format of / - public ManagedObjectReference getDatastoreMorByPath(String inventoryPath) throws Exception { - assert(inventoryPath != null); - - String[] tokens; - if(inventoryPath.startsWith("/")) - tokens = inventoryPath.substring(1).split("/"); - else - tokens = inventoryPath.split("/"); - - if(tokens == null || tokens.length != 2) { - s_logger.error("Invalid datastore inventory path. path: " + inventoryPath); - return null; - } - - DatacenterMO dcMo = new DatacenterMO(this, tokens[0]); - if(dcMo.getMor() == null) { - s_logger.error("Unable to locate the datacenter specified in path: " + inventoryPath); - return null; - } - - return dcMo.findDatastore(tokens[1]); - } - - public void waitForTaskProgressDone(ManagedObjectReference morTask) throws Exception { - while(true) { - TaskInfo tinfo = (TaskInfo)getServiceUtil().getDynamicProperty(morTask, "info"); - Integer progress = tinfo.getProgress(); - if(progress == null) - break; - - if(progress.intValue() >= 100) - break; - - Thread.sleep(1000); - } - } - - public void getFile(String urlString, String localFileFullName) throws Exception { - HttpURLConnection conn = getHTTPConnection(urlString); - - InputStream in = conn.getInputStream(); - OutputStream out = new FileOutputStream(new File(localFileFullName)); - byte[] buf = new byte[_CHUNKSIZE]; - int len = 0; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - in.close(); - out.close(); - } + + static { + try { + javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; + javax.net.ssl.TrustManager tm = new TrustAllManager(); + trustAllCerts[0] = tm; + javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, null); + javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } catch (Exception e) { + s_logger.error("Unexpected exception ", e); + } + } + + public VmwareContext(ExtendedAppUtil appUtil, String address) { + assert(appUtil != null) : "Invalid parameter in constructing VmwareContext object"; + + _appUtil = appUtil; + _serverAddress = address; + } + + public void registerStockObject(String name, Object obj) { + synchronized(_stockMap) { + _stockMap.put(name, obj); + } + } + + public void uregisterStockObject(String name) { + synchronized(_stockMap) { + _stockMap.remove(name); + } + } + + @SuppressWarnings("unchecked") + public T getStockObject(String name) { + synchronized(_stockMap) { + return (T)_stockMap.get(name); + } + } + + public String getServerAddress() { + return _serverAddress; + } + + public ServiceConnection getServiceConnection() { + return _appUtil.getServiceConnection3(); + } + + public VimPortType getService() { + return getServiceConnection().getService(); + } + + public ServiceContent getServiceContent() { + return getServiceConnection().getServiceContent(); + } + + public ServiceUtil getServiceUtil() { + return _appUtil.getServiceUtil3(); + } + + public ManagedObjectReference getRootFolder() { + return getServiceContent().getRootFolder(); + } + + public ManagedObjectReference getHostMorByPath(String inventoryPath) throws Exception { + assert(inventoryPath != null); + + String[] tokens; + if(inventoryPath.startsWith("/")) + tokens = inventoryPath.substring(1).split("/"); + else + tokens = inventoryPath.split("/"); + + ManagedObjectReference mor = getRootFolder(); + for(int i=0; i < tokens.length;i++) { + String token = tokens[i]; + ObjectContent[] ocs; + if(mor.getType().equalsIgnoreCase("Datacenter")) { + PropertySpec pSpec = new PropertySpec(); + pSpec.setType("ManagedEntity"); + pSpec.setPathSet(new String[] { "name" }); + + TraversalSpec dcHostFolderTraversal = new TraversalSpec(); + dcHostFolderTraversal.setType("Datacenter"); + dcHostFolderTraversal.setPath("hostFolder"); + dcHostFolderTraversal.setName("dcHostFolderTraversal"); + + ObjectSpec oSpec = new ObjectSpec(); + oSpec.setObj(mor); + oSpec.setSkip(Boolean.TRUE); + oSpec.setSelectSet(new SelectionSpec[] { dcHostFolderTraversal }); + + PropertyFilterSpec pfSpec = new PropertyFilterSpec(); + pfSpec.setPropSet(new PropertySpec[] { pSpec }); + pfSpec.setObjectSet(new ObjectSpec[] { oSpec }); + ocs = getService().retrieveProperties( + getServiceContent().getPropertyCollector(), + new PropertyFilterSpec[] { pfSpec }); + + } else if(mor.getType().equalsIgnoreCase("Folder")) { + PropertySpec pSpec = new PropertySpec(); + pSpec.setType("ManagedEntity"); + pSpec.setPathSet(new String[] { "name" }); + + TraversalSpec folderChildrenTraversal = new TraversalSpec(); + folderChildrenTraversal.setType("Folder"); + folderChildrenTraversal.setPath("childEntity"); + folderChildrenTraversal.setName("folderChildrenTraversal"); + + ObjectSpec oSpec = new ObjectSpec(); + oSpec.setObj(mor); + oSpec.setSkip(Boolean.TRUE); + oSpec.setSelectSet(new SelectionSpec[] { folderChildrenTraversal }); + + PropertyFilterSpec pfSpec = new PropertyFilterSpec(); + pfSpec.setPropSet(new PropertySpec[] { pSpec }); + pfSpec.setObjectSet(new ObjectSpec[] { oSpec }); + + ocs = getService().retrieveProperties( + getServiceContent().getPropertyCollector(), + new PropertyFilterSpec[] { pfSpec }); + } else if(mor.getType().equalsIgnoreCase("ClusterComputeResource")) { + PropertySpec pSpec = new PropertySpec(); + pSpec.setType("ManagedEntity"); + pSpec.setPathSet(new String[] { "name" }); + + TraversalSpec clusterHostTraversal = new TraversalSpec(); + clusterHostTraversal.setType("ClusterComputeResource"); + clusterHostTraversal.setPath("host"); + clusterHostTraversal.setName("folderChildrenTraversal"); + + ObjectSpec oSpec = new ObjectSpec(); + oSpec.setObj(mor); + oSpec.setSkip(Boolean.TRUE); + oSpec.setSelectSet(new SelectionSpec[] { clusterHostTraversal }); + + PropertyFilterSpec pfSpec = new PropertyFilterSpec(); + pfSpec.setPropSet(new PropertySpec[] { pSpec }); + pfSpec.setObjectSet(new ObjectSpec[] { oSpec }); + + ocs = getService().retrieveProperties( + getServiceContent().getPropertyCollector(), + new PropertyFilterSpec[] { pfSpec }); + } else { + s_logger.error("Invalid inventory path, path element can only be datacenter and folder"); + return null; + } + + if(ocs != null && ocs.length > 0) { + boolean found = false; + for(ObjectContent oc : ocs) { + String name = oc.getPropSet()[0].getVal().toString(); + if(name.equalsIgnoreCase(token) || name.equalsIgnoreCase("host")) { + mor = oc.getObj(); + found = true; + if (name.equalsIgnoreCase("host")) + i--; + break; + } + } + if(!found) { + s_logger.error("Path element points to an un-existing inventory entity"); + return null; + } + } else { + s_logger.error("Path element points to an un-existing inventory entity"); + return null; + } + } + return mor; + } + + // path in format of / + public ManagedObjectReference getDatastoreMorByPath(String inventoryPath) throws Exception { + assert(inventoryPath != null); + + String[] tokens; + if(inventoryPath.startsWith("/")) + tokens = inventoryPath.substring(1).split("/"); + else + tokens = inventoryPath.split("/"); + + if(tokens == null || tokens.length != 2) { + s_logger.error("Invalid datastore inventory path. path: " + inventoryPath); + return null; + } + + DatacenterMO dcMo = new DatacenterMO(this, tokens[0]); + if(dcMo.getMor() == null) { + s_logger.error("Unable to locate the datacenter specified in path: " + inventoryPath); + return null; + } + + return dcMo.findDatastore(tokens[1]); + } + + public void waitForTaskProgressDone(ManagedObjectReference morTask) throws Exception { + while(true) { + TaskInfo tinfo = (TaskInfo)getServiceUtil().getDynamicProperty(morTask, "info"); + Integer progress = tinfo.getProgress(); + if(progress == null) + break; + + if(progress.intValue() >= 100) + break; + + Thread.sleep(1000); + } + } + + public void getFile(String urlString, String localFileFullName) throws Exception { + HttpURLConnection conn = getHTTPConnection(urlString); + + InputStream in = conn.getInputStream(); + OutputStream out = new FileOutputStream(new File(localFileFullName)); + byte[] buf = new byte[_CHUNKSIZE]; + int len = 0; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + in.close(); + out.close(); + } public void uploadFile(String urlString, String localFileFullName) throws Exception { uploadFile(urlString, new File(localFileFullName));