You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by je...@apache.org on 2010/02/09 14:50:20 UTC
svn commit: r908030 - /incubator/libcloud/trunk/libcloud/drivers/vcloud.py
Author: jerry
Date: Tue Feb 9 13:50:19 2010
New Revision: 908030
URL: http://svn.apache.org/viewvc?rev=908030&view=rev
Log:
80-col formatting update: drivers/vcloud.py
Modified:
incubator/libcloud/trunk/libcloud/drivers/vcloud.py
Modified: incubator/libcloud/trunk/libcloud/drivers/vcloud.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/drivers/vcloud.py?rev=908030&r1=908029&r2=908030&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/drivers/vcloud.py (original)
+++ incubator/libcloud/trunk/libcloud/drivers/vcloud.py Tue Feb 9 13:50:19 2010
@@ -17,7 +17,8 @@
"""
from libcloud.providers import Provider
from libcloud.types import NodeState, InvalidCredsException
-from libcloud.base import Node, Response, ConnectionUserAndKey, NodeDriver, NodeSize, NodeImage, NodeAuthPassword, NodeLocation
+from libcloud.base import Node, Response, ConnectionUserAndKey, NodeDriver
+from libcloud.base import NodeSize, NodeImage, NodeAuthPassword, NodeLocation
import base64
import httplib
@@ -26,7 +27,10 @@
from xml.etree import ElementTree as ET
from xml.parsers.expat import ExpatError
-#From vcloud api "The VirtualQuantity element defines the number of MB of memory. This should be either 512 or a multiple of 1024 (1 GB)."
+"""
+From vcloud api "The VirtualQuantity element defines the number of MB
+of memory. This should be either 512 or a multiple of 1024 (1 GB)."
+"""
VIRTUAL_MEMORY_VALS = [512] + [1024 * i for i in range(1,9)]
DEFAULT_TASK_COMPLETION_TIMEOUT = 600
@@ -37,12 +41,14 @@
def fixxpath(root, xpath):
"""ElementTree wants namespaces in its xpaths, so here we add them."""
namespace, root_tag = root.tag[1:].split("}", 1)
- fixed_xpath = "/".join(["{%s}%s" % (namespace, e) for e in xpath.split("/")])
+ fixed_xpath = "/".join(["{%s}%s" % (namespace, e)
+ for e in xpath.split("/")])
return fixed_xpath
class InstantiateVAppXML(object):
-
- def __init__(self, name, template, net_href, cpus, memory, password=None, row=None, group=None):
+
+ def __init__(self, name, template, net_href, cpus, memory,
+ password=None, row=None, group=None):
self.name = name
self.template = template
self.net_href = net_href
@@ -56,12 +62,12 @@
def tostring(self):
return ET.tostring(self.root)
-
+
def _build_xmltree(self):
self.root = self._make_instantiation_root()
self._add_vapp_template(self.root)
- instantionation_params = ET.SubElement(self.root,
+ instantionation_params = ET.SubElement(self.root,
"InstantiationParams")
product = self._make_product_section(instantionation_params)
@@ -75,7 +81,7 @@
def _make_instantiation_root(self):
return ET.Element(
- "InstantiateVAppTemplateParams",
+ "InstantiateVAppTemplateParams",
{'name': self.name,
'xml:lang': 'en',
'xmlns': "http://www.vmware.com/vcloud/v0.8",
@@ -84,7 +90,7 @@
def _add_vapp_template(self, parent):
return ET.SubElement(
- parent,
+ parent,
"VAppTemplate",
{'href': self.template}
)
@@ -110,13 +116,13 @@
def _add_property(self, parent, ovfkey, ovfvalue):
return ET.SubElement(
- parent,
+ parent,
"Property",
{'xmlns': 'http://schemas.dmtf.org/ovf/envelope/1',
'ovf:key': ovfkey,
'ovf:value': ovfvalue}
)
-
+
def _make_virtual_hardware(self, parent):
vh = ET.SubElement(
parent,
@@ -155,7 +161,7 @@
def _add_instance_id(self, parent, id):
elm = ET.SubElement(
- parent,
+ parent,
"InstanceID",
{'xmlns': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData'}
)
@@ -201,7 +207,7 @@
return self.error
def success(self):
- return self.status in (httplib.OK, httplib.CREATED,
+ return self.status in (httplib.OK, httplib.CREATED,
httplib.NO_CONTENT, httplib.ACCEPTED)
class VCloudConnection(ConnectionUserAndKey):
@@ -215,18 +221,24 @@
return super(VCloudConnection, self).request(*args, **kwargs)
def check_org(self):
- self._get_auth_token() # the only way to get our org is by logging in.
+ # the only way to get our org is by logging in.
+ self._get_auth_token()
def _get_auth_headers(self):
"""Some providers need different headers than others"""
- return {'Authorization': "Basic %s" % base64.b64encode('%s:%s' % (self.user_id, self.key)),
- 'Content-Length': 0}
+ return {
+ 'Authorization':
+ "Basic %s"
+ % base64.b64encode('%s:%s' % (self.user_id, self.key)),
+ 'Content-Length': 0
+ }
def _get_auth_token(self):
if not self.token:
- conn = self.conn_classes[self.secure](self.host,
+ conn = self.conn_classes[self.secure](self.host,
self.port[self.secure])
- conn.request(method='POST', url='/api/v0.8/login', headers=self._get_auth_headers())
+ conn.request(method='POST', url='/api/v0.8/login',
+ headers=self._get_auth_headers())
resp = conn.getresponse()
headers = dict(resp.getheaders())
@@ -237,7 +249,9 @@
except KeyError:
raise InvalidCredsException()
- self.driver.org = get_url_path(body.find(fixxpath(body, 'Org')).get('href'))
+ self.driver.org = get_url_path(
+ body.find(fixxpath(body, 'Org')).get('href')
+ )
def add_default_headers(self, headers):
headers['Cookie'] = self.token
@@ -261,10 +275,13 @@
if not self._vdcs:
self.connection.check_org() # make sure the org is set.
res = self.connection.request(self.org)
- self._vdcs = [get_url_path(i.get('href'))
- for i in res.object.findall(fixxpath(res.object, "Link"))
- if i.get('type') == 'application/vnd.vmware.vcloud.vdc+xml']
-
+ self._vdcs = [
+ get_url_path(i.get('href'))
+ for i
+ in res.object.findall(fixxpath(res.object, "Link"))
+ if i.get('type') == 'application/vnd.vmware.vcloud.vdc+xml'
+ ]
+
return self._vdcs
@property
@@ -273,7 +290,10 @@
for vdc in self.vdcs:
res = self.connection.request(vdc).object
networks.extend(
- [network for network in res.findall(fixxpath(res, "AvailableNetworks/Network"))]
+ [network
+ for network in res.findall(
+ fixxpath(res, "AvailableNetworks/Network")
+ )]
)
return networks
@@ -292,7 +312,9 @@
# Following code to find private IPs works for Terremark
connections = elm.findall('{http://schemas.dmtf.org/ovf/envelope/1}NetworkConnectionSection/{http://www.vmware.com/vcloud/v0.8}NetworkConnection')
for connection in connections:
- ips = [ip.text for ip in connection.findall(fixxpath(elm, "IpAddress"))]
+ ips = [ip.text
+ for ip
+ in connection.findall(fixxpath(elm, "IpAddress"))]
if connection.get('Network') == 'Internal':
private_ips.extend(ips)
else:
@@ -309,68 +331,88 @@
def _get_catalog_hrefs(self):
res = self.connection.request(self.org)
- catalogs = [get_url_path(i.get('href'))
- for i in res.object.findall(fixxpath(res.object, "Link"))
- if i.get('type') == 'application/vnd.vmware.vcloud.catalog+xml']
+ catalogs = [
+ get_url_path(i.get('href'))
+ for i in res.object.findall(fixxpath(res.object, "Link"))
+ if i.get('type') == 'application/vnd.vmware.vcloud.catalog+xml'
+ ]
return catalogs
-
- def _wait_for_task_completion(self, task_href, timeout=DEFAULT_TASK_COMPLETION_TIMEOUT):
+
+ def _wait_for_task_completion(self, task_href,
+ timeout=DEFAULT_TASK_COMPLETION_TIMEOUT):
start_time = time.time()
res = self.connection.request(task_href)
status = res.object.get('status')
while status != 'success':
if status == 'error':
- raise Exception("Error status returned by task %s." % task_href)
+ raise Exception("Error status returned by task %s."
+ % task_href)
if status == 'canceled':
- raise Exception("Canceled status returned by task %s." % task_href)
+ raise Exception("Canceled status returned by task %s."
+ % task_href)
if (time.time() - start_time >= timeout):
- raise Exception("Timeout while waiting for task %s." % task_href)
+ raise Exception("Timeout while waiting for task %s."
+ % task_href)
time.sleep(5)
res = self.connection.request(task_href)
status = res.object.get('status')
-
+
def destroy_node(self, node):
node_path = get_url_path(node.id)
# blindly poweroff node, it will throw an exception if already off
try:
- res = self.connection.request('%s/power/action/poweroff' % node_path,
- method='POST')
+ res = self.connection.request('%s/power/action/poweroff'
+ % node_path,
+ method='POST')
self._wait_for_task_completion(res.object.get('href'))
- except Exception, e:
+ except Exception, e:
pass
try:
res = self.connection.request('%s/action/undeploy' % node_path,
method='POST')
self._wait_for_task_completion(res.object.get('href'))
- except ExpatError: # the undeploy response is malformed XML atm. We can remove this whent he providers fix the problem.
+ except ExpatError:
+ # The undeploy response is malformed XML atm.
+ # We can remove this whent he providers fix the problem.
pass
- except Exception, e: # some vendors don't implement undeploy at all yet, so catch this and move on.
+ except Exception, e:
+ # Some vendors don't implement undeploy at all yet,
+ # so catch this and move on.
pass
res = self.connection.request(node_path, method='DELETE')
return res.status == 202
def reboot_node(self, node):
- res = self.connection.request('%s/power/action/reset' % get_url_path(node.id),
- method='POST')
+ res = self.connection.request('%s/power/action/reset'
+ % get_url_path(node.id),
+ method='POST')
return res.status == 202 or res.status == 204
def list_nodes(self):
nodes = []
for vdc in self.vdcs:
- res = self.connection.request(vdc)
- elms = res.object.findall(fixxpath(res.object, "ResourceEntities/ResourceEntity"))
- vapps = [(i.get('name'), get_url_path(i.get('href')))
- for i in elms
- if i.get('type') == 'application/vnd.vmware.vcloud.vApp+xml' and
- i.get('name')]
+ res = self.connection.request(vdc)
+ elms = res.object.findall(fixxpath(
+ res.object, "ResourceEntities/ResourceEntity")
+ )
+ vapps = [
+ (i.get('name'), get_url_path(i.get('href')))
+ for i in elms
+ if i.get('type')
+ == 'application/vnd.vmware.vcloud.vApp+xml'
+ and i.get('name')
+ ]
for vapp_name, vapp_href in vapps:
res = self.connection.request(
vapp_href,
- headers={'Content-Type': 'application/vnd.vmware.vcloud.vApp+xml'}
+ headers={
+ 'Content-Type':
+ 'application/vnd.vmware.vcloud.vApp+xml'
+ }
)
nodes.append(self._to_node(vapp_name, res.object))
@@ -386,9 +428,8 @@
price=None,
driver=self.connection.driver
)
-
return ns
-
+
def list_sizes(self):
sizes = [self._to_size(i) for i in VIRTUAL_MEMORY_VALS]
return sizes
@@ -397,13 +438,17 @@
"""Given a catalog href returns contained catalog item hrefs"""
res = self.connection.request(
catalog,
- headers={'Content-Type': 'application/vnd.vmware.vcloud.catalog+xml'}
+ headers={
+ 'Content-Type':
+ 'application/vnd.vmware.vcloud.catalog+xml'
+ }
).object
cat_items = res.findall(fixxpath(res, "CatalogItems/CatalogItem"))
cat_item_hrefs = [i.get('href')
for i in cat_items
- if i.get('type') == 'application/vnd.vmware.vcloud.catalogItem+xml']
+ if i.get('type') ==
+ 'application/vnd.vmware.vcloud.catalogItem+xml']
return cat_item_hrefs
@@ -411,40 +456,53 @@
"""Given a catalog item href returns elementree"""
res = self.connection.request(
catalog_item,
- headers={'Content-Type': 'application/vnd.vmware.vcloud.catalogItem+xml'}
+ headers={
+ 'Content-Type':
+ 'application/vnd.vmware.vcloud.catalogItem+xml'
+ }
).object
return res
-
+
def list_images(self):
images = []
for vdc in self.vdcs:
res = self.connection.request(vdc).object
- res_ents = res.findall(fixxpath(res, "ResourceEntities/ResourceEntity"))
- images += [self._to_image(i)
- for i in res_ents
- if i.get('type') == 'application/vnd.vmware.vcloud.vAppTemplate+xml']
-
+ res_ents = res.findall(fixxpath(
+ res, "ResourceEntities/ResourceEntity")
+ )
+ images += [
+ self._to_image(i)
+ for i in res_ents
+ if i.get('type') ==
+ 'application/vnd.vmware.vcloud.vAppTemplate+xml'
+ ]
+
for catalog in self._get_catalog_hrefs():
for cat_item in self._get_catalogitems_hrefs(catalog):
- res = self._get_catalogitem(cat_item)
+ res = self._get_catalogitem(cat_item)
res_ents = res.findall(fixxpath(res, 'Entity'))
- images += [self._to_image(i)
- for i in res_ents
- if i.get('type') == 'application/vnd.vmware.vcloud.vAppTemplate+xml']
+ images += [
+ self._to_image(i)
+ for i in res_ents
+ if i.get('type') ==
+ 'application/vnd.vmware.vcloud.vAppTemplate+xml'
+ ]
return images
def create_node(self, **kwargs):
"""Creates and returns node.
- Non-standard optional keyword arguments:
- network -- link to a "Network" e.g., "https://services.vcloudexpress.terremark.com/api/v0.8/network/7"
- vdc -- link to a "VDC" e.g., "https://services.vcloudexpress.terremark.com/api/v0.8/vdc/1"
- cpus -- number of virtual cpus (limit depends on provider)
- password
- row
- group
+ Non-standard optional keyword arguments:
+ network -- link to a "Network" e.g.,
+ "https://services.vcloudexpress.terremark.com/api/v0.8/network/7"
+ vdc -- link to a "VDC" e.g.,
+ "https://services.vcloudexpress.terremark.com/api/v0.8/vdc/1"
+ cpus -- number of virtual cpus (limit depends on provider)
+ password
+ row
+ group
"""
name = kwargs['name']
image = kwargs['image']
@@ -465,8 +523,8 @@
raise ValueError('auth must be of NodeAuthPassword type')
instantiate_xml = InstantiateVAppXML(
- name=name,
- template=image.id,
+ name=name,
+ template=image.id,
net_href=network,
cpus=str(kwargs.get('cpus', 1)),
memory=str(size.ram),
@@ -476,19 +534,25 @@
)
# Instantiate VM and get identifier.
- res = self.connection.request('%s/action/instantiateVAppTemplate' % kwargs.get('vdc', self.vdcs[0]),
- data=instantiate_xml.tostring(),
- method='POST',
- headers={'Content-Type': 'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml'})
+ res = self.connection.request(
+ '%s/action/instantiateVAppTemplate'
+ % kwargs.get('vdc', self.vdcs[0]),
+ data=instantiate_xml.tostring(),
+ method='POST',
+ headers={
+ 'Content-Type':
+ 'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml'
+ }
+ )
vapp_name = res.object.get('name')
vapp_href = get_url_path(res.object.get('href'))
# Deploy the VM from the identifier.
res = self.connection.request('%s/action/deploy' % vapp_href,
method='POST')
-
+
self._wait_for_task_completion(res.object.get('href'))
-
+
# Power on the VM.
res = self.connection.request('%s/power/action/powerOn' % vapp_href,
method='POST')
@@ -501,13 +565,15 @@
features = {"create_node": ["password"]}
class HostingComConnection(VCloudConnection):
- host = "vcloud.safesecureweb.com"
-
+ host = "vcloud.safesecureweb.com"
+
def _get_auth_headers(self):
"""hosting.com doesn't follow the standard vCloud authentication API"""
- return {'Authentication': base64.b64encode('%s:%s' % (self.user_id, self.key)),
- 'Content-Length': 0}
-
+ return {
+ 'Authentication':
+ base64.b64encode('%s:%s' % (self.user_id, self.key)),
+ 'Content-Length': 0
+ }
class HostingComDriver(VCloudNodeDriver):
connectionCls = HostingComConnection