def clone(self):
        """
        Command Section: clone
        Clone a VM from a template
        """
        self.config['hostname'] = self.config['hostname'].lower()
        self.config['mem'] = int(self.config['mem'] * 1024)  # convert GB to MB

        print("Cloning %s to new host %s with %sMB RAM..." % (
            self.config['template'],
            self.config['hostname'],
            self.config['mem']
        ))

        # initialize a list to hold our network settings
        ip_settings = list()

        # Get network settings for each IP
        for key, ip_string in enumerate(self.config['ips']):

            # convert ip from string to the 'IPAddress' type
            ip = IPAddress(ip_string)

            # determine network this IP is in
            for network in self.config['networks']:
                if ip in IPNetwork(network):
                    self.config['networks'][network]['ip'] = ip
                    ipnet = IPNetwork(network)
                    self.config['networks'][network]['subnet_mask'] = str(
                        ipnet.netmask
                    )
                    ip_settings.append(self.config['networks'][network])

            # throw an error if we couldn't find a network for this ip
            if not any(d['ip'] == ip for d in ip_settings):
                print("I don't know what network %s is in.  You can supply "
                      "settings for this network in config.yml." % ip_string)
                sys.exit(1)

        # network to place new VM in
        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
        if self.config['destination_folder']:
            destfolder = self.content.searchIndex.FindByInventoryPath(
                self.config['destination_folder']
            )
        else:
            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
        # default 'Resources' pool
        if resource_pool_str == 'Resources' \
                and ('resource_pool' in ip_settings[key]):
            resource_pool_str = ip_settings[key]['resource_pool']

        resource_pool = self.get_resource_pool(cluster, resource_pool_str)

        host_system = self.config['host']
        if host_system != "":
            host_system = self.get_obj([vim.HostSystem],
                                       self.config['host']
                                       )

        if self.debug:
            self.print_debug(
                "Destination cluster",
                cluster
            )
            self.print_debug(
                "Resource pool",
                resource_pool
            )

        if resource_pool is None:
            # use default resource pool of target cluster
            resource_pool = cluster.resourcePool

        datastore = None

        if self.config['datastore']:
            datastore = self.get_obj(
                [vim.Datastore], self.config['datastore'])
        elif 'datastore' in ip_settings[0]:
            datastore = self.get_obj(
                [vim.Datastore],
                ip_settings[0]['datastore'])
        if datastore is None:
            print("Error: Unable to find Datastore '%s'"
                  % ip_settings[0]['datastore'])
            sys.exit(1)

        if self.config['template_folder']:
            template_vm = self.get_vm_failfast(
                self.config['template'],
                False,
                'Template VM',
                path=self.config['template_folder']
            )
        else:
            template_vm = self.get_vm_failfast(
                self.config['template'],
                False,
                'Template VM'
            )

        # Relocation spec
        relospec = vim.vm.RelocateSpec()
        relospec.datastore = datastore
        if host_system:
            relospec.host = host_system

        if resource_pool:
            relospec.pool = resource_pool

        # Networking self.config for VM and guest OS
        devices = []
        adaptermaps = []

        # add existing NIC devices from template to our list of NICs
        # to be created
        try:
            for device in template_vm.config.hardware.device:

                if hasattr(device, 'addressType'):
                    # this is a VirtualEthernetCard, so we'll delete it
                    nic = vim.vm.device.VirtualDeviceSpec()
                    nic.operation = \
                        vim.vm.device.VirtualDeviceSpec.Operation.remove
                    nic.device = device
                    devices.append(nic)
        except:
            # not the most graceful handling, but unable to reproduce
            # user's issues in #57 at this time.
            pass

        # create a Network device for each static IP
        for key, ip in enumerate(ip_settings):
            # VM device
            nic = vim.vm.device.VirtualDeviceSpec()
            # or edit if a device exists
            nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
            nic.device = vim.vm.device.VirtualVmxnet3()
            nic.device.wakeOnLanEnabled = True
            nic.device.addressType = 'assigned'
            # 4000 seems to be the value to use for a vmxnet3 device
            nic.device.key = 4000
            nic.device.deviceInfo = vim.Description()
            nic.device.deviceInfo.label = 'Network Adapter %s' % (key + 1)
            if 'dvportgroup' in ip_settings[key]:
                dvpg = ip_settings[key]['dvportgroup']
                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
                )
                # 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']
                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)

            if 'customspecname' in ip_settings[key]:
                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()
                # 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'])

            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']

            if self.config['domain']:
                guest_map.adapter.dnsDomain = self.config['domain']

            adaptermaps.append(guest_map)

        # DNS settings
        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()
        ident.domain = self.config['domain']
        ident.hostName = vim.vm.customization.FixedName()
        ident.hostName.name = self.config['hostname']

        customspec.nicSettingMap = adaptermaps
        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
        clonespec.config = vmconf
        clonespec.customization = customspec
        clonespec.powerOn = True
        clonespec.template = False

        self.addDisks(template_vm, clonespec)

        if self.debug:
            self.print_debug("CloneSpec", clonespec)

        # fire the clone task
        tasks = [template_vm.Clone(folder=destfolder,
                                   name=self.config['hostname'],
                                   spec=clonespec
                                   )]
        result = self.WaitForTasks(tasks)

        if self.config['post_clone_cmd']:
            try:
                # helper env variables
                os.environ['EZMOMI_CLONE_HOSTNAME'] = self.config['hostname']
                print("Running --post-clone-cmd %s"
                      % self.config['post_clone_cmd'])
                os.system(self.config['post_clone_cmd'])

            except Exception as e:
                print("Error running post-clone command. Exception: %s" % e)
                pass

        # send notification email
        if self.config['mail']:
            self.send_email()
