Deploying OVF files on ESX

9,774 views
Skip to first unread message

Nikunj

unread,
Dec 12, 2011, 4:00:07 AM12/12/11
to pysphere, nikunj....@emc.com
Hi,

I am automating tasks on my vm infrastructure.
I want to deploy OVF files on the ESX. And do further operations on
them( on/off/status/suspend etc.).
How is it possible?

Any ideas?

Thanks
Nikunj

Seba

unread,
Dec 12, 2011, 7:45:18 PM12/12/11
to pysphere, nikunj....@emc.com

Hi Nikunj

I've just come from holiday and seen your message. I'm at home right
now and I don't have any ESXs to test against. Tomorrow at the office
I'll try to write some code snippet that might guide you in your task.
I've never worked with OVF files before but I'll see what I can do.

Regards,

Sebastian.

Seba

unread,
Dec 13, 2011, 2:34:13 PM12/13/11
to pysphere
Ok, I wrote something but in certain point something weird happens,
I'm crashing my ESXi 5.0 server.

According to the vSphere API documentation this is the process for
importing a vm or virtual appliance from an OVF:

"""
(via the OvfManager managed object)
Import

For the import scenario, the typical sequence of events is as follows:
The client calls parseDescriptor to obtain information about the OVF
descriptor. This typically includes information (such as a list of
networks) that must be mapped to VI infrastructure entities.

The OVF descriptor is validated against the OVF Specification, and any
errors or warnings are returned as part of the ParseResult. For
example, the parser might encounter a section marked required that it
does not understand, or the XML descriptor might be malformed.

The client decides on network mappings, datastore, properties etc. It
then calls createImportSpec to obtain the parameters needed to call
ResourcePool.importVApp.

If any warnings are present, the client will review these and decide
whether to proceed or not. If errors are present, the ImportSpec will
be missing, so the client is forced to give up or fix the problems and
then try again.

The client now calls ResourcePool.importVApp, passing the ImportSpec
as a parameter. This will create the virtual machines and VirtualApp
objects in VI and return locations to which the files of the entity
can be uploaded. It also returns a lease that controls the duration of
the lock taken on the newly created inventory objects. When all files
have been uploaded, the client must release this lease.
"""
And this is the ImportVApp documentation:
"""
ImportVApp

Creates a new entity in this resource pool. The import process
consists of two steps:
Create the VMs and/or vApps that make up the entity.
Upload virtual disk contents.
In step 1, the client must wait for the server to create all inventory
objects. It does that by monitoring the state property on the
HttpNfcLease object returned from this call. When the server is done
creating objects, the lease will change to the ready state, and step 2
begins. If an error occurs while the server is creating inventory
objects, the lease will change to the error state, and the import
process is aborted.
In step 2, the client uploads disk contents using the URLs provided in
the info property of the lease. The client must call
HttpNfcLeaseProgress on the lease periodically to keep the lease alive
and report progress to the server. Failure to do so will cause the
lease to time out, and the import process will be aborted.

When the client is done uploading disks, it completes the lease by
calling HttpNfcLeaseComplete. The client can also abort the import
process by calling HttpNfcLeaseAbort.

If the import process fails, is aborted, or times out, all created
inventory objects are removed, including all virtual disks.

This operation only works if the folder's childType includes
VirtualMachine.

Depending on the properties of the virtual machine bring imported,
additional privileges may be required. See CreateVM_Task for a
description of these privileges.
"""

The script I'll show later does all this up to the point where I get
the HttpNfcLease, I keep querying its state while it is on
"initializing" (meaning that the server is still creating the new vm
directory and file structure) and then suddenly the server crashes.

I did the same thing manually with the vSphere Client tool, and it
works all right. However got soap requests, and responses traces from
both, pysphere and the vSphere Client but I haven't found anything
wrong there.

Nkunj, can you run the following code using a test environment (DON'T
USE PRODUCTION as you might crash the server) an confirm I you crash
it too?
Of course you have to modify the server connection settings and the
following parameters with your values:
RESOURCE_POOL = "/Resources"
OVF_FILE = r"C:\FreeSCO\FreeSCO-043.ovf"
HOST = "localhost.localdomain"
DATASTORE = "datastore1"
NETWORK_NAME = "VM Network"
VAPP_NAME = "My New VM2"

Here's the code:

from pysphere import VIServer, VIProperty
from pysphere.resources import VimService_services as VI

def get_descriptor(ovf_path):
fh = open(ovf_path, "r")
ovf_descriptor = fh.read()
fh.close()
return ovf_descriptor

def parse_descriptor(ovf_descriptor):
ovf_manager = s._do_service_content.OvfManager
request = VI.ParseDescriptorRequestMsg()
_this =request.new__this(ovf_manager)
_this.set_attribute_type(ovf_manager.get_attribute_type())
request.set_element__this(_this)
request.set_element_ovfDescriptor(ovf_descriptor)
pdp = request.new_pdp()
pdp.set_element_locale("")
pdp.set_element_deploymentOption("")
request.set_element_pdp(pdp)
return s._proxy.ParseDescriptor(request)._returnval

def validate_host(host_name, ovf_descriptor):
hosts = s.get_hosts()
host = hosts.get(host_name)
if not host:
raise ValueError("invalid ESX host name")
ovf_manager = s._do_service_content.OvfManager
request = VI.ValidateHostRequestMsg()
_this =request.new__this(ovf_manager)
_this.set_attribute_type(ovf_manager.get_attribute_type())
request.set_element__this(_this)
request.set_element_ovfDescriptor(ovf_descriptor)
h = request.new_host(host)
h.set_attribute_type(host.get_attribute_type())
request.set_element_host(h)
vhp = request.new_vhp()
vhp.set_element_locale("")
vhp.set_element_deploymentOption("")
request.set_element_vhp(vhp)
return s._proxy.ValidateHost(request)._returnval

def find_datastore_by_name(datastore_name):
ret = None
for dc in s._get_datacenters().values():
dc_properties = VIProperty(s, dc)
for ds in dc_properties.datastore:
if ds.name == datastore_name:
ret = ds._obj
break
if ret:
break
if not ret:
raise ValueError("Couldn't find datastore '%s'" %
(datastore_name))
return ret

def find_network_by_name(network_name):
ret = None
for dc in s._get_datacenters().values():
dc_properties = VIProperty(s, dc)
for nw in dc_properties.network:
if nw.name == network_name:
ret = nw._obj
break
if ret:
break
if not ret:
raise ValueError("Couldn't find network '%s'" %
(network_name))
return ret

def find_vmfolder_by_name(folder_name):
ret = None
for dc in s._get_datacenters().values():
dc_properties = VIProperty(s, dc)
if dc_properties.vmFolder.name == folder_name:
return dc_properties.vmFolder._obj
raise ValueError("Couldn't find network '%s'" % (network_name))

def create_import_spec(resource_pool_mor,
datastore,
ovf_descriptor,
name,
host=None,
network=None,
ip_allocation_policy="fixedPolicy",
ip_protocol="IPv4",
disk_provisioning="flat"
):
#get the host MOR
if host:
hosts = s.get_hosts()
host = hosts.get(host)
if not host:
raise ValueError("invalid ESX host name")
#get the network MOR:
if network:
network_mor = find_network_by_name(network)

#get the datastore MOR
datastore_mor = find_datastore_by_name(datastore)

ovf_manager = s._do_service_content.OvfManager
request = VI.CreateImportSpecRequestMsg()
_this =request.new__this(ovf_manager)
_this.set_attribute_type(ovf_manager.get_attribute_type())
request.set_element__this(_this)

