EDIT: crossposted to reddit in r/vmware here
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:
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)
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!
I've achieved exactly what I am describing via PowerCLI with the code below:
# 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
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!
Thanks!
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.
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:
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()