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