request.set_element_ovfDescriptor(ovf_descriptor)

rp = request.new_resourcePool(resource_pool_mor)
rp.set_attribute_type(resource_pool_mor.get_attribute_type())
request.set_element_resourcePool(rp)

ds = request.new_datastore(datastore_mor)
ds.set_attribute_type(datastore_mor.get_attribute_type())
request.set_element_datastore(ds)

cisp = request.new_cisp()
cisp.set_element_entityName(name)
cisp.set_element_locale("")
cisp.set_element_deploymentOption("")
if host:
h = cisp.new_hostSystem(host)
h.set_attribute_type(host.get_attribute_type())
cisp.set_element_hostSystem(h)
if network:
network_mapping = cisp.new_networkMapping()
network_mapping.set_element_name(network)
n_mor = network_mapping.new_network(network_mor)
n_mor.set_attribute_type(network_mor.get_attribute_type())
network_mapping.set_element_network(n_mor)

network_mapping2 = cisp.new_networkMapping()
network_mapping2.set_element_name("Internal")
n_mor = network_mapping.new_network(network_mor)
n_mor.set_attribute_type(network_mor.get_attribute_type())
network_mapping2.set_element_network(n_mor)

cisp.set_element_networkMapping([network_mapping,
network_mapping2])
if ip_allocation_policy:
cisp.set_element_ipAllocationPolicy(ip_allocation_policy)
if ip_protocol:
cisp.set_element_ipProtocol(ip_protocol)
if disk_provisioning:
cisp.set_element_diskProvisioning(disk_provisioning)

request.set_element_cisp(cisp)
return s._proxy.CreateImportSpec(request)._returnval

def import_vapp(resource_pool, import_spec, host=None, folder=None):
#get the host MOR
if host:
hosts = s.get_hosts()
host = hosts.get(host)
if not host:
raise ValueError("invalid ESX host name")
#get the vm folder MOR
if folder:
folder = find_vmfolder_by_name(folder)
request = VI.ImportVAppRequestMsg()
_this =request.new__this(resource_pool)
_this.set_attribute_type(resource_pool.get_attribute_type())
request.set_element__this(_this)
request.set_element_spec(import_spec.ImportSpec)
if host:
h = request.new_host(host)
h.set_attribute_type(host.get_attribute_type())
request.set_element_host(h)
if folder:
f = request.new_folder(folder)
f.set_attribute_type(folder.get_attribute_type())
request.set_element_folder(f)
return s._proxy.ImportVApp(request)._returnval


if __name__ == "__main__":

#you can get the resource pools running s._get_resource_pools()
RESOURCE_POOL = "/Resources"

OVF_FILE = r"C:\FreeSCO\FreeSCO-043.ovf"

#you can get the host names running s.get_hosts()
HOST = "localhost.localdomain"

DATASTORE = "datastore1"
NETWORK_NAME = "VM Network"
VAPP_NAME = "My New VM2"

s = VIServer()
s.connect("host", "username", "password")

try:
resource_pool = s._get_resource_pools()[RESOURCE_POOL]
ovf = get_descriptor(OVF_FILE)
descriptor_info = parse_descriptor(ovf)
support_info = validate_host(HOST, ovf)
import_spec = create_import_spec(resource_pool,
DATASTORE,
ovf,
VAPP_NAME,
host=HOST,
network=NETWORK_NAME,
)
if hasattr(import_spec, "Warning"):
print "Warning:", import_spec.Warning[0].LocalizedMessage
http_nfc_lease = import_vapp(resource_pool, import_spec,
host=HOST)
lease = VIProperty(s, http_nfc_lease)
while lease.state == 'initializing':
print lease.state
lease._flush_cache()
if lease.state != 'ready':
print "something went wrong"
exit()

for url in lease.info.deviceURL:
print url.key
#Once we reach here, we should use the provided url to upload
the .vmdk file(s)
#But the ESX has already crashed by this time
finally:
s.disconnect()

Besides trying to make this work I'll see if the bug is exploitable,
maybe I can get to execute arbitrary code in the server :P


Regards,


Seba

Nikunj

unread,
Dec 14, 2011, 5:06:36 AM12/14/11
to pysphere, nikunj....@emc.com
Hi Seba,

Thanks a lot for your reply.
I tried running the script with my set of parameters.
I am getting following error.

{{{
C:\Documents and Settings\badjan\Desktop>python pysphere_test_ovf.py
Traceback (most recent call last):
File "pysphere_test_ovf.py", line 238, in <module>
network=NETWORK_NAME,
File "pysphere_test_ovf.py", line 176, in create_import_spec
return s._proxy.CreateImportSpec(request)._returnval
File "C:\Python27\lib\site-packages\pysphere\resources
\VimService_services.py", line 1790, in Crea
teImportSpec
response =
self.binding.Receive(CreateImportSpecResponseMsg.typecode)
File "C:\Python27\lib\site-packages\pysphere\ZSI\client.py", line
544, in Receive
return _Binding.Receive(self, replytype, **kw)
File "C:\Python27\lib\site-packages\pysphere\ZSI\client.py", line
463, in Receive
raise FaultException(msg)
pysphere.ZSI.FaultException:
<pysphere.resources.VimService_services_types.InvalidHostStateFault_Dec_Holder
object at 0x0293DAD0>

}}}

I am giving NETWORK_NAME = "VM Network" and this is the name available
on the esx host and the ovf too has the same network name.
Any ideas?

Regards,
Nikunj

Seba

unread,
Dec 14, 2011, 7:37:40 AM12/14/11
to pysp...@googlegroups.com, nikunj....@emc.com
Hi! 
   This is the exception you are getting (which is returned by the server): http://pubs.vmware.com/vsphere-50/index.jsp?topic=/com.vmware.wssdk.apiref.doc_50/vim.fault.InvalidHostState.html


may throw an InvalidState fault:
InvalidState Thrown if the operation failed due to the current state of the system.

Perhaps the host is maintenance mode or some required objects are locked by another operation.

You can catch the exception in the try block at the end of my script to get more details about what caused the error:

.....
    except VI.ZSI.FaultException, e:
        print "%s: %s" % (e.fault.detail[0].typecode.pname, e.fault.args[1])
    finally:
        s.disconnect()

Regards,

Seba.

2011/12/14 Nikunj <nikunjb...@gmail.com>

Nikunj

unread,
Dec 15, 2011, 8:56:08 AM12/15/11
to pysphere
Hey Seba !

I checked once more by putting the exception handling line into the
script.


{{{
C:\Documents and Settings\badjan\Desktop>python pysphere_test_ovf.py

InvalidHostStateFault:
}}}

This is what I get.

Further,
I am trying to find the number of NIC cards present at a particular
ESX. I had a look at the source code but couldnt get anymethod for it.
Also, some methods require "mor" objects. What are those?

Regards,
Nikunj


On Dec 14, 5:37 pm, Seba <argo...@gmail.com> wrote:
> Hi!

>    This is the exception you are getting (which is returned by the server):http://pubs.vmware.com/vsphere-50/index.jsp?topic=/com.vmware.wssdk.a...
> It's a subclass of this one:http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_5...
>
> The createImportSpec method described herehttp://pubs.vmware.com/vsphere-50/index.jsp?topic=/com.vmware.wssdk.a...


>
> may throw an InvalidState fault:

> InvalidState<http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_5...>Thrown


