Command Section: clone
        Clone a VM from a template

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()