def clone ( self ) : self . config [ 'hostname' ] = self . config [ 'hostname' ] . lower ( ) self . config [ 'mem' ] = int ( self . config [ 'mem' ] * 1024 ) print ( "Cloning %s to new host %s with %sMB RAM..." % ( self . config [ 'template' ] , self . config [ 'hostname' ] , self . config [ 'mem' ] ) ) ip_settings = list ( ) for key , ip_string in enumerate ( self . config [ 'ips' ] ) : ip = IPAddress ( ip_string ) for network in self . config [ 'networks' ] : if ip in IPNetwork ( network ) : self . config [ 'networks' ] [ network ] [ 'ip' ] = ip ipnet = IPNetwork ( network ) self . config [ 'networks' ] [ network ] [ 'subnet_mask' ] = str ( ipnet . netmask ) ip_settings . append ( self . config [ 'networks' ] [ network ] ) if not any ( d [ 'ip' ] == ip for d in ip_settings ) : print ( "I don't know what network %s is in.  You can supply " "settings for this network in config.yml." % ip_string ) sys . exit ( 1 ) self . get_obj ( [ vim . Network ] , ip_settings [ 0 ] [ 'network' ] ) datacenter = self . get_obj ( [ vim . Datacenter ] , ip_settings [ 0 ] [ 'datacenter' ] ) if self . config [ 'destination_folder' ] : destfolder = self . content . searchIndex . FindByInventoryPath ( self . config [ 'destination_folder' ] ) else : destfolder = datacenter . vmFolder cluster = self . get_obj ( [ vim . ClusterComputeResource ] , ip_settings [ 0 ] [ 'cluster' ] ) resource_pool_str = self . config [ 'resource_pool' ] if resource_pool_str == 'Resources' and ( 'resource_pool' in ip_settings [ key ] ) : resource_pool_str = ip_settings [ key ] [ 'resource_pool' ] resource_pool = self . get_resource_pool ( cluster , resource_pool_str ) host_system = self . config [ 'host' ] if host_system != "" : host_system = self . get_obj ( [ vim . HostSystem ] , self . config [ 'host' ] ) if self . debug : self . print_debug ( "Destination cluster" , cluster ) self . print_debug ( "Resource pool" , resource_pool ) if resource_pool is None : resource_pool = cluster . resourcePool datastore = None if self . config [ 'datastore' ] : datastore = self . get_obj ( [ vim . Datastore ] , self . config [ 'datastore' ] ) elif 'datastore' in ip_settings [ 0 ] : datastore = self . get_obj ( [ vim . Datastore ] , ip_settings [ 0 ] [ 'datastore' ] ) if datastore is None : print ( "Error: Unable to find Datastore '%s'" % ip_settings [ 0 ] [ 'datastore' ] ) sys . exit ( 1 ) if self . config [ 'template_folder' ] : template_vm = self . get_vm_failfast ( self . config [ 'template' ] , False , 'Template VM' , path = self . config [ 'template_folder' ] ) else : template_vm = self . get_vm_failfast ( self . config [ 'template' ] , False , 'Template VM' ) relospec = vim . vm . RelocateSpec ( ) relospec . datastore = datastore if host_system : relospec . host = host_system if resource_pool : relospec . pool = resource_pool devices = [ ] adaptermaps = [ ] try : for device in template_vm . config . hardware . device : if hasattr ( device , 'addressType' ) : nic = vim . vm . device . VirtualDeviceSpec ( ) nic . operation = vim . vm . device . VirtualDeviceSpec . Operation . remove nic . device = device devices . append ( nic ) except : pass for key , ip in enumerate ( ip_settings ) : nic = vim . vm . device . VirtualDeviceSpec ( ) nic . operation = vim . vm . device . VirtualDeviceSpec . Operation . add nic . device = vim . vm . device . VirtualVmxnet3 ( ) nic . device . wakeOnLanEnabled = True nic . device . addressType = 'assigned' nic . device . key = 4000 nic . device . deviceInfo = vim . Description ( ) nic . device . deviceInfo . label = 'Network Adapter %s' % ( key + 1 ) if 'dvportgroup' in ip_settings [ key ] : dvpg = ip_settings [ key ] [ 'dvportgroup' ] nic . device . deviceInfo . summary = dvpg pg_obj = self . get_obj ( [ vim . dvs . DistributedVirtualPortgroup ] , dvpg ) dvs_port_connection = vim . dvs . PortConnection ( ) dvs_port_connection . portgroupKey = pg_obj . key dvs_port_connection . switchUuid = ( pg_obj . config . distributedVirtualSwitch . uuid ) 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' ] 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 ) if 'customspecname' in ip_settings [ key ] : 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 ( ) 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' ] ) 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' ] if self . config [ 'domain' ] : guest_map . adapter . dnsDomain = self . config [ 'domain' ] adaptermaps . append ( guest_map ) 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 ident = vim . vm . customization . LinuxPrep ( ) ident . domain = self . config [ 'domain' ] ident . hostName = vim . vm . customization . FixedName ( ) ident . hostName . name = self . config [ 'hostname' ] customspec . nicSettingMap = adaptermaps customspec . identity = ident vmconf = vim . vm . ConfigSpec ( ) vmconf . numCPUs = self . config [ 'cpus' ] vmconf . memoryMB = self . config [ 'mem' ] vmconf . cpuHotAddEnabled = True vmconf . memoryHotAddEnabled = True vmconf . deviceChange = devices clonespec = vim . vm . CloneSpec ( ) clonespec . location = relospec clonespec . config = vmconf clonespec . customization = customspec clonespec . powerOn = True clonespec . template = False self . addDisks ( template_vm , clonespec ) if self . debug : self . print_debug ( "CloneSpec" , clonespec ) tasks = [ template_vm . Clone ( folder = destfolder , name = self . config [ 'hostname' ] , spec = clonespec ) ] result = self . WaitForTasks ( tasks ) if self . config [ 'post_clone_cmd' ] : try : os . environ [ 'EZMOMI_CLONE_HOSTNAME' ] = self . config [ 'hostname' ] print ( "Running --post-clone-cmd %s" % self . config [ 'post_clone_cmd' ] ) os . system ( self . config [ 'post_clone_cmd' ] ) except Exception as e : print ( "Error running post-clone command. Exception: %s" % e ) pass if self . config [ 'mail' ] : self . send_email ( )
Command Section: clone
        Clone a VM from a template