> if the operation failed due to the current state of the system.
>
> Perhaps the host is maintenance mode or some required objects are locked by
> another operation.
>
> You can catch the exception in the try block at the end of my script to get
> more details about what caused the error:
>
> .....
>     except VI.ZSI.FaultException, e:
>         print "%s: %s" % (e.fault.detail[0].typecode.pname, e.fault.args[1])
>     finally:
>         s.disconnect()
>
> Regards,
>
> Seba.
>

> 2011/12/14 Nikunj <nikunjbadja...@gmail.com>


>
>
>
> > Hi Seba,
>
> > Thanks a lot for your reply.
> > I tried running the script with my set of parameters.
> > I am getting following error.
>
> > {{{
> > C:\Documents and Settings\badjan\Desktop>python pysphere_test_ovf.py
> > Traceback (most recent call last):
> >  File "pysphere_test_ovf.py", line 238, in <module>
> >    network=NETWORK_NAME,
> >  File "pysphere_test_ovf.py", line 176, in create_import_spec
> >    return s._proxy.CreateImportSpec(request)._returnval
> >  File "C:\Python27\lib\site-packages\pysphere\resources
> > \VimService_services.py", line 1790, in Crea
> > teImportSpec
> >    response =
> > self.binding.Receive(CreateImportSpecResponseMsg.typecode)
> >  File "C:\Python27\lib\site-packages\pysphere\ZSI\client.py", line
> > 544, in Receive
> >    return _Binding.Receive(self, replytype, **kw)
> >  File "C:\Python27\lib\site-packages\pysphere\ZSI\client.py", line
> > 463, in Receive
> >    raise FaultException(msg)
> > pysphere.ZSI.FaultException:
>

> > <pysphere.resources.VimService_services_types.InvalidHostStateFault_Dec_Hol­der

> ...
>
> read more »- Hide quoted text -
>
> - Show quoted text -

Seba

unread,
Dec 15, 2011, 11:54:38 AM12/15/11
to pysp...@googlegroups.com, Nikunj....@emc.com
Seem that the exception message didn't provide much detail after all, for reason the host system is in an invalid state.

Regarding the number of NICs in the host systems, I'll provide you two ways:
#THE EASY WAY
from pysphere import *

s = VIServer()
s.connect("host", "user", "pass")

for h, mor in s.get_hosts().items():
    prop = VIProperty(s, mor)
    try:
        print h, "has", prop.summary.hardware.numNics, "NICs"
    except AttributeError:
        print h, "does not have NIC info

#THE PERFORMANT WAY
from pysphere import *

s = VIServer()
s.connect("host", "user", "pass")

data = s._retrieve_properties_traversal(property_names=["name", "summary.hardware.numNics"],
                                        obj_type='HostSystem')
for item in data:
    name = ""
    nics = None
    for p in item.PropSet:
        if p.Name == "name": name = p.Val
        if p.Name == "summary.hardware.numNics": nics = p.Val
    print name, "has", nics, "NICs"

In the first case, I'm getting all the properties of the host when instantiating VIProperty, so the response sent by the server is much larger, besides I'm sending a request for each host system.
However you can get any other HostSytem (http://pubs.vmware.com/vsphere-50/index.jsp?topic=/com.vmware.wssdk.apiref.doc_50/vim.HostSystem.html) existing property without having to do extra requests.
For example: prop.runtime.powerState, prop.config.product, etc

In the second case, I'm just getting the name, and number of nics of all the hosts in one single request.

Regarding your question about 'mor':
MOR stands for Managed Object Reference, it represents some kind of ID of an existing living object on the ESX side.
All the vSphere API is based in these Managed Objects, either you can retrieve properties of these objects or you can invoke methods to these objects.
In fact all the methods need a list a MOR parameter (called _this) which is the object that can and will execute that method.

As the objects live in the server side, at the client side we nee references to those objects (MORs). In pysphere, they are a subclass of basestring. So they're basically str objects with 2 additional methods 'set_attribute_type' and 'get_attribute_type' that define the managed objet type for a particular MO reference (the str value).

for example, s.get_host() returns a dictionary where key's are the Host names, and values their corresponding MORs.

for name, host_mor in s.get_hosts().items():
    print host_mor, host_mor.get_attribute_type(), name

shows something like:

host-444 HostSystem ew-esx1.example.com
host-203 HostSystem dev-esx1.example.com
host-720 HostSystem qa-esx4.example.com
host-5583 HostSystem 192.168.20.22
host-399 HostSystem orgy.example.com
host-123 HostSystem wa-esx3.example.com
host-120 HostSystem wa-esx1.example.com
host-185 HostSystem build-esx1.example.com
host-1029 HostSystem qa-esx1.example.com
host-206 HostSystem dev-esx2.example.com
host-1547 HostSystem qa-esx3.example.com
host-12 HostSystem prod-esx1.example.com
host-67 HostSystem test.example.com
host-6577 HostSystem dev-esx3.example.com
host-1263 HostSystem qa-esx2.example.com



Regards,


Sebastian.

2011/12/15 Nikunj <nikunjb...@gmail.com>

Nikunj

unread,
Dec 16, 2011, 7:48:09 AM12/16/11
to pysp...@googlegroups.com, Nikunj....@emc.com

Thanks a lot Seba!

That worked for me. :)

I myself tried few other examples to make myself more comfortable. Slower method but have a look.

In a particular hostsystem:

1.       Finding no. of networks a VM is using .

{{{

>>> for h, mor in server.get_hosts().items():

...     if h ==’esx.domain.com’:

...         prop = VIProperty(server, mor)

...         for vmname in prop.vm:

...             print vmname.name

...             for net in vmname.network:

...                 print "   ", net.name

}}}

2.       Number of ethernet cards and virtual disks a VM has.

{{{

>>> for h, mor in server.get_hosts().items():

...     if h == ’esx.domain.com':

...         prop = VIProperty(server, mor)

...         for vmname in prop.vm:

...             print vmname.name

...             print “ ethernet cards:  “ , vmname.summary.config.numEthernetCards, “Virtual disks: “, vmname.summary.config.numVirtualDisks

}}}

I now understood what a MOR means and how to get different properties of Hostsystem, VM, Datastore etc.

As I said earlier, we are trying to deploy OVF file. Previously we were using powershell because of greater bonding with powercli. But now we are planning to remove powershell and make it 100% python.

We are in dire need for completed Advanced Usage guide of pysphere. May be now at some places I can too contribute in the documentation ;)

So, since pysphere is for interacting with vsphere web services sdk. It can do virtually anything what the sdk offers ??

When we compare pysphere with vsphere powercli sdk, how good it stands ??

Some more queries coming up! ;)

Thanks

Nikunj

Seba

unread,
Dec 20, 2011, 8:19:37 AM12/20/11
to pysphere, nikunjb...@gmail.com
> So, since pysphere is for interacting with vsphere web services sdk. It can> do virtually anything what the sdk offers ??
Yes, it can virtually do anything the SDK offers. Besides that, It
provides simple interfaces for some operations (VMs, snapshots,
performance monitoring) so the user doesn't need to have deep
knowledge of vSphere for those things (you can still do it the hard
way).
I Hope the community helps adding more of these simplified interfaces,
so, for example if we managed to make this complex OVF deploying stuff
to work, we could add a single method to pysphere like
"deploy_ovf(file, host, resource_pool, ...extra_config)" that hides
all the complexity behind

> When we compare pysphere with vsphere powercli sdk, how good it stands ??

I answered a similar question here: http://communities.vmware.com/message/1876247#1876247

Thanks!

Sebastian

Nick Wiesmueller

unread,
Jan 13, 2012, 10:45:07 AM1/13/12
to pysphere
I need to be able to deploy on OVA file so I'm attempting to use the
code you specified. I have two problems.

First problem. If I don't extract the ova to OVF and VMDK and I can't
read in the file using python's .read() method (I get a MemoryError).
I can't find a feasible workaround for this other than extracting the
OVA file to its components. This is cumbersome and invalidates some of
the testing we're doing.

Second problem. When I run your code using this except block:
except VI.ZSI.FaultException, e:
print "%s: %s" % (e.fault.detail[0].typecode.pname,
e.fault.args[1])

I just get
InvalidHostStateFault:

but no other output to suggest what the problem is.

Thanks for your help. FWIW, the code as written did not crash the
server.

Nick
> ...
>
> read more »

Seba

unread,
Jan 19, 2012, 1:15:26 PM1/19/12
to pysphere, Nick Wiesmueller, nikunjb...@gmail.com
Hi All,

Nick has successfully reached to the last part of my script. I keep
crashing my ESXi 5.0 server (which is running on a vmware workstation,
so it's not very reliable). I tested with a different server, I didn't
crashed it, but I couldn't pass through the 'initializing' state of
the httpnfclease.
By the way, Nick solved the InvalidHostState fault by unregistering
the hosts and registering them back again.

Nick, I wrote the missing part of the code, being totally blind, so
I'll need your help to test it. It does the following
1- Reads the httpnfclease info, for each device that has to be
uploaded
2- Opens and reads the file using memory map (mmap) as a vmdk files
are probably very large, and you might get a memory error if you read
it all from one shot.
3- I believe the file has to be sent using the HTTP PUT method, not
suppoted by python's urllib 2, so there's a little hack there.
4- Once all the files have been sent, calls HttpNfcLeaseComplete.
Probably we should start a thread that calls HttpNfcLeaseProgress
periodically to keep the lease alive

Ok then, you should replace this part of the script

for url in lease.info.deviceUrl:
print url.key

with this.

import os
import urllib2
import mmap
from urlparse import urlparse

for dev_url in lease.info.deviceUrl:
filename = dev_url.targetId
hostname = urlparse(s._proxy.binding.url).hostname
upload_url = dev_url.ulr.replace("*", hostname)

filename = os.path.join(os.path.dirname(OVF_FILE), filename)
fsize = os.stat(filename).st_size

f = open(filename,'rb')
mmapped_file = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)

request = urllib2.Request(upload_url, upload_url=content)
request.get_method = lambda: 'PUT'
request.add_header("Content-Type", "application/x-vnd.vmware-
streamVmdk")
request.add_header("Connection", "Keep-Alive")
request.add_header("Content-Length", str(fsize))
resp = opener.open(request)

mmapped_file.close()
f.close()

if not resp.code == 200:
print "something didn't work"

request = VI.HttpNfcLeaseCompleteRequestMsg()
_this =request.new__this(http_nfc_lease)
_this.set_attribute_type(http_nfc_lease.get_attribute_type())
request.set_element__this(_this)
s._proxy.HttpNfcLeaseComplete(request)



Hope it works! let's cross our fingers!

Sebastian.

On Jan 13, 12:45 pm, Nick Wiesmueller
> ...
>
> read more »

Seba

unread,
Jan 19, 2012, 4:53:36 PM1/19/12
to pysp...@googlegroups.com
Nick, I'm forwarding your questions to the post in the discussion group.

Find my answers inline (starting with:  **** ).

Thanks,

Seba
---------- Forwarded message ----------
From: Nick Wiesmueller
Date: 2012/1/19
Subject: Re: Deploying OVF files on ESX
To: Seba

thanks Seba. 

A couple questions I need answered before I can try it out. 

1. What does OVF_FILE refer to? the full path to the file? 

**** The OVF_FILE variable was defined before in the first long code snippet I sent, and yes, it's the full path to the file

2. what does content refer to on this line
 request = urllib2.Request(upload_url, upload_url=content)
I don't see that it was ever set. 

**** sorry, it should be:
**** request = urllib2.Request(upload_url, upload_url=mmapped_file)

3. What is opener here:

resp = opener.open(request)

Is there a line where an urllib2 opener was built that I missed?

**** Sorry again, I forgot to add this line before that one:
**** opener = urllib2.build_opener(urllib2.HTTPHandler)

4. 

I need to use chunking or buffering to load the vmdk. will something like this work so that it won't load it into memory?

#!/usr/bin/env python
import httplib
c = httplib.HTTPConnection('localhost', 3000)
c.request("POST", '/people', file('f.vmdk'))
print(c.getresponse().read())

**** That's why I used mmap, it is a file-like object and it loads the file content to memory on demand. Of course I couldn't test if it works.


Thanks,

Nick

Thanks,

Nick

Seba

unread,
Jan 20, 2012, 5:14:27 PM1/20/12
to pysp...@googlegroups.com, Nick Wiesmueller
(I'm posting my answer to the discussion group as well)

Awesome!, By common sense I would have used POST, as PUT is not a very common method. However I used PUT because there's a similar method (InitiateFileTransferToGuest) in which you are also provided with an URL to send a file and VMware requires to use PUT, I though they would use the same logic in this case (cause it's not documented at all).

To keep the connection alive we need to call periodically the HttpNfcLeaseProgress method. It receives a percent parameter (a value from 0 to 100).
I think that providing any percent progress (e.g. always 50%) is enough to keep the lease alive. The neat way would be knowing the total number of bytes to be sent (summing up the size of each file) and keep track of how many bytes have been sent to calculate the total progress.
As your script will get blocked on the line "resp = opener.open(request)" until the whole file is sent, first we need to start a separate thread that will call HttpNfcLeaseProgress periodically. However there might be some issues using threads with pysphere as the underlying framework (ZSI) is not thread-safe. 
Particularly I've seen issues with sockets when two vSphere methods are invoked at the same time from different threads. In your case, only the HttpNfcLeaseProgress thread is using the API, the main thread is submitting the file on a separate channel, so I think it should work. (Anyway I'm thinking of modifying ZSI to make it thread-safe). 

So, to keep the lease you should do something like this:

import time
import threading

def keep_lease_alive(lease):
    request = VI.HttpNfcLeaseProgressRequestMsg()
    _this =request.new__this(lease)
    _this.set_attribute_type(lease.get_attribute_type())
    request.set_element__this(_this)
    request.set_element_percent(50) #then we can add logic to set a real one
    while go_on:
        s._proxy.HttpNfcLeaseProgress(request)
        time.sleep(5)

...
...
...
go_on = True
t = threading.Thread(target=keep_lease_alive, args=(http_nfc_lease,))
t.start()

for dev_url in lease.info.deviceUrl:
...
... #THE WHOLE FOR FILE TRANSFER LOOP HERE
...

go_on = False
t.join()

request = VI.HttpNfcLeaseCompleteRequestMsg()
_this =request.new__this(http_nfc_lease)
_this.set_attribute_type(http_nfc_lease.get_attribute_type())
request.set_element__this(_this)
s._proxy.HttpNfcLeaseComplete(request)


Thanks,


Sebastian.

2012/1/20 Nick Wiesmueller
I've figured it out and successfully deployed a vm!!! I changed the PUT to POST and it worked! I don't understand why that worked. Do you think we should always be using POST instead of PUT?

Also the response code was not 200 but everything worked. I'm not sure what we got back because I didn't print it out.

How do I access the lease.info.status to keep the connection alive?
I've got a couple more issues to work out but I won't trouble you with them.

Thanks for your help on this issue!

Nick





On Fri, Jan 20, 2012 at 11:22 AM, Nick Wiesmueller <nick.wie...@singlewire.com> wrote:
Bah!

I'm getting a connection refused on this line

 resp = opener.open(request)
  File "C:\Python27\lib\urllib2.py", line 394, in open
    response = self._open(req, data)
  File "C:\Python27\lib\urllib2.py", line 412, in _open
    '_open', req)
  File "C:\Python27\lib\urllib2.py", line 372, in _call_chain
    result = func(*args)
  File "C:\Python27\lib\urllib2.py", line 1207, in https_open
    return self.do_open(httplib.HTTPSConnection, req)
  File "C:\Python27\lib\urllib2.py", line 1174, in do_open
    raise URLError(err)
URLError: <urlopen error [Errno 10054] An existing connection was forcibly closed by the remote host>

Still, it's progress, but I don't know how to troubleshoot the problem.

The vmware logs are very difficult to decipher. I did see this message at the time of attempted deploy:

2012-01-20T10:17:07.887-06:00 [03904 warning 'Default'] [VpxdVmprovUtil::GetDiskDatastoreFromUrl] Unable to lookup ds for disk

I don't know that this has anything to do with the problem though.



Nick




I looked at the vmcenter logs and I didn't see anything useful.
On Thu, Jan 19, 2012 at 3:56 PM, Seba <arg...@gmail.com> wrote:
I forgot to CC you. :P

Nick Wiesmueller

unread,
Jan 24, 2012, 12:27:34 PM1/24/12
to Seba, pysp...@googlegroups.com
Hi Seba,

The code you provided for keeping the lease alive works. I may write something  a more sophisticated method of keeping track of lease status down the road, but that's a lower priority. One problem I've discovered is that the deployed VM is not using the network that I'm specifying. I've verified that the network I'm specifying is accurate.  It seems to just pick the first in the list. I realize that this would be very difficult if not impossible to troubleshoot without your ability to execute the code yourself, but any hints would be much appreciated because at this point I'm just throwing stuff at the problem.

