From 4677f896431af16854c61209c7bd0ef1d6a738c6 Mon Sep 17 00:00:00 2001 From: Sumit Murari Date: Wed, 14 Jun 2017 19:11:57 +0530 Subject: [PATCH 1/3] Added support for distributedvirtualportgroup and customization specifications. --- ezmomi/ezmomi.py | 139 ++++++++++++++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 50 deletions(-) diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index edc6c81..344a8c0 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -162,6 +162,7 @@ def clone(self): self.config['hostname'] = self.config['hostname'].lower() self.config['mem'] = int(self.config['mem'] * 1024) # convert GB to MB + template_path = self.config['default_templates_path'] print "Cloning %s to new host %s with %sMB RAM..." % ( self.config['template'], self.config['hostname'], @@ -197,14 +198,14 @@ def clone(self): self.get_obj([vim.Network], ip_settings[0]['network']) datacenter = self.get_obj([vim.Datacenter], ip_settings[0]['datacenter'] - ) + ) # get the folder where VMs are kept for this datacenter destfolder = datacenter.vmFolder cluster = self.get_obj([vim.ClusterComputeResource], ip_settings[0]['cluster'] - ) + ) resource_pool_str = self.config['resource_pool'] # resource_pool setting in config file takes priority over the @@ -219,7 +220,7 @@ def clone(self): if host_system != "": host_system = self.get_obj([vim.HostSystem], self.config['host'] - ) + ) if self.debug: self.print_debug( @@ -245,11 +246,20 @@ def clone(self): % ip_settings[0]['datastore'] sys.exit(1) - template_vm = self.get_vm_failfast( - self.config['template'], - False, - 'Template VM' - ) + if template_path: + print("Template_path " + template_path) + template_vm = self.get_vm_failfast( + self.config['template'], + False, + 'Template VM', + path=template_path + ) + else: + template_vm = self.get_vm_failfast( + self.config['template'], + False, + 'Template VM' + ) # Relocation spec relospec = vim.vm.RelocateSpec() @@ -294,52 +304,59 @@ def clone(self): nic.device.key = 4000 nic.device.deviceInfo = vim.Description() nic.device.deviceInfo.label = 'Network Adapter %s' % (key + 1) - nic.device.deviceInfo.summary = ip_settings[key]['network'] - nic.device.backing = ( - vim.vm.device.VirtualEthernetCard.NetworkBackingInfo() - ) - nic.device.backing.network = ( - self.get_obj([vim.Network], ip_settings[key]['network']) - ) - nic.device.backing.deviceName = ip_settings[key]['network'] - nic.device.backing.useAutoDetect = False + if 'distributedvirtualportgroup' in ip_settings[key]: + dvpg = ip_settings[key]['distributedvirtualportgroup'] + nic.device.deviceInfo.summary = dvpg + pg_obj = self.get_obj([vim.dvs.DistributedVirtualPortgroup], dvpg) # noqa + dvs_port_connection = vim.dvs.PortConnection() + dvs_port_connection.portgroupKey = pg_obj.key + dvs_port_connection.switchUuid = pg_obj.config.distributedVirtualSwitch.uuid + nic.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo() + nic.device.backing.port = dvs_port_connection + else: + nic.device.deviceInfo.summary = ip_settings[key]['network'] + nic.device.backing = ( + vim.vm.device.VirtualEthernetCard.NetworkBackingInfo() + ) + nic.device.backing.network = ( + self.get_obj([vim.Network], ip_settings[key]['network']) + ) + nic.device.backing.deviceName = ip_settings[key]['network'] + nic.device.backing.useAutoDetect = False + nic.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo() nic.device.connectable.startConnected = True nic.device.connectable.allowGuestControl = True devices.append(nic) - # guest NIC settings, i.e. 'adapter map' - guest_map = vim.vm.customization.AdapterMapping() - guest_map.adapter = vim.vm.customization.IPSettings() + if 'customspecname' in ip_settings[key]: + customspec = self.get_customization_settings(ip_settings[key]['customspecname']) + guest_map = customspec.nicSettingMap[0] + else: + customspec = vim.vm.customization.Specification() + # guest NIC settings, i.e. 'adapter map' + guest_map = vim.vm.customization.AdapterMapping() + guest_map.adapter = vim.vm.customization.IPSettings() guest_map.adapter.ip = vim.vm.customization.FixedIp() guest_map.adapter.ip.ipAddress = str(ip_settings[key]['ip']) - guest_map.adapter.subnetMask = str(ip_settings[key]['subnet_mask']) - # these may not be set for certain IPs - try: + if 'subnet_mask' in ip_settings[key]: + guest_map.adapter.subnetMask = str(ip_settings[key]['subnet_mask']) + + if 'gateway' in ip_settings[key]: guest_map.adapter.gateway = ip_settings[key]['gateway'] - except: - pass - try: + if self.config['domain']: guest_map.adapter.dnsDomain = self.config['domain'] - except: - pass adaptermaps.append(guest_map) - # VM config spec - vmconf = vim.vm.ConfigSpec() - vmconf.numCPUs = self.config['cpus'] - vmconf.memoryMB = self.config['mem'] - vmconf.cpuHotAddEnabled = True - vmconf.memoryHotAddEnabled = True - vmconf.deviceChange = devices - # DNS settings - globalip = vim.vm.customization.GlobalIPSettings() - globalip.dnsServerList = self.config['dns_servers'] - globalip.dnsSuffixList = self.config['domain'] + if 'dns_servers' in self.config: + globalip = vim.vm.customization.GlobalIPSettings() + globalip.dnsServerList = self.config['dns_servers'] + globalip.dnsSuffixList = self.config['domain'] + customspec.globalIPSettings = globalip # Hostname settings ident = vim.vm.customization.LinuxPrep() @@ -347,11 +364,18 @@ def clone(self): ident.hostName = vim.vm.customization.FixedName() ident.hostName.name = self.config['hostname'] - customspec = vim.vm.customization.Specification() + #customspec = vim.vm.customization.Specification() customspec.nicSettingMap = adaptermaps - customspec.globalIPSettings = globalip customspec.identity = ident + # VM config spec + vmconf = vim.vm.ConfigSpec() + vmconf.numCPUs = self.config['cpus'] + vmconf.memoryMB = self.config['mem'] + vmconf.cpuHotAddEnabled = True + vmconf.memoryHotAddEnabled = True + vmconf.deviceChange = devices + # Clone spec clonespec = vim.vm.CloneSpec() clonespec.location = relospec @@ -705,6 +729,13 @@ def send_email(self): s = smtplib.SMTP(mailserver) s.sendmail(mailfrom, [mailto], msg.as_string()) s.quit() + def get_customization_settings(self, customization_settings_name): + ''' + Fetch the customization specific settings. + ''' + return self.content.customizationSpecManager.GetCustomizationSpec( + customization_settings_name + ).spec def get_resource_pool(self, cluster, pool_name): """ @@ -731,11 +762,15 @@ def get_resource_pool(self, cluster, pool_name): return pool_obj - def get_obj(self, vimtype, name, return_all=False): + def get_obj(self, vimtype, name, return_all=False, path=""): """Get the vsphere object associated with a given text name or MOID""" obj = list() - container = self.content.viewManager.CreateContainerView( - self.content.rootFolder, vimtype, True) + if path: + obj_folder = self.content.searchIndex.FindByInventoryPath(path) + container = self.content.viewManager.CreateContainerView(obj_folder, vimtype, True) + else: + container = self.content.viewManager.CreateContainerView( + self.content.rootFolder, vimtype, True) for c in container.view: if name in [c.name, c._GetMoId()]: @@ -778,20 +813,24 @@ def get_host_system_failfast( return hs - def get_vm(self, name): + def get_vm(self, name, path=""): """Get a VirtualMachine object""" - return self.get_obj([vim.VirtualMachine], name) + if path: + return self.get_obj([vim.VirtualMachine], name, path=path) + else: + return self.get_obj([vim.VirtualMachine], name) - def get_vm_failfast(self, name, verbose=False, vm_term='VM'): + def get_vm_failfast(self, name, verbose=False, vm_term='VM', path=""): """ Get a VirtualMachine object fail fast if the object isn't a valid reference """ if verbose: print "Finding VirtualMachine named %s..." % name - - vm = self.get_vm(name) - + if path: + vm = self.get_vm(name,path=path) + else: + vm = self.get_vm(name) if vm is None: print "Error: %s '%s' does not exist" % (vm_term, name) sys.exit(1) From 1f930fb7e5a7fa0d0cac15827b355c2731ea1044 Mon Sep 17 00:00:00 2001 From: Sumit Murari Date: Thu, 15 Jun 2017 09:53:41 +0530 Subject: [PATCH 2/3] Added config paramters for new features --- ezmomi/config/config.yml.example | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ezmomi/config/config.yml.example b/ezmomi/config/config.yml.example index 62e6864..93c0b6b 100644 --- a/ezmomi/config/config.yml.example +++ b/ezmomi/config/config.yml.example @@ -16,6 +16,8 @@ password: "mypass#123" # New VM defaults cpus: 1 mem: 3 + +default_templates_path: "Specific_folder_for_the_template_This_is_option_like_/DC/folder1/folder2" #Optional template: centos65 domain: example @@ -29,6 +31,8 @@ networks: datastore: 'Mystore 1' network: 'My Internal Net' gateway: '172.10.16.1' + customspecname: 'Customization_specification_name_if_none_this_field is optional' + distributedvirtualportgroup: 'This_field_is_also_optional' '192.168.24.50/24': datacenter: 'Foocenter' From e726f4d132c63cf9ca34d29cc3cbd23ce204e19b Mon Sep 17 00:00:00 2001 From: Sumit Murari Date: Fri, 16 Jun 2017 09:20:49 +0530 Subject: [PATCH 3/3] pep 8 compliant now. --- ezmomi/ezmomi.py | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index 344a8c0..8554207 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -198,14 +198,14 @@ def clone(self): self.get_obj([vim.Network], ip_settings[0]['network']) datacenter = self.get_obj([vim.Datacenter], ip_settings[0]['datacenter'] - ) + ) # get the folder where VMs are kept for this datacenter destfolder = datacenter.vmFolder cluster = self.get_obj([vim.ClusterComputeResource], ip_settings[0]['cluster'] - ) + ) resource_pool_str = self.config['resource_pool'] # resource_pool setting in config file takes priority over the @@ -220,7 +220,7 @@ def clone(self): if host_system != "": host_system = self.get_obj([vim.HostSystem], self.config['host'] - ) + ) if self.debug: self.print_debug( @@ -247,7 +247,6 @@ def clone(self): sys.exit(1) if template_path: - print("Template_path " + template_path) template_vm = self.get_vm_failfast( self.config['template'], False, @@ -255,7 +254,7 @@ def clone(self): path=template_path ) else: - template_vm = self.get_vm_failfast( + template_vm = self.get_vm_failfast( self.config['template'], False, 'Template VM' @@ -310,8 +309,15 @@ def clone(self): pg_obj = self.get_obj([vim.dvs.DistributedVirtualPortgroup], dvpg) # noqa dvs_port_connection = vim.dvs.PortConnection() dvs_port_connection.portgroupKey = pg_obj.key - dvs_port_connection.switchUuid = pg_obj.config.distributedVirtualSwitch.uuid - nic.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo() + dvs_port_connection.switchUuid = ( + pg_obj.config.distributedVirtualSwitch.uuid + ) + # did it to get pep8 + e_nic = vim.vm.device.VirtualEthernetCard + nic.device.backing = ( + e_nic.DistributedVirtualPortBackingInfo() + ) + nic.device.backing.port = dvs_port_connection else: nic.device.deviceInfo.summary = ip_settings[key]['network'] @@ -330,7 +336,10 @@ def clone(self): devices.append(nic) if 'customspecname' in ip_settings[key]: - customspec = self.get_customization_settings(ip_settings[key]['customspecname']) + custom_spec_name = ip_settings[key]['customspecname'] + customspec = ( + self.get_customization_settings(custom_spec_name) + ) guest_map = customspec.nicSettingMap[0] else: customspec = vim.vm.customization.Specification() @@ -341,7 +350,9 @@ def clone(self): guest_map.adapter.ip.ipAddress = str(ip_settings[key]['ip']) if 'subnet_mask' in ip_settings[key]: - guest_map.adapter.subnetMask = str(ip_settings[key]['subnet_mask']) + guest_map.adapter.subnetMask = ( + str(ip_settings[key]['subnet_mask']) + ) if 'gateway' in ip_settings[key]: guest_map.adapter.gateway = ip_settings[key]['gateway'] @@ -364,7 +375,6 @@ def clone(self): ident.hostName = vim.vm.customization.FixedName() ident.hostName.name = self.config['hostname'] - #customspec = vim.vm.customization.Specification() customspec.nicSettingMap = adaptermaps customspec.identity = ident @@ -729,6 +739,7 @@ def send_email(self): s = smtplib.SMTP(mailserver) s.sendmail(mailfrom, [mailto], msg.as_string()) s.quit() + def get_customization_settings(self, customization_settings_name): ''' Fetch the customization specific settings. @@ -767,7 +778,9 @@ def get_obj(self, vimtype, name, return_all=False, path=""): obj = list() if path: obj_folder = self.content.searchIndex.FindByInventoryPath(path) - container = self.content.viewManager.CreateContainerView(obj_folder, vimtype, True) + container = self.content.viewManager.CreateContainerView( + obj_folder, vimtype, True + ) else: container = self.content.viewManager.CreateContainerView( self.content.rootFolder, vimtype, True) @@ -828,7 +841,7 @@ def get_vm_failfast(self, name, verbose=False, vm_term='VM', path=""): if verbose: print "Finding VirtualMachine named %s..." % name if path: - vm = self.get_vm(name,path=path) + vm = self.get_vm(name, path=path) else: vm = self.get_vm(name) if vm is None: