title: pyvmomi: adding a .vmx to inventory as a template and moving to a specific folder
body: <p>EDIT: crossposted to reddit in r/vmware <a href="https://www.reddit.com/r/vmware/comments/3ovpw1/pyvmomi_help_adding_a_vmx_to_inventory_as_a/" rel="nofollow">here</a></p>
  
  <p>I'm new to using the VMWare API, and specifically trying to use pyVmomi. I'm having a really difficult time understanding how it all fits together.
  What I'm trying to accomplish is simply: 1. take a vmx/vmdk that is on a datastore and add it to the inventory (RegisterVM_Task ?) 2. Once in the inventory, convert to template
  If the above 2 can be combined into 1 process, even better.
  Basically all I've been able to do so far is connect to my vcenter endpoint and get a valid connection via pyVmomi.
  Here's the relevant code I have, and have been trying to use without success:</p>
  
  <pre><code>from pyVim.connect import SmartConnect, Disconnect
  from pyVmomi import vim
  import requests
  import ssl
  
  #hacky way around SSL certificate checks in Python 2.7.9+
  requests.packages.urllib3.disable_warnings()
  
  try:
      _create_unverified_https_context = ssl._create_unverified_context
  except AttributeError:
      pass
  else:
      ssl._create_default_https_context = _create_unverified_https_context
  
  # Create connection to vcenter
  
  hostname = 'vcenter'
  username = 'username'
  passwd = 'password'
  
  try:
      si = SmartConnect(host=hostname, user=username, pwd=passwd, port=int(443))
  
  except IOError, e:
      pass
  
  if not si:
      print "Could not connect to the specified host using specified username and password"
  
  # Do stuff
  
  content = si.RetrieveContent()
  si.content.rootFolder.RegisterVM_Task("[dvsolidfire01-vmware-general] packer_images/centos7-vmware-2015-10-13/devit-centos7-vmware-2015-10-13.vmx", "template-test", asTemplate=True)
  </code></pre>
  
  <p>What this does it return a vim.Task:task-XXXXX and then I see the actual task in the vcenter console fail with the follow error: "A specified parameter was not correct: host"
  So if I try to specify a host/cluster string, I get the following error: "TypeError: For "host" expected type vim.HostSystem, but got str"
  OK, so how do I specify a vim.HostSystem type? And is my syntax/process even correct for what I'm trying to attempt?
  This is pretty difficult to figure out without any examples or documentation. Any help would be appreciated! (yes I've seen the pyvmomi samples, but they don't help me here).
  Thanks!</p>
  
  <p>I've achieved exactly what I am describing via PowerCLI with the code below:</p>
  
  <pre><code># Add VMX to Inventory and convert to template
  $vCenter='vcenter'
  $vCenterUser='username'
  $vCenterUserPassword='password'
  
  write-host "Connecting to vCenter Server $vCenter" -foreground green
  Connect-viserver $vCenter -user $vCenterUser -password $vCenterUserPassword -WarningAction 0
  
  # Set Cluster to MyCluster
  $Cluster = "MyCluster"
  
  # Get random ESX host from Cluster list
  $ESXHost = Get-Cluster $Cluster | Get-VMHost | select -First 1
  
  write-host "Adding to inventory and converting to template..." -foreground green
  $VM = New-VM -VMFilePath $VMXFile -VMHost $ESXHost
  $template = Get-VM $VM | Set-VM -ToTemplate -Name "Template-Test" -Confirm:$false
  
  # Move template to Templates folder
  $folder = Get-Folder -ID "Folder-group-v22506"
  Move-Inventory -Item $template -Destination $folder
  </code></pre>
  
  <p>I really need this to be run from a Linux host, so pyvmomi is preferable. I'm not sure why the documentation or usage is so utterly complicated and unintuitive compared to PowerCLI. Any help would be MUCH appreciated here!</p>
  
  <p>Thanks!</p>
  
  <p>SOLVED:
  So I've figured this out and hopefully my trials and frustrations with this will yield something others can use in their search if they stumble across this.</p>
  
  <p>For anyone who may need to do something similar, I've tried to document it as best as possible. The code is relatively simple, in that I'm not using classes or instantiating my own objects (yet). The current version has accomplished what I need (for now). Here we go:</p>
  
  <pre><code>from pyVim.connect import SmartConnect, Disconnect
  from pyVmomi import vim
  import atexit
  import time
  
  def main():
  
      def get_uuid(vmfolder, vmname, vmstatus):
          """
          Get UUID of specific orphaned vm from vmfolder ManagedObject
          """
  
          # if this is a group it will have children, if so iterate through all the VMs in said parent
          if hasattr(vmfolder, 'childEntity'):
              vmlist = vmfolder.childEntity
              for vm in vmlist:
                  summary = vm.summary
                  if summary.config.name == vmname and summary.runtime.connectionState == vmstatus:
                      return summary.config.instanceUuid
  
      # Environment vars
      hostname = 'vcenter'
      username = 'username'
      from getpass import getpass
      passwd = getpass("enter vcenter pass: ")
  
      #hacky workaround to ssl cert warnings in Python 2.7.9+
      #http://www.errr-online.com/index.php/tag/pyvmomi/
      import requests, ssl
      requests.packages.urllib3.disable_warnings()
      try:
          _create_unverified_https_context = ssl._create_unverified_context
      except AttributeError:
          pass
      else:
          ssl._create_default_https_context = _create_unverified_https_context
  
      # Make connection to vcenter
      try:
          si = SmartConnect(host=hostname, user=username, pwd=passwd, port=int(443))
  
      except IOError, e:
          pass
  
      if not si:
          print "Could not connect to the specified host using specified username and password"
  
      atexit.register(Disconnect, si)
  
      # Get vcenter content object
      content = si.RetrieveContent()
  
      # Get list of DCs in vCenter and set datacente to the vim.Datacenter object corresponding to the "DC01" DC
      datacenters = content.rootFolder.childEntity
      for dc in datacenters:
          if dc.name == "DC01":
              datacenter = dc
  
      # Get List of Folders in the "DC01" DC and set tfolder to the vim.Folder object corresponding to the "Templates" folder
      dcfolders = datacenter.vmFolder
      vmfolders = dcfolders.childEntity
      for folder in vmfolders:
          if folder.name == "Templates":
              tfolder = folder
          # Set "Discovered virtual machine" folder to orphan_folder for future use.
          elif folder.name == "Discovered virtual machine":
              orphan_folder = folder
  
      # Get vim.HostSystem object for specific ESX host to place template on
      esxhost = content.searchIndex.FindByDnsName(None, "dvesx10.dev.tsi.lan", vmSearch=False)
  
      # Clean up orphaned VM from packer build (since they don't do it for some reason)
      orphan_uuid = get_uuid(orphan_folder, "devit-centos7-vmware-2015-10-15", "orphaned")
      if orphan_uuid not None:
          vm = content.searchIndex.FindByUuid(None, orphan_uuid, True, True)
          vm.Destroy_Task()
  
      # Wait 10 seconds until VMWare updates that the orphaned item has been deleted before trying to create a new one
      time.sleep(10)
  
      # Wow, we can actually do stuff now! Add the VMX in the specified path to the inventory as a template within the "Templates" folder
      tfolder.RegisterVM_Task("[dvsolidfire01-vmware-general] packer_images/centos7-vmware-2015-10-15/devit-centos7-vmware-2015-10-15.vmx", "CentOS 7 - 2015Q4 - Test", asTemplate=True, host=esxhost)
  
  if __name__ == "__main__":
      main()
  </code></pre>