Thanks,

Nick

Seba

unread,
Jan 27, 2012, 11:21:33 AM1/27/12
to pysp...@googlegroups.com, Nick Wiesmueller
Hi Nick,

     I've made some changes to the script, see the 'NETWORK_MAPPING' parameters, which should be something like this:
NETWORK_MAPPING = {"OVF Network Name":"VMWare Network Name", "OVF2":"VMWare 2"} 
    There you specify which network defined in the .ovf file should be matched to which network on your ESX/vCenter.
Maybe that new logic solves your issue.

Besides, I've made other changes since  since revision 53, _get_resource_pool(), _get_clusters(),  _get_datacenters() have been deprecated for get_resource_pools(), get_clusters(), and get_datacenters() which return a similar dictionary but inverted (keys are managed object references, and values are names). 
Besides get_hosts() behavior was changed to do the same (now returns the same dictionary but inverted). I had to do this because MOR are unique but names aren't so some objects with the same name were not returned when calling these methods (http://code.google.com/p/pysphere/issues/detail?id=4 

So this script I'm copying will work since that revision. By the way, I changed the way ZSI (the underlying SOAP framework) handles HTTP connections, so pysphere should now be thread-safe.

Regards,

Sebastian.

import time
import threading
import os
import urllib2
import mmap
from urlparse import urlparse

from pysphere import VIServer, VIProperty
from pysphere.resources import VimService_services as VI

def get_descriptor(ovf_path):
    fh = open(ovf_path, "r")
    ovf_descriptor = fh.read()
    fh.close()
    return ovf_descriptor
def parse_descriptor(ovf_descriptor):
    ovf_manager = s._do_service_content.OvfManager
    request = VI.ParseDescriptorRequestMsg()
    _this =request.new__this(ovf_manager)
    _this.set_attribute_type(ovf_manager.get_attribute_type())
    request.set_element__this(_this)
    request.set_element_ovfDescriptor(ovf_descriptor)
    pdp = request.new_pdp()
    pdp.set_element_locale("")
    pdp.set_element_deploymentOption("")
    request.set_element_pdp(pdp)
    return s._proxy.ParseDescriptor(request)._returnval

def validate_host(host, ovf_descriptor):
    ovf_manager = s._do_service_content.OvfManager
    request = VI.ValidateHostRequestMsg()
    _this =request.new__this(ovf_manager)
    _this.set_attribute_type(ovf_manager.get_attribute_type())
    request.set_element__this(_this)
    request.set_element_ovfDescriptor(ovf_descriptor)
    h = request.new_host(host)
    h.set_attribute_type(host.get_attribute_type())
    request.set_element_host(h)
    vhp = request.new_vhp()
    vhp.set_element_locale("")
    vhp.set_element_deploymentOption("")
    request.set_element_vhp(vhp)
    return s._proxy.ValidateHost(request)._returnval

def find_network_by_name(network_name):
    ret = None
    for dc in  s.get_datacenters().keys():
        dc_properties = VIProperty(s, dc)
        for nw in dc_properties.network:
            if nw.name == network_name:
                ret = nw._obj
                break
        if ret:
            break
    if not ret:
        raise ValueError("Couldn't find network '%s'" % (network_name))
    return ret

def find_vmfolder_by_name(folder_name):
    ret = None
    for dc in s.get_datacenters().keys():
        dc_properties = VIProperty(s, dc)
        if dc_properties.vmFolder.name == folder_name:
            return dc_properties.vmFolder._obj
    raise ValueError("Couldn't find folder '%s'" % (folder_name))

def create_import_spec(resource_pool_mor,
                       datastore_mor,
                       ovf_descriptor,
                       name,
                       host=None,
                       network_mapping=None,
                       ip_allocation_policy="fixedPolicy",
                       ip_protocol="IPv4",
                       disk_provisioning="flat"
                       ):
    #get the network MORs:
    networks = {}
    if network_mapping:
        for ovf_net_name, vmware_net_name in network_mapping.items():
            networks[ovf_net_name] = find_network_by_name(vmware_net_name)

    ovf_manager = s._do_service_content.OvfManager
    request = VI.CreateImportSpecRequestMsg()
    _this =request.new__this(ovf_manager)
    _this.set_attribute_type(ovf_manager.get_attribute_type())
    request.set_element__this(_this)
    request.set_element_ovfDescriptor(ovf_descriptor)
    rp = request.new_resourcePool(resource_pool_mor)
    rp.set_attribute_type(resource_pool_mor.get_attribute_type())
    request.set_element_resourcePool(rp)
    ds = request.new_datastore(datastore_mor)
    ds.set_attribute_type(datastore_mor.get_attribute_type())
    request.set_element_datastore(ds)
    cisp = request.new_cisp()
    cisp.set_element_entityName(name)
    cisp.set_element_locale("")
    cisp.set_element_deploymentOption("")
    if host:
        h = cisp.new_hostSystem(host)
        h.set_attribute_type(host.get_attribute_type())
        cisp.set_element_hostSystem(h)
    if networks:
        networks_map = []
        for ovf_net_name, net_mor in networks.items():
            network_mapping = cisp.new_networkMapping()
            network_mapping.set_element_name(ovf_net_name)
            n_mor = network_mapping.new_network(net_mor)
            n_mor.set_attribute_type(net_mor.get_attribute_type())
            network_mapping.set_element_network(n_mor)
            networks_map.append(network_mapping)
        cisp.set_element_networkMapping(network_mapping)
    if ip_allocation_policy:
        cisp.set_element_ipAllocationPolicy(ip_allocation_policy)
    if ip_protocol:
        cisp.set_element_ipProtocol(ip_protocol)
    if disk_provisioning:
        cisp.set_element_diskProvisioning(disk_provisioning)
    request.set_element_cisp(cisp)
    return s._proxy.CreateImportSpec(request)._returnval

def import_vapp(resource_pool, import_spec, host=None, folder=None):
    #get the vm folder MOR
    if folder:
        folder = find_vmfolder_by_name(folder)
    request = VI.ImportVAppRequestMsg()
    _this =request.new__this(resource_pool)
    _this.set_attribute_type(resource_pool.get_attribute_type())
    request.set_element__this(_this)
    request.set_element_spec(import_spec.ImportSpec)
    if host:
        h = request.new_host(host)
        h.set_attribute_type(host.get_attribute_type())
        request.set_element_host(h)
    if folder:
        f = request.new_folder(folder)
        f.set_attribute_type(folder.get_attribute_type())
        request.set_element_folder(f)
    return s._proxy.ImportVApp(request)._returnval

def keep_lease_alive(lease):
    request = VI.HttpNfcLeaseProgressRequestMsg()
    _this =request.new__this(lease)
    _this.set_attribute_type(lease.get_attribute_type())
    request.set_element__this(_this)
    request.set_element_percent(50) #then we can add logic to set a real one
    while go_on:
        s._proxy.HttpNfcLeaseProgress(request)
        time.sleep(5)

go_on = True

if __name__ == "__main__":
    #you can get the resource pools running s.get_resource_pools()
    RESOURCE_POOL = "/Resources"
    OVF_FILE = r"C:\FreeSCO\FreeSCO-043.ovf"
    #you can get the host names running s.get_hosts()
    HOST = "localhost.localdomain"
    DATASTORE = "datastore1"
    NETWORK_MAPPING = {"OVF Network Name":"VMWare Network Name", "OVF2":"VMWare 2"}
    VAPP_NAME = "My New VM2"
    s = VIServer()
    s.connect("host", "username", "password")
    try:
        host = [k for k,v in s.get_hosts().items() if v==HOST][0]

        resource_pool = [k for k,v in s.get_resource_pools().items()
                         if v == RESOURCE_POOL][0]
        datastore = [k for k,v in s.get_datastores().items() if v==DATASTORE][0]

        ovf = get_descriptor(OVF_FILE)
        descriptor_info =  parse_descriptor(ovf)
        support_info = validate_host(host, ovf)
        import_spec = create_import_spec(resource_pool,
                                         datastore,
                                         ovf,
                                         VAPP_NAME,
                                         host=host,
                                         network_mapping=NETWORK_MAPPING,
                                         )
        if hasattr(import_spec, "Warning"):
            print "Warning:", import_spec.Warning[0].LocalizedMessage
        http_nfc_lease = import_vapp(resource_pool, import_spec, host=host)
        lease = VIProperty(s, http_nfc_lease)
        while lease.state == 'initializing':
            print lease.state
            lease._flush_cache()
        if lease.state != 'ready':
            print "something went wrong"
            exit()

        t = threading.Thread(target=keep_lease_alive, args=(http_nfc_lease,))
        t.start()
        for dev_url in lease.info.deviceUrl:
            filename = dev_url.targetId
            hostname = urlparse(s._proxy.binding.url).hostname
            upload_url = dev_url.ulr.replace("*", hostname)
            filename = os.path.join(os.path.dirname(OVF_FILE), filename)
            fsize = os.stat(filename).st_size
            f = open(filename,'rb')
            mmapped_file = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
            request = urllib2.Request(upload_url, upload_url=mmapped_file)

            request.add_header("Content-Type", "application/x-vnd.vmware-streamVmdk")
            request.add_header("Connection", "Keep-Alive")
            request.add_header("Content-Length", str(fsize))
            opener = urllib2.build_opener(urllib2.HTTPHandler)
            resp = opener.open(request)
            mmapped_file.close()
            f.close()

        go_on = False
        t.join()
        request = VI.HttpNfcLeaseCompleteRequestMsg()
        _this =request.new__this(http_nfc_lease)
        _this.set_attribute_type(http_nfc_lease.get_attribute_type())
        request.set_element__this(_this)
        s._proxy.HttpNfcLeaseComplete(request)

    finally:
        s.disconnect()


2012/1/24 Nick Wiesmueller

Wu Li

unread,
Dec 10, 2012, 1:54:46 AM12/10/12
to pysp...@googlegroups.com, Nick Wiesmueller, nikunjb...@gmail.com
hi Seba,
Very glad googled the script that can use python script to populate OVA deployment. I tried the pyshere and the script you wrote here. But unfortunately i crashed the VMware host(5.0) too as you experienced. Here is some information printed. (I modify some parameter settings such as host, user, ....)
When i was calling the script, i opened another session by using vmware sphere, this session will be disconnect once the state in "In Progress" status.

Any suggestions for that?

Thanks,
Wu


________________Console Output_____________________
initializing
initializing
initializing
initializing
initializing
initializing
Traceback (most recent call last):
  File "deploy.py", line 201, in <module>
    http_nfc_lease = import_vapp(resource_pool, import_spec, host=host)
  File "build/bdist.linux-x86_64/egg/pysphere/vi_server.py", line 150, in disconnect
  File "build/bdist.linux-x86_64/egg/pysphere/resources/VimService_services.py", line 2247, in Logout
  File "build/bdist.linux-x86_64/egg/pysphere/ZSI/client.py", line 295, in Send
  File "/root/ws/cats/lib/python2.7/httplib.py", line 1154, in connect
    self.timeout, self.source_address)
  File "/root/ws/cats/lib/python2.7/socket.py", line 571, in create_connection
    raise err
socket.error: [Errno 111] Connection refused


在 2012年1月20日星期五UTC+8上午2时15分26秒,Seba写道:

Seba

unread,
Jan 2, 2013, 8:05:26 AM1/2/13
to pysp...@googlegroups.com, Nick Wiesmueller, nikunjb...@gmail.com
Hi Wu!

  Even though we must be doing something wrong I guess this is a VMWare bug as the server shouldn't crash due to a bad formatted request. The script worked for some people, I will run it again to see if I still crash the server.

Regards,

Seba

Wu Li

unread,
Jan 6, 2013, 9:50:01 PM1/6/13
to pysp...@googlegroups.com, Nick Wiesmueller, nikunjb...@gmail.com
Thanks, Seba. looking forward your good news.

在 2013年1月2日星期三UTC+8下午9时05分26秒,Seba写道:

Seba

unread,
Jan 15, 2013, 8:03:59 AM1/15/13
to pysp...@googlegroups.com, Nick Wiesmueller, nikunjb...@gmail.com
Hi Wu Li,

 After upgrading ESXi from 5.0 to 5.1, I'm not longer crashing the server.

Regards,

Seba.

Wu Li

unread,
Jan 22, 2013, 1:17:25 AM1/22/13
to pysp...@googlegroups.com, Nick Wiesmueller, nikunjb...@gmail.com
good, i'll have a try once get 5.1 installed

Thanks,
Wu

在 2013年1月15日星期二UTC+8下午9时03分59秒,Seba写道:

Dave Johnson

unread,
Apr 17, 2013, 9:03:14 AM4/17/13
to pysp...@googlegroups.com, Nick Wiesmueller, nikunjb...@gmail.com
Many thanks to this project for its work as well as this import_ovf script...

FYI, going through it, I stumbled across a issue in create_import_spec()... under if networks:  you need to change
        cisp.set_element_networkMapping(network_mapping)
to this
        cisp.set_element_networkMapping(networks_map)

Unfortunately I ran into a issue that I am not sure how to deal with and am hoping someone has some experience to point me in the right direction...

Basically parse_descriptor comes back with a "Error: Line 1: Incorrect namespace 'http://schemas.dmtf.org/ovf/envelope/1/' found." which is confusing as this OVF does import into vsphere through the console and I am fairly certain it 'http://schemas.dmtf.org/ovf/envelope/1/'is the correct namespace, right?

Top two lines of the descriptor:
<?xml version=\'1.0\' encoding=\'UTF-8\'?><ovf:Envelope xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1/" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ovf:version="3.0.0.0">

Any help is much appreciated!

mxmader

unread,
Apr 19, 2013, 10:53:48 PM4/19/13
to pysp...@googlegroups.com, Nick Wiesmueller, nikunjb...@gmail.com
was your OVF created by an export action executed from a vsphere client? if not, that could be the source of the issue. not all OVF XML descriptors are truly standards compliant or cross-virtualization platform compatible. i've had to hack up XML to make VMware and VirtualBox OVFs play nice when importing across virt platforms. if indeed this is the case, maybe there's a flag to set which will sell the vsphere API how to parse/interpret the OVF descriptor (just a guess)

Chris Powers

unread,
May 17, 2013, 1:07:01 PM5/17/13
to pysp...@googlegroups.com, nikunj....@emc.com
I'm attempting to use Seba's script to deploy a OVA built by oftool but I'm running across this issue during create_import_spec:

 request.set_element_spec(import_spec.ImportSpec)
 File "build\bdist.win-amd64\egg\pysphere\ZSI\generate\pyclass.py", line 160, in get
AttributeError: 'DynamicData_Holder' object has no attribute '_importSpec'

If I set a breakpoint and evaluate the return from s._proxy.CreateImportSpec(request), I see that the _return_value.ImportSpect member is set to:
str: Traceback (most recent call last):
  File "C:\eclipse\plugins\org.python.pydev.debug_2.5.0.2012040618\pysrc\pydevd_resolver.py", line 182, in _getPyDictionary
    attr = getattr(var, n)
  File "build\bdist.win-amd64\egg\pysphere\ZSI\generate\pyclass.py", line 160, in get
    return getattr(self, what().aname)
AttributeError: 'DynamicData_Holder' object has no attribute '_importSpec'


Any suggestions on what the issue might be or how I can debug it? Is this potentially an issue with how the OVA is built?

Thanks!
chris

Ran Leibman

unread,
Aug 11, 2013, 10:53:44 AM8/11/13
to pysp...@googlegroups.com, nikunj....@emc.com
Hi Guys,

Did someone manage to deploy the ovf on 5.0 after all ?
I can't upgrade it to 5.1 just yet ... =/

Daniel Resendez

unread,
Dec 4, 2013, 3:54:16 PM12/4/13
to pysp...@googlegroups.com, Nick Wiesmueller, nikunjb...@gmail.com
I am getting the same error as Chris Powers.... does anyone have an idea how to fix it..

frankh...@yahoo.com

unread,
Dec 16, 2013, 9:28:16 PM12/16/13
to pysp...@googlegroups.com, Nick Wiesmueller, nikunjb...@gmail.com
I just got the same error (no _importSpec attribute) and see the traceback in import_vapp - just not catching it as early.
Has anyone found a solution for this yet?  Thanks

--Frank

Sankaranarayanan Muralidharan

unread,
Dec 19, 2013, 5:59:11 AM12/19/13
to pysp...@googlegroups.com, Nick Wiesmueller, nikunjb...@gmail.com
Hi Seba,

I am testing this with Vcenter 5.5.   Trying to deploy the OVF template.

I stuck at the below error. The lease.state goes to error state and I have probed the error, it was showing "The operation is not supported on the object"

Note: the lease.state was going to initializing state for some times and stuck at error state all the times.

Can you please help me out ? 


initializing
{'_obj': 'session[9049cc3c-eca4-5448-ab1b-851685ef78f1]52744802-0b5d-fdf3-14e3-aa7ea2daddb6',
 '_server': <pysphere.vi_server.VIServer instance at 0x4d51f38>,
 '_type': 'ManagedObjectReference',
 '_values': {'initializeProgress': 10, 'state': 'initializing'},
 '_values_set': True,
 'state': 'initializing'}
something went wrong
error
{'_obj': 'session[9049cc3c-eca4-5448-ab1b-851685ef78f1]52744802-0b5d-fdf3-14e3-aa7ea2daddb6',
 '_server': <pysphere.vi_server.VIServer instance at 0x4d51f38>,
 '_type': 'ManagedObjectReference',
 '_values': {'error': <pysphere.resources.VimService_services_types.DynamicData_Holder object at 0x50d2150>,
             'initializeProgress': 100,
             'state': 'error'},
 '_values_set': True,
 'state': 'error'}
{'_dynamicProperty': [],
 '_dynamicType': None,
 '_fault': <pysphere.resources.VimService_services_types.MethodFault_Holder object at 0x51d91d0>,
 '_localizedMessage': 'The operation is not supported on the object.'}

Nick Wiesmueller

unread,
Feb 5, 2014, 10:57:08 AM2/5/14
to Sankaranarayanan Muralidharan, pysp...@googlegroups.com, nikunjb...@gmail.com
Well it's my turn to get this error. It began happening after we added a 5.5 esxi host. We had been using Vcenter 5.5 + 5.1 hosts and the code worked perfectly. Now with a 5.5 host we are getting this:

elf.localt.http_nfc_lease = self.import_vapp(self.localt.resource_pool, self.localt.import_spec, host=self.localt.hostname, folder=folder) 
09:29:54   File "./src/informacast/linux_util/vm_util.py", line 978, in import_vapp
09:29:54     request.set_element_spec(import_spec.ImportSpec) 
09:29:54   File "/root/jenkins/workspace/DeployONELinuxVM/lib/pysphere-0.1.6-py2.7.egg/pysphere/ZSI/generate/pyclass.py", line 167, in get
09:29:54     return getattr(self, what().aname)
09:29:54 AttributeError: 'DynamicData_Holder' object has no attribute '_importSpec'
--
Nick Wiesmueller
QA Analyst
Singlewire Software
2601 W. Beltline Hwy
Madison, WI
Phone Direct - 608.661.1180
www.singlewire.com

Nick Wiesmueller

unread,
Feb 6, 2014, 12:07:57 PM2/6/14
to Sebastián Tello, pysp...@googlegroups.com
This may or may not help anyone, but we rebooted our esxi host after it crashed. It's unclear whether my deploy attempts actually caused the crash, but after the reboot I no longer receive the error. This is with a 5.5 vcenter and 5.5 host. 

Nick


On Thu, Feb 6, 2014 at 7:47 AM, Nick Wiesmueller <nick.wie...@singlewire.com> wrote:
Hello Seba,

I was wondering if you had any ideas on this (see below also posted to the group)? 

If I do a dir on an importspec object from a working system (esxi 5.1) I see this:

11:26:52 informacast.linux_util.vm_util.Vm_util.deploy_ovf  Dir of import spec is ['DynamicProperty', 'DynamicType', 'Error', 'FileItem', 'ImportSpec', 'Warning', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_dynamicProperty', '_dynamicType', '_fileItem', '_importSpec', '_warning', 'get_element_dynamicProperty', 'get_element_dynamicType', 'get_element_error', 'get_element_fileItem', 'get_element_importSpec', 'get_element_warning', 'new_dynamicProperty', 'new_error', 'new_fileItem', 'new_importSpec', 'new_warning', 'set_element_dynamicProperty', 'set_element_dynamicType', 'set_element_error', 'set_element_fileItem', 'set_element_importSpec', 'set_element_warning', 'typecode'] 

on  a non-working system (esxi 5.5)

11:25:07 informacast.linux_util.vm_util.Vm_util.deploy_ovf  Dir of import spec is ['DynamicProperty', 'DynamicType', 'Error', 'FileItem', 'ImportSpec', 'Warning', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_dynamicProperty', '_dynamicType', '_error', 'get_element_dynamicProperty', 'get_element_dynamicType', 'get_element_error', 'get_element_fileItem', 'get_element_importSpec', 'get_element_warning', 'new_dynamicProperty', 'new_error', 'new_fileItem', 'new_importSpec', 'new_warning', 'set_element_dynamicProperty', 'set_element_dynamicType', 'set_element_error', 'set_element_fileItem', 'set_element_importSpec', 'set_element_warning', 'typecode']

I don't understand why attempting to access importspec.ImportSpec actually accesses _importSpec internally or why this property would not be present.

Any ideas you have would be greatly appreciated.

Thanks,

Nick

---------- Forwarded message ----------
From: Nick Wiesmueller <nick.wie...@singlewire.com>
Date: Wed, Feb 5, 2014 at 9:57 AM
Subject: Re: Deploying OVF files on ESX

~S

unread,
Apr 1, 2015, 12:22:30 AM4/1/15
to pysp...@googlegroups.com
Hello Seba

  I have just started to look into PySphere package. I have a requirement to automate the vm deployment - ( with ova file ). I was trying to use the sample program that you wrote down. I made some minimum modification for the script to make it compatible for my environment. But while executing it gives the below mentioned error.


>>>
Traceback (most recent call last):
  File "import_salil.py", line 209, in <module>
    support_info = validate_host(HOST_LOCAL, ovf)
  File "import_salil.py", line 38, in validate_host
    h.set_attribute_type(host.get_attribute_type())
AttributeError: 'str' object has no attribute 'get_attribute_type'

<<<

  Following is the changes that I made.

>>>>
    #you can get the resource pools running s._get_resource_pools()

    RESOURCE_POOL = "/Resources"

    OVF_FILE = r"C:\FreeSCO\FreeSCO-043.ovf"
    OVF_FILE = "/home/sagk/Downloads/pysphere-0.1.8/sample/s42700x8_1_1_rc5.ovf"


    #you can get the host names running s.get_hosts()
    HOST = "localhost.localdomain"
    HOST = "10.106.251.12"   # This is the ESXi IP address  ?

    HOST_LOCAL = 'ha-host'

    DATASTORE = "datastore1"
    DATASTORE = "datastore2 (1)"

    NETWORK_NAME = "VM Network"
    VAPP_NAME = "MyTestVM"

    s = VIServer()
    #s.connect("host", "username", "password")
    s.connect(HOST, 'root', '12Password12')
<<<


    Following are the information that I can get from the python command line.

>>>>

In [17]: server.connect('10.106.251.12', 'root', '12Cisco12')

In [18]: hosts = server.get_hosts()

In [19]: hosts
Out[19]: {'ha-host': 'ucs59rangbala.rt.cisco.com'}

In [20]: server.get_datastores()
Out[20]:
{'10.78.87.44:/common/adminsftp/fresh_install/': 'blrr36ccm44_NFS',
 '10.78.87.74:/common/adminsftp/fresh_install/': 'blrr40ccm74_NFS',
 '4e0ab072-9a6cab72-a010-0010189c04ea': 'datastore1 (3)',
 '4e0ab088-5443c956-a8bf-0010189c04ea': 'datastore2 (1)'}

In [21]: server.get_datacenters()
Out[21]: {'ha-datacenter': 'ha-datacenter'}

In [22]: server.get_re
server.get_registered_vms  server.get_resource_pools 

In [22]: server.get_resource_pools()
Out[22]: {'ha-root-pool': '/Resources'}

<<<

I attached the script with this message

How do I fix this issue ?

Thanks and regards
~S

    cisp.set_element_deploymentOption("")
    if host:
        h = cisp.new_hostSystem(host)
        h.set_attribute_type(host.get_attribute_type())
        cisp.set_element_hostSystem(h)

    if network:
        network_mapping = cisp.new_networkMapping()
        network_mapping.set_element_name(network)
        n_mor = network_mapping.new_network(network_mor)
        n_mor.set_attribute_type(network_mor.get_attribute_type())
        network_mapping.set_element_network(n_mor)

        network_mapping2 = cisp.new_networkMapping()
        network_mapping2.set_element_name("Internal")
        n_mor = network_mapping.new_network(network_mor)
        n_mor.set_attribute_type(network_mor.get_attribute_type())
        network_mapping2.set_element_network(n_mor)

        cisp.set_element_networkMapping([network_mapping,
network_mapping2])


    if ip_allocation_policy:
        cisp.set_element_ipAllocationPolicy(ip_allocation_policy)
    if ip_protocol:
        cisp.set_element_ipProtocol(ip_protocol)
    if disk_provisioning:
        cisp.set_element_diskProvisioning(disk_provisioning)

    request.set_element_cisp(cisp)
    return s._proxy.CreateImportSpec(request)._returnval

def import_vapp(resource_pool, import_spec, host=None, folder=None):

    #get the host MOR
    if host:
        hosts = s.get_hosts()
        host = hosts.get(host)
        if not host:
            raise ValueError("invalid ESX host name")

    #get the vm folder MOR
    if folder:
        folder = find_vmfolder_by_name(folder)
    request = VI.ImportVAppRequestMsg()
    _this =request.new__this(resource_pool)
    _this.set_attribute_type(resource_pool.get_attribute_type())
    request.set_element__this(_this)
    request.set_element_spec(import_spec.ImportSpec)
    if host:

        h = request.new_host(host)
        h.set_attribute_type(host.get_attribute_type())
        request.set_element_host(h)

    if folder:
        f = request.new_folder(folder)
        f.set_attribute_type(folder.get_attribute_type())
        request.set_element_folder(f)
    return s._proxy.ImportVApp(request)._returnval


if __name__ == "__main__":

    #you can get the resource pools running s._get_resource_pools()
    RESOURCE_POOL = "/Resources"

    OVF_FILE = r"C:\FreeSCO\FreeSCO-043.ovf"

    #you can get the host names running s.get_hosts()
    HOST = "localhost.localdomain"

    DATASTORE = "datastore1"
    NETWORK_NAME = "VM Network"
    VAPP_NAME = "My New VM2"

    s = VIServer()


    s.connect("host", "username", "password")

    try:
        resource_pool = s._get_resource_pools()[RESOURCE_POOL]


        ovf = get_descriptor(OVF_FILE)
        descriptor_info =  parse_descriptor(ovf)

        support_info = validate_host(HOST, ovf)
        import_spec = create_import_spec(resource_pool,
                                         DATASTORE,
                                         ovf,
                                         VAPP_NAME,
                                         host=HOST,
                                         network=NETWORK_NAME,

                                         )
        if hasattr(import_spec, "Warning"):
            print "Warning:", import_spec.Warning[0].LocalizedMessage
        http_nfc_lease = import_vapp(resource_pool, import_spec,

host=HOST)


        lease = VIProperty(s, http_nfc_lease)
        while lease.state == 'initializing':
            print lease.state
            lease._flush_cache()
        if lease.state != 'ready':
            print "something went wrong"
            exit()

        for url in lease.info.deviceURL:

import_salil.py
Reply all
Reply to author
Forward
0 new messages