You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by an...@apache.org on 2016/11/14 23:51:05 UTC

[18/56] [abbrv] libcloud git commit: Removed sdist

http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/vcloud.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/vcloud.py b/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/vcloud.py
deleted file mode 100644
index 9789eaf..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/vcloud.py
+++ /dev/null
@@ -1,2226 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""
-VMware vCloud driver.
-"""
-import copy
-import sys
-import re
-import base64
-import os
-from libcloud.utils.py3 import httplib
-from libcloud.utils.py3 import urlencode
-from libcloud.utils.py3 import urlparse
-from libcloud.utils.py3 import b
-from libcloud.utils.py3 import next
-
-urlparse = urlparse.urlparse
-
-import time
-
-try:
-    from lxml import etree as ET
-except ImportError:
-    from xml.etree import ElementTree as ET
-
-from xml.parsers.expat import ExpatError
-
-from libcloud.common.base import XmlResponse, ConnectionUserAndKey
-from libcloud.common.types import InvalidCredsError, LibcloudError
-from libcloud.compute.providers import Provider
-from libcloud.compute.types import NodeState
-from libcloud.compute.base import Node, NodeDriver, NodeLocation
-from libcloud.compute.base import NodeSize, NodeImage
-
-"""
-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 timeout (in seconds) for long running tasks
-DEFAULT_TASK_COMPLETION_TIMEOUT = 600
-
-DEFAULT_API_VERSION = '0.8'
-
-"""
-Valid vCloud API v1.5 input values.
-"""
-VIRTUAL_CPU_VALS_1_5 = [i for i in range(1, 9)]
-FENCE_MODE_VALS_1_5 = ['bridged', 'isolated', 'natRouted']
-IP_MODE_VALS_1_5 = ['POOL', 'DHCP', 'MANUAL', 'NONE']
-
-
-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("/")])
-    return fixed_xpath
-
-
-def get_url_path(url):
-    return urlparse(url.strip()).path
-
-
-class Vdc(object):
-    """
-    Virtual datacenter (vDC) representation
-    """
-    def __init__(self, id, name, driver, allocation_model=None, cpu=None,
-                 memory=None, storage=None):
-        self.id = id
-        self.name = name
-        self.driver = driver
-        self.allocation_model = allocation_model
-        self.cpu = cpu
-        self.memory = memory
-        self.storage = storage
-
-    def __repr__(self):
-        return ('<Vdc: id=%s, name=%s, driver=%s  ...>'
-                % (self.id, self.name, self.driver.name))
-
-
-class Capacity(object):
-    """
-    Represents CPU, Memory or Storage capacity of vDC.
-    """
-    def __init__(self, limit, used, units):
-        self.limit = limit
-        self.used = used
-        self.units = units
-
-    def __repr__(self):
-        return ('<Capacity: limit=%s, used=%s, units=%s>'
-                % (self.limit, self.used, self.units))
-
-
-class ControlAccess(object):
-    """
-    Represents control access settings of a node
-    """
-    class AccessLevel(object):
-        READ_ONLY = 'ReadOnly'
-        CHANGE = 'Change'
-        FULL_CONTROL = 'FullControl'
-
-    def __init__(self, node, everyone_access_level, subjects=None):
-        self.node = node
-        self.everyone_access_level = everyone_access_level
-        if not subjects:
-            subjects = []
-        self.subjects = subjects
-
-    def __repr__(self):
-        return ('<ControlAccess: node=%s, everyone_access_level=%s, '
-                'subjects=%s>'
-                % (self.node, self.everyone_access_level, self.subjects))
-
-
-class Subject(object):
-    """
-    User or group subject
-    """
-    def __init__(self, type, name, access_level, id=None):
-        self.type = type
-        self.name = name
-        self.access_level = access_level
-        self.id = id
-
-    def __repr__(self):
-        return ('<Subject: type=%s, name=%s, access_level=%s>'
-                % (self.type, self.name, self.access_level))
-
-
-class InstantiateVAppXML(object):
-
-    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
-        self.cpus = cpus
-        self.memory = memory
-        self.password = password
-        self.row = row
-        self.group = group
-
-        self._build_xmltree()
-
-    def tostring(self):
-        return ET.tostring(self.root)
-
-    def _build_xmltree(self):
-        self.root = self._make_instantiation_root()
-
-        self._add_vapp_template(self.root)
-        instantiation_params = ET.SubElement(self.root,
-                                             "InstantiationParams")
-
-        # product and virtual hardware
-        self._make_product_section(instantiation_params)
-        self._make_virtual_hardware(instantiation_params)
-
-        network_config_section = ET.SubElement(instantiation_params,
-                                               "NetworkConfigSection")
-
-        network_config = ET.SubElement(network_config_section,
-                                       "NetworkConfig")
-        self._add_network_association(network_config)
-
-    def _make_instantiation_root(self):
-        return ET.Element(
-            "InstantiateVAppTemplateParams",
-            {'name': self.name,
-             'xml:lang': 'en',
-             'xmlns': "http://www.vmware.com/vcloud/v0.8",
-             'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"}
-        )
-
-    def _add_vapp_template(self, parent):
-        return ET.SubElement(
-            parent,
-            "VAppTemplate",
-            {'href': self.template}
-        )
-
-    def _make_product_section(self, parent):
-        prod_section = ET.SubElement(
-            parent,
-            "ProductSection",
-            {'xmlns:q1': "http://www.vmware.com/vcloud/v0.8",
-             'xmlns:ovf': "http://schemas.dmtf.org/ovf/envelope/1"}
-        )
-
-        if self.password:
-            self._add_property(prod_section, 'password', self.password)
-
-        if self.row:
-            self._add_property(prod_section, 'row', self.row)
-
-        if self.group:
-            self._add_property(prod_section, 'group', self.group)
-
-        return prod_section
-
-    def _add_property(self, parent, ovfkey, ovfvalue):
-        return ET.SubElement(
-            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,
-            "VirtualHardwareSection",
-            {'xmlns:q1': "http://www.vmware.com/vcloud/v0.8"}
-        )
-
-        self._add_cpu(vh)
-        self._add_memory(vh)
-
-        return vh
-
-    def _add_cpu(self, parent):
-        cpu_item = ET.SubElement(
-            parent,
-            "Item",
-            {'xmlns': "http://schemas.dmtf.org/ovf/envelope/1"}
-        )
-        self._add_instance_id(cpu_item, '1')
-        self._add_resource_type(cpu_item, '3')
-        self._add_virtual_quantity(cpu_item, self.cpus)
-
-        return cpu_item
-
-    def _add_memory(self, parent):
-        mem_item = ET.SubElement(
-            parent,
-            'Item',
-            {'xmlns': "http://schemas.dmtf.org/ovf/envelope/1"}
-        )
-        self._add_instance_id(mem_item, '2')
-        self._add_resource_type(mem_item, '4')
-        self._add_virtual_quantity(mem_item, self.memory)
-
-        return mem_item
-
-    def _add_instance_id(self, parent, id):
-        elm = ET.SubElement(
-            parent,
-            'InstanceID',
-            {'xmlns': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/'
-                      'CIM_ResourceAllocationSettingData'}
-        )
-        elm.text = id
-        return elm
-
-    def _add_resource_type(self, parent, type):
-        elm = ET.SubElement(
-            parent,
-            'ResourceType',
-            {'xmlns': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/'
-                      'CIM_ResourceAllocationSettingData'}
-        )
-        elm.text = type
-        return elm
-
-    def _add_virtual_quantity(self, parent, amount):
-        elm = ET.SubElement(
-            parent,
-            'VirtualQuantity',
-            {'xmlns': 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/'
-                      'CIM_ResourceAllocationSettingData'}
-        )
-        elm.text = amount
-        return elm
-
-    def _add_network_association(self, parent):
-        return ET.SubElement(
-            parent,
-            'NetworkAssociation',
-            {'href': self.net_href}
-        )
-
-
-class VCloudResponse(XmlResponse):
-
-    def success(self):
-        return self.status in (httplib.OK, httplib.CREATED,
-                               httplib.NO_CONTENT, httplib.ACCEPTED)
-
-
-class VCloudConnection(ConnectionUserAndKey):
-
-    """
-    Connection class for the vCloud driver
-    """
-
-    responseCls = VCloudResponse
-    token = None
-    host = None
-
-    def request(self, *args, **kwargs):
-        self._get_auth_token()
-        return super(VCloudConnection, self).request(*args, **kwargs)
-
-    def check_org(self):
-        # 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(
-                b('%s:%s' % (self.user_id, self.key))).decode('utf-8'),
-            'Content-Length': '0',
-            'Accept': 'application/*+xml'
-        }
-
-    def _get_auth_token(self):
-        if not self.token:
-            self.connection.request(method='POST', url='/api/v0.8/login',
-                                    headers=self._get_auth_headers())
-
-            resp = self.connection.getresponse()
-            headers = dict(resp.getheaders())
-            body = ET.XML(resp.read())
-
-            try:
-                self.token = headers['set-cookie']
-            except KeyError:
-                raise InvalidCredsError()
-
-            self.driver.org = get_url_path(
-                body.find(fixxpath(body, 'Org')).get('href')
-            )
-
-    def add_default_headers(self, headers):
-        headers['Cookie'] = self.token
-        headers['Accept'] = 'application/*+xml'
-        return headers
-
-
-class VCloudNodeDriver(NodeDriver):
-
-    """
-    vCloud node driver
-    """
-
-    type = Provider.VCLOUD
-    name = 'vCloud'
-    website = 'http://www.vmware.com/products/vcloud/'
-    connectionCls = VCloudConnection
-    org = None
-    _vdcs = None
-
-    NODE_STATE_MAP = {'0': NodeState.PENDING,
-                      '1': NodeState.PENDING,
-                      '2': NodeState.PENDING,
-                      '3': NodeState.PENDING,
-                      '4': NodeState.RUNNING}
-
-    features = {'create_node': ['password']}
-
-    def __new__(cls, key, secret=None, secure=True, host=None, port=None,
-                api_version=DEFAULT_API_VERSION, **kwargs):
-        if cls is VCloudNodeDriver:
-            if api_version == '0.8':
-                cls = VCloudNodeDriver
-            elif api_version == '1.5':
-                cls = VCloud_1_5_NodeDriver
-            elif api_version == '5.1':
-                cls = VCloud_5_1_NodeDriver
-            elif api_version == '5.5':
-                cls = VCloud_5_5_NodeDriver
-            else:
-                raise NotImplementedError(
-                    "No VCloudNodeDriver found for API version %s" %
-                    (api_version))
-        return super(VCloudNodeDriver, cls).__new__(cls)
-
-    @property
-    def vdcs(self):
-        """
-        vCloud virtual data centers (vDCs).
-
-        :return: list of vDC objects
-        :rtype: ``list`` of :class:`Vdc`
-        """
-        if not self._vdcs:
-            self.connection.check_org()  # make sure the org is set.
-            res = self.connection.request(self.org)
-            self._vdcs = [
-                self._to_vdc(
-                    self.connection.request(get_url_path(i.get('href'))).object
-                )
-                for i in res.object.findall(fixxpath(res.object, "Link"))
-                if i.get('type') == 'application/vnd.vmware.vcloud.vdc+xml'
-            ]
-        return self._vdcs
-
-    def _to_vdc(self, vdc_elm):
-        return Vdc(vdc_elm.get('href'), vdc_elm.get('name'), self)
-
-    def _get_vdc(self, vdc_name):
-        vdc = None
-        if not vdc_name:
-            # Return the first organisation VDC found
-            vdc = self.vdcs[0]
-        else:
-            for v in self.vdcs:
-                if v.name == vdc_name:
-                    vdc = v
-            if vdc is None:
-                raise ValueError('%s virtual data centre could not be found',
-                                 vdc_name)
-        return vdc
-
-    @property
-    def networks(self):
-        networks = []
-        for vdc in self.vdcs:
-            res = self.connection.request(get_url_path(vdc.id)).object
-            networks.extend(
-                [network
-                 for network in res.findall(
-                     fixxpath(res, 'AvailableNetworks/Network')
-
-                 )]
-            )
-
-        return networks
-
-    def _to_image(self, image):
-        image = NodeImage(id=image.get('href'),
-                          name=image.get('name'),
-                          driver=self.connection.driver)
-        return image
-
-    def _to_node(self, elm):
-        state = self.NODE_STATE_MAP[elm.get('status')]
-        name = elm.get('name')
-        public_ips = []
-        private_ips = []
-
-        # Following code to find private IPs works for Terremark
-        connections = elm.findall('%s/%s' % (
-            '{http://schemas.dmtf.org/ovf/envelope/1}NetworkConnectionSection',
-            fixxpath(elm, 'NetworkConnection'))
-        )
-        if not connections:
-            connections = elm.findall(
-                fixxpath(
-                    elm,
-                    'Children/Vm/NetworkConnectionSection/NetworkConnection'))
-
-        for connection in connections:
-            ips = [ip.text
-                   for ip
-                   in connection.findall(fixxpath(elm, "IpAddress"))]
-            if connection.get('Network') == 'Internal':
-                private_ips.extend(ips)
-            else:
-                public_ips.extend(ips)
-
-        node = Node(id=elm.get('href'),
-                    name=name,
-                    state=state,
-                    public_ips=public_ips,
-                    private_ips=private_ips,
-                    driver=self.connection.driver)
-
-        return node
-
-    def _get_catalog_hrefs(self):
-        res = self.connection.request(self.org)
-        catalogs = [
-            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):
-        start_time = time.time()
-        res = self.connection.request(get_url_path(task_href))
-        status = res.object.get('status')
-        while status != 'success':
-            if status == 'error':
-                # Get error reason from the response body
-                error_elem = res.object.find(fixxpath(res.object, 'Error'))
-                error_msg = "Unknown error"
-                if error_elem is not None:
-                    error_msg = error_elem.get('message')
-                raise Exception("Error status returned by task %s.: %s"
-                                % (task_href, error_msg))
-            if status == 'canceled':
-                raise Exception("Canceled status returned by task %s."
-                                % task_href)
-            if (time.time() - start_time >= timeout):
-                raise Exception("Timeout (%s sec) while waiting for task %s."
-                                % (timeout, task_href))
-            time.sleep(5)
-            res = self.connection.request(get_url_path(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')
-            self._wait_for_task_completion(res.object.get('href'))
-        except Exception:
-            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.
-            pass
-        except Exception:
-            # 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 == httplib.ACCEPTED
-
-    def reboot_node(self, node):
-        res = self.connection.request('%s/power/action/reset'
-                                      % get_url_path(node.id),
-                                      method='POST')
-        return res.status in [httplib.ACCEPTED, httplib.NO_CONTENT]
-
-    def list_nodes(self):
-        return self.ex_list_nodes()
-
-    def ex_list_nodes(self, vdcs=None):
-        """
-        List all nodes across all vDCs. Using 'vdcs' you can specify which vDCs
-        should be queried.
-
-        :param vdcs: None, vDC or a list of vDCs to query. If None all vDCs
-                     will be queried.
-        :type vdcs: :class:`Vdc`
-
-        :rtype: ``list`` of :class:`Node`
-        """
-        if not vdcs:
-            vdcs = self.vdcs
-        if not isinstance(vdcs, (list, tuple)):
-            vdcs = [vdcs]
-        nodes = []
-        for vdc in vdcs:
-            res = self.connection.request(get_url_path(vdc.id))
-            elms = res.object.findall(fixxpath(
-                res.object, "ResourceEntities/ResourceEntity")
-            )
-            vapps = [
-                (i.get('name'), 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:
-                try:
-                    res = self.connection.request(
-                        get_url_path(vapp_href),
-                        headers={'Content-Type':
-                                 'application/vnd.vmware.vcloud.vApp+xml'}
-                    )
-                    nodes.append(self._to_node(res.object))
-                except Exception:
-                    # The vApp was probably removed since the previous vDC
-                    # query, ignore
-                    e = sys.exc_info()[1]
-                    if not (e.args[0].tag.endswith('Error') and
-                            e.args[0].get('minorErrorCode') ==
-                            'ACCESS_TO_RESOURCE_IS_FORBIDDEN'):
-                        raise
-
-        return nodes
-
-    def _to_size(self, ram):
-        ns = NodeSize(
-            id=None,
-            name="%s Ram" % ram,
-            ram=ram,
-            disk=None,
-            bandwidth=None,
-            price=None,
-            driver=self.connection.driver
-        )
-        return ns
-
-    def list_sizes(self, location=None):
-        sizes = [self._to_size(i) for i in VIRTUAL_MEMORY_VALS]
-        return sizes
-
-    def _get_catalogitems_hrefs(self, catalog):
-        """Given a catalog href returns contained catalog item hrefs"""
-        res = self.connection.request(
-            get_url_path(catalog),
-            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']
-
-        return cat_item_hrefs
-
-    def _get_catalogitem(self, catalog_item):
-        """Given a catalog item href returns elementree"""
-        res = self.connection.request(
-            get_url_path(catalog_item),
-            headers={
-                'Content-Type': 'application/vnd.vmware.vcloud.catalogItem+xml'
-            }
-        ).object
-
-        return res
-
-    def list_images(self, location=None):
-        images = []
-        for vdc in self.vdcs:
-            res = self.connection.request(get_url_path(vdc.id)).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'
-            ]
-
-        for catalog in self._get_catalog_hrefs():
-            for cat_item in self._get_catalogitems_hrefs(catalog):
-                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'
-                ]
-
-        def idfun(image):
-            return image.id
-
-        return self._uniquer(images, idfun)
-
-    def _uniquer(self, seq, idfun=None):
-        if idfun is None:
-            def idfun(x):
-                return x
-        seen = {}
-        result = []
-        for item in seq:
-            marker = idfun(item)
-            if marker in seen:
-                continue
-            seen[marker] = 1
-            result.append(item)
-        return result
-
-    def create_node(self, **kwargs):
-        """
-        Creates and returns node.
-
-        :keyword    ex_network: link to a "Network" e.g.,
-                    ``https://services.vcloudexpress...``
-        :type       ex_network: ``str``
-
-        :keyword    ex_vdc: Name of organisation's virtual data
-                            center where vApp VMs will be deployed.
-        :type       ex_vdc: ``str``
-
-        :keyword    ex_cpus: number of virtual cpus (limit depends on provider)
-        :type       ex_cpus: ``int``
-
-        :type       ex_row: ``str``
-
-        :type       ex_group: ``str``
-        """
-        name = kwargs['name']
-        image = kwargs['image']
-        size = kwargs['size']
-
-        # Some providers don't require a network link
-        try:
-            network = kwargs.get('ex_network', self.networks[0].get('href'))
-        except IndexError:
-            network = ''
-
-        password = None
-        auth = self._get_and_check_auth(kwargs.get('auth'))
-        password = auth.password
-
-        instantiate_xml = InstantiateVAppXML(
-            name=name,
-            template=image.id,
-            net_href=network,
-            cpus=str(kwargs.get('ex_cpus', 1)),
-            memory=str(size.ram),
-            password=password,
-            row=kwargs.get('ex_row', None),
-            group=kwargs.get('ex_group', None)
-        )
-
-        vdc = self._get_vdc(kwargs.get('ex_vdc', None))
-
-        # Instantiate VM and get identifier.
-        content_type = \
-            'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml'
-        res = self.connection.request(
-            '%s/action/instantiateVAppTemplate' % get_url_path(vdc.id),
-            data=instantiate_xml.tostring(),
-            method='POST',
-            headers={'Content-Type': content_type}
-        )
-        vapp_path = get_url_path(res.object.get('href'))
-
-        # Deploy the VM from the identifier.
-        res = self.connection.request('%s/action/deploy' % vapp_path,
-                                      method='POST')
-
-        self._wait_for_task_completion(res.object.get('href'))
-
-        # Power on the VM.
-        res = self.connection.request('%s/power/action/powerOn' % vapp_path,
-                                      method='POST')
-
-        res = self.connection.request(vapp_path)
-        node = self._to_node(res.object)
-
-        if getattr(auth, "generated", False):
-            node.extra['password'] = auth.password
-
-        return node
-
-
-class HostingComConnection(VCloudConnection):
-
-    """
-    vCloud connection subclass for Hosting.com
-    """
-
-    host = "vcloud.safesecureweb.com"
-
-    def _get_auth_headers(self):
-        """hosting.com doesn't follow the standard vCloud authentication API"""
-        return {
-            'Authentication': base64.b64encode(b('%s:%s' % (self.user_id,
-                                                            self.key))),
-            'Content-Length': '0'
-        }
-
-
-class HostingComDriver(VCloudNodeDriver):
-
-    """
-    vCloud node driver for Hosting.com
-    """
-    connectionCls = HostingComConnection
-
-
-class TerremarkConnection(VCloudConnection):
-
-    """
-    vCloud connection subclass for Terremark
-    """
-
-    host = "services.vcloudexpress.terremark.com"
-
-
-class TerremarkDriver(VCloudNodeDriver):
-
-    """
-    vCloud node driver for Terremark
-    """
-
-    connectionCls = TerremarkConnection
-
-    def list_locations(self):
-        return [NodeLocation(0, "Terremark Texas", 'US', self)]
-
-
-class VCloud_1_5_Connection(VCloudConnection):
-
-    def _get_auth_headers(self):
-        """Compatibility for using v1.5 API under vCloud Director 5.1"""
-        return {
-            'Authorization': "Basic %s" % base64.b64encode(
-                b('%s:%s' % (self.user_id, self.key))).decode('utf-8'),
-            'Content-Length': '0',
-            'Accept': 'application/*+xml;version=1.5'
-        }
-
-    def _get_auth_token(self):
-        if not self.token:
-            # Log In
-            self.connection.request(method='POST', url='/api/sessions',
-                                    headers=self._get_auth_headers())
-
-            resp = self.connection.getresponse()
-            headers = dict(resp.getheaders())
-
-            # Set authorization token
-            try:
-                self.token = headers['x-vcloud-authorization']
-            except KeyError:
-                raise InvalidCredsError()
-
-            # Get the URL of the Organization
-            body = ET.XML(resp.read())
-            self.org_name = body.get('org')
-            org_list_url = get_url_path(
-                next((link for link in body.findall(fixxpath(body, 'Link'))
-                     if link.get('type') ==
-                     'application/vnd.vmware.vcloud.orgList+xml')).get('href')
-            )
-
-            if self.proxy_url is not None:
-                self.connection.set_http_proxy(self.proxy_url)
-            self.connection.request(method='GET', url=org_list_url,
-                                    headers=self.add_default_headers({}))
-            body = ET.XML(self.connection.getresponse().read())
-            self.driver.org = get_url_path(
-                next((org for org in body.findall(fixxpath(body, 'Org'))
-                     if org.get('name') == self.org_name)).get('href')
-            )
-
-    def add_default_headers(self, headers):
-        headers['Accept'] = 'application/*+xml;version=1.5'
-        headers['x-vcloud-authorization'] = self.token
-        return headers
-
-
-class VCloud_5_5_Connection(VCloud_1_5_Connection):
-    def add_default_headers(self, headers):
-        headers['Accept'] = 'application/*+xml;version=5.5'
-        headers['x-vcloud-authorization'] = self.token
-        return headers
-
-
-class Instantiate_1_5_VAppXML(object):
-
-    def __init__(self, name, template, network, vm_network=None,
-                 vm_fence=None):
-        self.name = name
-        self.template = template
-        self.network = network
-        self.vm_network = vm_network
-        self.vm_fence = vm_fence
-        self._build_xmltree()
-
-    def tostring(self):
-        return ET.tostring(self.root)
-
-    def _build_xmltree(self):
-        self.root = self._make_instantiation_root()
-
-        if self.network is not None:
-            instantionation_params = ET.SubElement(self.root,
-                                                   'InstantiationParams')
-            network_config_section = ET.SubElement(instantionation_params,
-                                                   'NetworkConfigSection')
-            ET.SubElement(
-                network_config_section,
-                'Info',
-                {'xmlns': 'http://schemas.dmtf.org/ovf/envelope/1'}
-            )
-            network_config = ET.SubElement(network_config_section,
-                                           'NetworkConfig')
-            self._add_network_association(network_config)
-
-        self._add_vapp_template(self.root)
-
-    def _make_instantiation_root(self):
-        return ET.Element(
-            'InstantiateVAppTemplateParams',
-            {'name': self.name,
-             'deploy': 'false',
-             'powerOn': 'false',
-             'xml:lang': 'en',
-             'xmlns': 'http://www.vmware.com/vcloud/v1.5',
-             'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
-        )
-
-    def _add_vapp_template(self, parent):
-        return ET.SubElement(
-            parent,
-            'Source',
-            {'href': self.template}
-        )
-
-    def _add_network_association(self, parent):
-        if self.vm_network is None:
-            # Don't set a custom vApp VM network name
-            parent.set('networkName', self.network.get('name'))
-        else:
-            # Set a custom vApp VM network name
-            parent.set('networkName', self.vm_network)
-        configuration = ET.SubElement(parent, 'Configuration')
-        ET.SubElement(configuration, 'ParentNetwork',
-                      {'href': self.network.get('href')})
-
-        if self.vm_fence is None:
-            fencemode = self.network.find(fixxpath(self.network,
-                                          'Configuration/FenceMode')).text
-        else:
-            fencemode = self.vm_fence
-        ET.SubElement(configuration, 'FenceMode').text = fencemode
-
-
-class VCloud_1_5_NodeDriver(VCloudNodeDriver):
-    connectionCls = VCloud_1_5_Connection
-
-    # Based on
-    # http://pubs.vmware.com/vcloud-api-1-5/api_prog/
-    # GUID-843BE3AD-5EF6-4442-B864-BCAE44A51867.html
-    NODE_STATE_MAP = {'-1': NodeState.UNKNOWN,
-                      '0': NodeState.PENDING,
-                      '1': NodeState.PENDING,
-                      '2': NodeState.PENDING,
-                      '3': NodeState.PENDING,
-                      '4': NodeState.RUNNING,
-                      '5': NodeState.RUNNING,
-                      '6': NodeState.UNKNOWN,
-                      '7': NodeState.UNKNOWN,
-                      '8': NodeState.STOPPED,
-                      '9': NodeState.UNKNOWN,
-                      '10': NodeState.UNKNOWN}
-
-    def list_locations(self):
-        return [NodeLocation(id=self.connection.host,
-                name=self.connection.host, country="N/A", driver=self)]
-
-    def ex_find_node(self, node_name, vdcs=None):
-        """
-        Searches for node across specified vDCs. This is more effective than
-        querying all nodes to get a single instance.
-
-        :param node_name: The name of the node to search for
-        :type node_name: ``str``
-
-        :param vdcs: None, vDC or a list of vDCs to search in. If None all vDCs
-                     will be searched.
-        :type vdcs: :class:`Vdc`
-
-        :return: node instance or None if not found
-        :rtype: :class:`Node` or ``None``
-        """
-        if not vdcs:
-            vdcs = self.vdcs
-        if not getattr(vdcs, '__iter__', False):
-            vdcs = [vdcs]
-        for vdc in vdcs:
-            res = self.connection.request(get_url_path(vdc.id))
-            xpath = fixxpath(res.object, "ResourceEntities/ResourceEntity")
-            entity_elems = res.object.findall(xpath)
-            for entity_elem in entity_elems:
-                if entity_elem.get('type') == \
-                        'application/vnd.vmware.vcloud.vApp+xml' and \
-                        entity_elem.get('name') == node_name:
-                    path = get_url_path(entity_elem.get('href'))
-                    headers = {'Content-Type':
-                               'application/vnd.vmware.vcloud.vApp+xml'}
-                    res = self.connection.request(path,
-                                                  headers=headers)
-                    return self._to_node(res.object)
-        return None
-
-    def destroy_node(self, node):
-        try:
-            self.ex_undeploy_node(node)
-        except Exception:
-            # Some vendors don't implement undeploy at all yet,
-            # so catch this and move on.
-            pass
-
-        res = self.connection.request(get_url_path(node.id), method='DELETE')
-        return res.status == httplib.ACCEPTED
-
-    def reboot_node(self, node):
-        res = self.connection.request('%s/power/action/reset'
-                                      % get_url_path(node.id),
-                                      method='POST')
-        if res.status in [httplib.ACCEPTED, httplib.NO_CONTENT]:
-            self._wait_for_task_completion(res.object.get('href'))
-            return True
-        else:
-            return False
-
-    def ex_deploy_node(self, node):
-        """
-        Deploys existing node. Equal to vApp "start" operation.
-
-        :param  node: The node to be deployed
-        :type   node: :class:`Node`
-
-        :rtype: :class:`Node`
-        """
-        data = {'powerOn': 'true',
-                'xmlns': 'http://www.vmware.com/vcloud/v1.5'}
-        deploy_xml = ET.Element('DeployVAppParams', data)
-        path = get_url_path(node.id)
-        headers = {
-            'Content-Type':
-            'application/vnd.vmware.vcloud.deployVAppParams+xml'
-        }
-        res = self.connection.request('%s/action/deploy' % path,
-                                      data=ET.tostring(deploy_xml),
-                                      method='POST',
-                                      headers=headers)
-        self._wait_for_task_completion(res.object.get('href'))
-        res = self.connection.request(get_url_path(node.id))
-        return self._to_node(res.object)
-
-    def ex_undeploy_node(self, node):
-        """
-        Undeploys existing node. Equal to vApp "stop" operation.
-
-        :param  node: The node to be deployed
-        :type   node: :class:`Node`
-
-        :rtype: :class:`Node`
-        """
-        data = {'xmlns': 'http://www.vmware.com/vcloud/v1.5'}
-        undeploy_xml = ET.Element('UndeployVAppParams', data)
-        undeploy_power_action_xml = ET.SubElement(undeploy_xml,
-                                                  'UndeployPowerAction')
-        undeploy_power_action_xml.text = 'shutdown'
-
-        headers = {
-            'Content-Type':
-            'application/vnd.vmware.vcloud.undeployVAppParams+xml'
-        }
-
-        try:
-            res = self.connection.request(
-                '%s/action/undeploy' % get_url_path(node.id),
-                data=ET.tostring(undeploy_xml),
-                method='POST',
-                headers=headers)
-
-            self._wait_for_task_completion(res.object.get('href'))
-        except Exception:
-            undeploy_power_action_xml.text = 'powerOff'
-            res = self.connection.request(
-                '%s/action/undeploy' % get_url_path(node.id),
-                data=ET.tostring(undeploy_xml),
-                method='POST',
-                headers=headers)
-            self._wait_for_task_completion(res.object.get('href'))
-
-        res = self.connection.request(get_url_path(node.id))
-        return self._to_node(res.object)
-
-    def ex_power_off_node(self, node):
-        """
-        Powers on all VMs under specified node. VMs need to be This operation
-        is allowed only when the vApp/VM is powered on.
-
-        :param  node: The node to be powered off
-        :type   node: :class:`Node`
-
-        :rtype: :class:`Node`
-        """
-        return self._perform_power_operation(node, 'powerOff')
-
-    def ex_power_on_node(self, node):
-        """
-        Powers on all VMs under specified node. This operation is allowed
-        only when the vApp/VM is powered off or suspended.
-
-        :param  node: The node to be powered on
-        :type   node: :class:`Node`
-
-        :rtype: :class:`Node`
-        """
-        return self._perform_power_operation(node, 'powerOn')
-
-    def ex_shutdown_node(self, node):
-        """
-        Shutdowns all VMs under specified node. This operation is allowed only
-        when the vApp/VM is powered on.
-
-        :param  node: The node to be shut down
-        :type   node: :class:`Node`
-
-        :rtype: :class:`Node`
-        """
-        return self._perform_power_operation(node, 'shutdown')
-
-    def ex_suspend_node(self, node):
-        """
-        Suspends all VMs under specified node. This operation is allowed only
-        when the vApp/VM is powered on.
-
-        :param  node: The node to be suspended
-        :type   node: :class:`Node`
-
-        :rtype: :class:`Node`
-        """
-        return self._perform_power_operation(node, 'suspend')
-
-    def _perform_power_operation(self, node, operation):
-        res = self.connection.request(
-            '%s/power/action/%s' % (get_url_path(node.id), operation),
-            method='POST')
-        self._wait_for_task_completion(res.object.get('href'))
-        res = self.connection.request(get_url_path(node.id))
-        return self._to_node(res.object)
-
-    def ex_get_control_access(self, node):
-        """
-        Returns the control access settings for specified node.
-
-        :param  node: node to get the control access for
-        :type   node: :class:`Node`
-
-        :rtype: :class:`ControlAccess`
-        """
-        res = self.connection.request(
-            '%s/controlAccess' % get_url_path(node.id))
-        everyone_access_level = None
-        is_shared_elem = res.object.find(
-            fixxpath(res.object, "IsSharedToEveryone"))
-        if is_shared_elem is not None and is_shared_elem.text == 'true':
-            everyone_access_level = res.object.find(
-                fixxpath(res.object, "EveryoneAccessLevel")).text
-
-        # Parse all subjects
-        subjects = []
-        xpath = fixxpath(res.object, "AccessSettings/AccessSetting")
-        for elem in res.object.findall(xpath):
-            access_level = elem.find(fixxpath(res.object, "AccessLevel")).text
-            subject_elem = elem.find(fixxpath(res.object, "Subject"))
-            if subject_elem.get('type') == \
-               'application/vnd.vmware.admin.group+xml':
-                subj_type = 'group'
-            else:
-                subj_type = 'user'
-
-            path = get_url_path(subject_elem.get('href'))
-            res = self.connection.request(path)
-            name = res.object.get('name')
-            subject = Subject(type=subj_type,
-                              name=name,
-                              access_level=access_level,
-                              id=subject_elem.get('href'))
-            subjects.append(subject)
-
-        return ControlAccess(node, everyone_access_level, subjects)
-
-    def ex_set_control_access(self, node, control_access):
-        """
-        Sets control access for the specified node.
-
-        :param  node: node
-        :type   node: :class:`Node`
-
-        :param  control_access: control access settings
-        :type   control_access: :class:`ControlAccess`
-
-        :rtype: ``None``
-        """
-        xml = ET.Element('ControlAccessParams',
-                         {'xmlns': 'http://www.vmware.com/vcloud/v1.5'})
-        shared_to_everyone = ET.SubElement(xml, 'IsSharedToEveryone')
-        if control_access.everyone_access_level:
-            shared_to_everyone.text = 'true'
-            everyone_access_level = ET.SubElement(xml, 'EveryoneAccessLevel')
-            everyone_access_level.text = control_access.everyone_access_level
-        else:
-            shared_to_everyone.text = 'false'
-
-        # Set subjects
-        if control_access.subjects:
-            access_settings_elem = ET.SubElement(xml, 'AccessSettings')
-        for subject in control_access.subjects:
-            setting = ET.SubElement(access_settings_elem, 'AccessSetting')
-            if subject.id:
-                href = subject.id
-            else:
-                res = self.ex_query(type=subject.type, filter='name==' +
-                                    subject.name)
-                if not res:
-                    raise LibcloudError('Specified subject "%s %s" not found '
-                                        % (subject.type, subject.name))
-                href = res[0]['href']
-            ET.SubElement(setting, 'Subject', {'href': href})
-            ET.SubElement(setting, 'AccessLevel').text = subject.access_level
-
-        headers = {
-            'Content-Type': 'application/vnd.vmware.vcloud.controlAccess+xml'
-        }
-        self.connection.request(
-            '%s/action/controlAccess' % get_url_path(node.id),
-            data=ET.tostring(xml),
-            headers=headers,
-            method='POST')
-
-    def ex_get_metadata(self, node):
-        """
-        :param  node: node
-        :type   node: :class:`Node`
-
-        :return: dictionary mapping metadata keys to metadata values
-        :rtype: dictionary mapping ``str`` to ``str``
-        """
-        res = self.connection.request('%s/metadata' % (get_url_path(node.id)))
-        xpath = fixxpath(res.object, 'MetadataEntry')
-        metadata_entries = res.object.findall(xpath)
-        res_dict = {}
-
-        for entry in metadata_entries:
-            key = entry.findtext(fixxpath(res.object, 'Key'))
-            value = entry.findtext(fixxpath(res.object, 'Value'))
-            res_dict[key] = value
-
-        return res_dict
-
-    def ex_set_metadata_entry(self, node, key, value):
-        """
-        :param  node: node
-        :type   node: :class:`Node`
-
-        :param key: metadata key to be set
-        :type key: ``str``
-
-        :param value: metadata value to be set
-        :type value: ``str``
-
-        :rtype: ``None``
-        """
-        metadata_elem = ET.Element(
-            'Metadata',
-            {'xmlns': "http://www.vmware.com/vcloud/v1.5",
-             'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"}
-        )
-        entry = ET.SubElement(metadata_elem, 'MetadataEntry')
-        key_elem = ET.SubElement(entry, 'Key')
-        key_elem.text = key
-        value_elem = ET.SubElement(entry, 'Value')
-        value_elem.text = value
-
-        # send it back to the server
-        res = self.connection.request(
-            '%s/metadata' % get_url_path(node.id),
-            data=ET.tostring(metadata_elem),
-            headers={
-                'Content-Type': 'application/vnd.vmware.vcloud.metadata+xml'
-            },
-            method='POST')
-        self._wait_for_task_completion(res.object.get('href'))
-
-    def ex_query(self, type, filter=None, page=1, page_size=100, sort_asc=None,
-                 sort_desc=None):
-        """
-        Queries vCloud for specified type. See
-        http://www.vmware.com/pdf/vcd_15_api_guide.pdf for details. Each
-        element of the returned list is a dictionary with all attributes from
-        the record.
-
-        :param type: type to query (r.g. user, group, vApp etc.)
-        :type  type: ``str``
-
-        :param filter: filter expression (see documentation for syntax)
-        :type  filter: ``str``
-
-        :param page: page number
-        :type  page: ``int``
-
-        :param page_size: page size
-        :type  page_size: ``int``
-
-        :param sort_asc: sort in ascending order by specified field
-        :type  sort_asc: ``str``
-
-        :param sort_desc: sort in descending order by specified field
-        :type  sort_desc: ``str``
-
-        :rtype: ``list`` of dict
-        """
-        # This is a workaround for filter parameter encoding
-        # the urllib encodes (name==Developers%20Only) into
-        # %28name%3D%3DDevelopers%20Only%29) which is not accepted by vCloud
-        params = {
-            'type': type,
-            'pageSize': page_size,
-            'page': page,
-        }
-        if sort_asc:
-            params['sortAsc'] = sort_asc
-        if sort_desc:
-            params['sortDesc'] = sort_desc
-
-        url = '/api/query?' + urlencode(params)
-        if filter:
-            if not filter.startswith('('):
-                filter = '(' + filter + ')'
-            url += '&filter=' + filter.replace(' ', '+')
-
-        results = []
-        res = self.connection.request(url)
-        for elem in res.object:
-            if not elem.tag.endswith('Link'):
-                result = elem.attrib
-                result['type'] = elem.tag.split('}')[1]
-                results.append(result)
-        return results
-
-    def create_node(self, **kwargs):
-        """
-        Creates and returns node. If the source image is:
-          - vApp template - a new vApp is instantiated from template
-          - existing vApp - a new vApp is cloned from the source vApp. Can
-                            not clone more vApps is parallel otherwise
-                            resource busy error is raised.
-
-
-        @inherits: :class:`NodeDriver.create_node`
-
-        :keyword    image:  OS Image to boot on node. (required). Can be a
-                            NodeImage or existing Node that will be cloned.
-        :type       image:  :class:`NodeImage` or :class:`Node`
-
-        :keyword    ex_network: Organisation's network name for attaching vApp
-                                VMs to.
-        :type       ex_network: ``str``
-
-        :keyword    ex_vdc: Name of organisation's virtual data center where
-                            vApp VMs will be deployed.
-        :type       ex_vdc: ``str``
-
-        :keyword    ex_vm_names: list of names to be used as a VM and computer
-                                 name. The name must be max. 15 characters
-                                 long and follow the host name requirements.
-        :type       ex_vm_names: ``list`` of ``str``
-
-        :keyword    ex_vm_cpu: number of virtual CPUs/cores to allocate for
-                               each vApp VM.
-        :type       ex_vm_cpu: ``int``
-
-        :keyword    ex_vm_memory: amount of memory in MB to allocate for each
-                                  vApp VM.
-        :type       ex_vm_memory: ``int``
-
-        :keyword    ex_vm_script: full path to file containing guest
-                                  customisation script for each vApp VM.
-                                  Useful for creating users & pushing out
-                                  public SSH keys etc.
-        :type       ex_vm_script: ``str``
-
-        :keyword    ex_vm_network: Override default vApp VM network name.
-                                   Useful for when you've imported an OVF
-                                   originating from outside of the vCloud.
-        :type       ex_vm_network: ``str``
-
-        :keyword    ex_vm_fence: Fence mode for connecting the vApp VM network
-                                 (ex_vm_network) to the parent
-                                 organisation network (ex_network).
-        :type       ex_vm_fence: ``str``
-
-        :keyword    ex_vm_ipmode: IP address allocation mode for all vApp VM
-                                  network connections.
-        :type       ex_vm_ipmode: ``str``
-
-        :keyword    ex_deploy: set to False if the node shouldn't be deployed
-                               (started) after creation
-        :type       ex_deploy: ``bool``
-
-        :keyword    ex_clone_timeout: timeout in seconds for clone/instantiate
-                                      VM operation.
-                                      Cloning might be a time consuming
-                                      operation especially when linked clones
-                                      are disabled or VMs are created on
-                                      different datastores.
-                                      Overrides the default task completion
-                                      value.
-        :type       ex_clone_timeout: ``int``
-        """
-        name = kwargs['name']
-        image = kwargs['image']
-        ex_vm_names = kwargs.get('ex_vm_names')
-        ex_vm_cpu = kwargs.get('ex_vm_cpu')
-        ex_vm_memory = kwargs.get('ex_vm_memory')
-        ex_vm_script = kwargs.get('ex_vm_script')
-        ex_vm_fence = kwargs.get('ex_vm_fence', None)
-        ex_network = kwargs.get('ex_network', None)
-        ex_vm_network = kwargs.get('ex_vm_network', None)
-        ex_vm_ipmode = kwargs.get('ex_vm_ipmode', None)
-        ex_deploy = kwargs.get('ex_deploy', True)
-        ex_vdc = kwargs.get('ex_vdc', None)
-        ex_clone_timeout = kwargs.get('ex_clone_timeout',
-                                      DEFAULT_TASK_COMPLETION_TIMEOUT)
-
-        self._validate_vm_names(ex_vm_names)
-        self._validate_vm_cpu(ex_vm_cpu)
-        self._validate_vm_memory(ex_vm_memory)
-        self._validate_vm_fence(ex_vm_fence)
-        self._validate_vm_ipmode(ex_vm_ipmode)
-        ex_vm_script = self._validate_vm_script(ex_vm_script)
-
-        # Some providers don't require a network link
-        if ex_network:
-            network_href = self._get_network_href(ex_network)
-            network_elem = self.connection.request(
-                get_url_path(network_href)).object
-        else:
-            network_elem = None
-
-        vdc = self._get_vdc(ex_vdc)
-
-        if self._is_node(image):
-            vapp_name, vapp_href = self._clone_node(name,
-                                                    image,
-                                                    vdc,
-                                                    ex_clone_timeout)
-        else:
-            vapp_name, vapp_href = self._instantiate_node(name, image,
-                                                          network_elem,
-                                                          vdc, ex_vm_network,
-                                                          ex_vm_fence,
-                                                          ex_clone_timeout)
-
-        self._change_vm_names(vapp_href, ex_vm_names)
-        self._change_vm_cpu(vapp_href, ex_vm_cpu)
-        self._change_vm_memory(vapp_href, ex_vm_memory)
-        self._change_vm_script(vapp_href, ex_vm_script)
-        self._change_vm_ipmode(vapp_href, ex_vm_ipmode)
-
-        # Power on the VM.
-        if ex_deploy:
-            # Retry 3 times: when instantiating large number of VMs at the same
-            # time some may fail on resource allocation
-            retry = 3
-            while True:
-                try:
-                    res = self.connection.request(
-                        '%s/power/action/powerOn' % get_url_path(vapp_href),
-                        method='POST')
-                    self._wait_for_task_completion(res.object.get('href'))
-                    break
-                except Exception:
-                    if retry <= 0:
-                        raise
-                    retry -= 1
-                    time.sleep(10)
-
-        res = self.connection.request(get_url_path(vapp_href))
-        node = self._to_node(res.object)
-        return node
-
-    def _instantiate_node(self, name, image, network_elem, vdc, vm_network,
-                          vm_fence, instantiate_timeout):
-        instantiate_xml = Instantiate_1_5_VAppXML(
-            name=name,
-            template=image.id,
-            network=network_elem,
-            vm_network=vm_network,
-            vm_fence=vm_fence
-        )
-
-        # Instantiate VM and get identifier.
-        headers = {
-            'Content-Type':
-            'application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml'
-        }
-        res = self.connection.request(
-            '%s/action/instantiateVAppTemplate' % get_url_path(vdc.id),
-            data=instantiate_xml.tostring(),
-            method='POST',
-            headers=headers
-        )
-        vapp_name = res.object.get('name')
-        vapp_href = res.object.get('href')
-
-        task_href = res.object.find(fixxpath(res.object, "Tasks/Task")).get(
-            'href')
-        self._wait_for_task_completion(task_href, instantiate_timeout)
-        return vapp_name, vapp_href
-
-    def _clone_node(self, name, sourceNode, vdc, clone_timeout):
-        clone_xml = ET.Element(
-            "CloneVAppParams",
-            {'name': name, 'deploy': 'false', 'powerOn': 'false',
-             'xmlns': "http://www.vmware.com/vcloud/v1.5",
-             'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"}
-        )
-        ET.SubElement(clone_xml,
-                      'Description').text = 'Clone of ' + sourceNode.name
-        ET.SubElement(clone_xml, 'Source', {'href': sourceNode.id})
-
-        headers = {
-            'Content-Type': 'application/vnd.vmware.vcloud.cloneVAppParams+xml'
-        }
-        res = self.connection.request(
-            '%s/action/cloneVApp' % get_url_path(vdc.id),
-            data=ET.tostring(clone_xml),
-            method='POST',
-            headers=headers
-        )
-        vapp_name = res.object.get('name')
-        vapp_href = res.object.get('href')
-
-        task_href = res.object.find(
-            fixxpath(res.object, "Tasks/Task")).get('href')
-        self._wait_for_task_completion(task_href, clone_timeout)
-
-        res = self.connection.request(get_url_path(vapp_href))
-
-        vms = res.object.findall(fixxpath(res.object, "Children/Vm"))
-
-        # Fix the networking for VMs
-        for i, vm in enumerate(vms):
-            # Remove network
-            network_xml = ET.Element("NetworkConnectionSection", {
-                'ovf:required': 'false',
-                'xmlns': "http://www.vmware.com/vcloud/v1.5",
-                'xmlns:ovf': 'http://schemas.dmtf.org/ovf/envelope/1'})
-            ET.SubElement(network_xml, "ovf:Info").text = \
-                'Specifies the available VM network connections'
-
-            headers = {
-                'Content-Type':
-                'application/vnd.vmware.vcloud.networkConnectionSection+xml'
-            }
-            res = self.connection.request(
-                '%s/networkConnectionSection' % get_url_path(vm.get('href')),
-                data=ET.tostring(network_xml),
-                method='PUT',
-                headers=headers
-            )
-            self._wait_for_task_completion(res.object.get('href'))
-
-            # Re-add network
-            network_xml = vm.find(fixxpath(vm, 'NetworkConnectionSection'))
-            network_conn_xml = network_xml.find(
-                fixxpath(network_xml, 'NetworkConnection'))
-            network_conn_xml.set('needsCustomization', 'true')
-            network_conn_xml.remove(
-                network_conn_xml.find(fixxpath(network_xml, 'IpAddress')))
-            network_conn_xml.remove(
-                network_conn_xml.find(fixxpath(network_xml, 'MACAddress')))
-
-            headers = {
-                'Content-Type':
-                'application/vnd.vmware.vcloud.networkConnectionSection+xml'
-            }
-            res = self.connection.request(
-                '%s/networkConnectionSection' % get_url_path(vm.get('href')),
-                data=ET.tostring(network_xml),
-                method='PUT',
-                headers=headers
-            )
-            self._wait_for_task_completion(res.object.get('href'))
-
-        return vapp_name, vapp_href
-
-    def ex_set_vm_cpu(self, vapp_or_vm_id, vm_cpu):
-        """
-        Sets the number of virtual CPUs for the specified VM or VMs under
-        the vApp. If the vapp_or_vm_id param represents a link to an vApp
-        all VMs that are attached to this vApp will be modified.
-
-        Please ensure that hot-adding a virtual CPU is enabled for the
-        powered on virtual machines. Otherwise use this method on undeployed
-        vApp.
-
-        :keyword    vapp_or_vm_id: vApp or VM ID that will be modified. If
-                                   a vApp ID is used here all attached VMs
-                                   will be modified
-        :type       vapp_or_vm_id: ``str``
-
-        :keyword    vm_cpu: number of virtual CPUs/cores to allocate for
-                            specified VMs
-        :type       vm_cpu: ``int``
-
-        :rtype: ``None``
-        """
-        self._validate_vm_cpu(vm_cpu)
-        self._change_vm_cpu(vapp_or_vm_id, vm_cpu)
-
-    def ex_set_vm_memory(self, vapp_or_vm_id, vm_memory):
-        """
-        Sets the virtual memory in MB to allocate for the specified VM or
-        VMs under the vApp. If the vapp_or_vm_id param represents a link
-        to an vApp all VMs that are attached to this vApp will be modified.
-
-        Please ensure that hot-change of virtual memory is enabled for the
-        powered on virtual machines. Otherwise use this method on undeployed
-        vApp.
-
-        :keyword    vapp_or_vm_id: vApp or VM ID that will be modified. If
-                                   a vApp ID is used here all attached VMs
-                                   will be modified
-        :type       vapp_or_vm_id: ``str``
-
-        :keyword    vm_memory: virtual memory in MB to allocate for the
-                               specified VM or VMs
-        :type       vm_memory: ``int``
-
-        :rtype: ``None``
-        """
-        self._validate_vm_memory(vm_memory)
-        self._change_vm_memory(vapp_or_vm_id, vm_memory)
-
-    def ex_add_vm_disk(self, vapp_or_vm_id, vm_disk_size):
-        """
-        Adds a virtual disk to the specified VM or VMs under the vApp. If the
-        vapp_or_vm_id param represents a link to an vApp all VMs that are
-        attached to this vApp will be modified.
-
-        :keyword    vapp_or_vm_id: vApp or VM ID that will be modified. If a
-                                   vApp ID is used here all attached VMs
-                                   will be modified
-        :type       vapp_or_vm_id: ``str``
-
-        :keyword    vm_disk_size: the disk capacity in GB that will be added
-                                  to the specified VM or VMs
-        :type       vm_disk_size: ``int``
-
-        :rtype: ``None``
-        """
-        self._validate_vm_disk_size(vm_disk_size)
-        self._add_vm_disk(vapp_or_vm_id, vm_disk_size)
-
-    @staticmethod
-    def _validate_vm_names(names):
-        if names is None:
-            return
-        hname_re = re.compile(
-            '^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9]*)[\-])*([A-Za-z]|[A-Za-z][A-Za-z0-9]*[A-Za-z0-9])$')  # NOQA
-        for name in names:
-            if len(name) > 15:
-                raise ValueError(
-                    'The VM name "' + name + '" is too long for the computer '
-                    'name (max 15 chars allowed).')
-            if not hname_re.match(name):
-                raise ValueError('The VM name "' + name + '" can not be '
-                                 'used. "' + name + '" is not a valid '
-                                 'computer name for the VM.')
-
-    @staticmethod
-    def _validate_vm_memory(vm_memory):
-        if vm_memory is None:
-            return
-        elif vm_memory not in VIRTUAL_MEMORY_VALS:
-            raise ValueError(
-                '%s is not a valid vApp VM memory value' % vm_memory)
-
-    @staticmethod
-    def _validate_vm_cpu(vm_cpu):
-        if vm_cpu is None:
-            return
-        elif vm_cpu not in VIRTUAL_CPU_VALS_1_5:
-            raise ValueError('%s is not a valid vApp VM CPU value' % vm_cpu)
-
-    @staticmethod
-    def _validate_vm_disk_size(vm_disk):
-        if vm_disk is None:
-            return
-        elif int(vm_disk) < 0:
-            raise ValueError('%s is not a valid vApp VM disk space value',
-                             vm_disk)
-
-    @staticmethod
-    def _validate_vm_script(vm_script):
-        if vm_script is None:
-            return
-        # Try to locate the script file
-        if not os.path.isabs(vm_script):
-            vm_script = os.path.expanduser(vm_script)
-            vm_script = os.path.abspath(vm_script)
-        if not os.path.isfile(vm_script):
-            raise LibcloudError(
-                "%s the VM script file does not exist" % vm_script)
-        try:
-            open(vm_script).read()
-        except:
-            raise
-        return vm_script
-
-    @staticmethod
-    def _validate_vm_fence(vm_fence):
-        if vm_fence is None:
-            return
-        elif vm_fence not in FENCE_MODE_VALS_1_5:
-            raise ValueError('%s is not a valid fencing mode value' % vm_fence)
-
-    @staticmethod
-    def _validate_vm_ipmode(vm_ipmode):
-        if vm_ipmode is None:
-            return
-        elif vm_ipmode == 'MANUAL':
-            raise NotImplementedError(
-                'MANUAL IP mode: The interface for supplying '
-                'IPAddress does not exist yet')
-        elif vm_ipmode not in IP_MODE_VALS_1_5:
-            raise ValueError(
-                '%s is not a valid IP address allocation mode value'
-                % vm_ipmode)
-
-    def _change_vm_names(self, vapp_or_vm_id, vm_names):
-        if vm_names is None:
-            return
-
-        vms = self._get_vm_elements(vapp_or_vm_id)
-        for i, vm in enumerate(vms):
-            if len(vm_names) <= i:
-                return
-
-            # Get GuestCustomizationSection
-            res = self.connection.request(
-                '%s/guestCustomizationSection' % get_url_path(vm.get('href')))
-
-            # Update GuestCustomizationSection
-            res.object.find(
-                fixxpath(res.object, 'ComputerName')).text = vm_names[i]
-            # Remove AdminPassword from customization section
-            admin_pass = res.object.find(fixxpath(res.object, 'AdminPassword'))
-            if admin_pass is not None:
-                res.object.remove(admin_pass)
-
-            headers = {
-                'Content-Type':
-                'application/vnd.vmware.vcloud.guestCustomizationSection+xml'
-            }
-            res = self.connection.request(
-                '%s/guestCustomizationSection' % get_url_path(vm.get('href')),
-                data=ET.tostring(res.object),
-                method='PUT',
-                headers=headers
-            )
-            self._wait_for_task_completion(res.object.get('href'))
-
-            # Update Vm name
-            req_xml = ET.Element("Vm", {
-                'name': vm_names[i],
-                'xmlns': "http://www.vmware.com/vcloud/v1.5"})
-            res = self.connection.request(
-                get_url_path(vm.get('href')),
-                data=ET.tostring(req_xml),
-                method='PUT',
-                headers={
-                    'Content-Type': 'application/vnd.vmware.vcloud.vm+xml'}
-            )
-            self._wait_for_task_completion(res.object.get('href'))
-
-    def _change_vm_cpu(self, vapp_or_vm_id, vm_cpu):
-        if vm_cpu is None:
-            return
-
-        vms = self._get_vm_elements(vapp_or_vm_id)
-        for vm in vms:
-            # Get virtualHardwareSection/cpu section
-            res = self.connection.request(
-                '%s/virtualHardwareSection/cpu' % get_url_path(vm.get('href')))
-
-            # Update VirtualQuantity field
-            xpath = ('{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/'
-                     'CIM_ResourceAllocationSettingData}VirtualQuantity')
-            res.object.find(xpath).text = str(vm_cpu)
-
-            headers = {
-                'Content-Type': 'application/vnd.vmware.vcloud.rasdItem+xml'
-            }
-            res = self.connection.request(
-                '%s/virtualHardwareSection/cpu' % get_url_path(vm.get('href')),
-                data=ET.tostring(res.object),
-                method='PUT',
-                headers=headers
-            )
-            self._wait_for_task_completion(res.object.get('href'))
-
-    def _change_vm_memory(self, vapp_or_vm_id, vm_memory):
-        if vm_memory is None:
-            return
-
-        vms = self._get_vm_elements(vapp_or_vm_id)
-        for vm in vms:
-            # Get virtualHardwareSection/memory section
-            res = self.connection.request(
-                '%s/virtualHardwareSection/memory' %
-                get_url_path(vm.get('href')))
-
-            # Update VirtualQuantity field
-            xpath = ('{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/'
-                     'CIM_ResourceAllocationSettingData}VirtualQuantity')
-            res.object.find(xpath).text = str(vm_memory)
-
-            headers = {
-                'Content-Type': 'application/vnd.vmware.vcloud.rasdItem+xml'
-            }
-            res = self.connection.request(
-                '%s/virtualHardwareSection/memory' % get_url_path(
-                    vm.get('href')),
-                data=ET.tostring(res.object),
-                method='PUT',
-                headers=headers
-            )
-            self._wait_for_task_completion(res.object.get('href'))
-
-    def _add_vm_disk(self, vapp_or_vm_id, vm_disk):
-        if vm_disk is None:
-            return
-
-        rasd_ns = ('{http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/'
-                   'CIM_ResourceAllocationSettingData}')
-
-        vms = self._get_vm_elements(vapp_or_vm_id)
-        for vm in vms:
-            # Get virtualHardwareSection/disks section
-            res = self.connection.request(
-                '%s/virtualHardwareSection/disks' %
-                get_url_path(vm.get('href')))
-
-            existing_ids = []
-            new_disk = None
-            for item in res.object.findall(fixxpath(res.object, 'Item')):
-                # Clean Items from unnecessary stuff
-                for elem in item:
-                    if elem.tag == '%sInstanceID' % rasd_ns:
-                        existing_ids.append(int(elem.text))
-                    if elem.tag in ['%sAddressOnParent' % rasd_ns,
-                                    '%sParent' % rasd_ns]:
-                        item.remove(elem)
-                if item.find('%sHostResource' % rasd_ns) is not None:
-                    new_disk = item
-
-            new_disk = copy.deepcopy(new_disk)
-            disk_id = max(existing_ids) + 1
-            new_disk.find('%sInstanceID' % rasd_ns).text = str(disk_id)
-            new_disk.find('%sElementName' %
-                          rasd_ns).text = 'Hard Disk ' + str(disk_id)
-            new_disk.find('%sHostResource' % rasd_ns).set(
-                fixxpath(new_disk, 'capacity'), str(int(vm_disk) * 1024))
-            res.object.append(new_disk)
-
-            headers = {
-                'Content-Type':
-                'application/vnd.vmware.vcloud.rasditemslist+xml'
-            }
-            res = self.connection.request(
-                '%s/virtualHardwareSection/disks' % get_url_path(
-                    vm.get('href')),
-                data=ET.tostring(res.object),
-                method='PUT',
-                headers=headers
-            )
-            self._wait_for_task_completion(res.object.get('href'))
-
-    def _change_vm_script(self, vapp_or_vm_id, vm_script):
-        if vm_script is None:
-            return
-
-        vms = self._get_vm_elements(vapp_or_vm_id)
-        try:
-            script = open(vm_script).read()
-        except:
-            return
-
-        # ElementTree escapes script characters automatically. Escape
-        # requirements:
-        # http://www.vmware.com/support/vcd/doc/rest-api-doc-1.5-html/types/
-        # GuestCustomizationSectionType.html
-        for vm in vms:
-            # Get GuestCustomizationSection
-            res = self.connection.request(
-                '%s/guestCustomizationSection' % get_url_path(vm.get('href')))
-
-            # Attempt to update any existing CustomizationScript element
-            try:
-                res.object.find(
-                    fixxpath(res.object, 'CustomizationScript')).text = script
-            except:
-                # CustomizationScript section does not exist, insert it just
-                # before ComputerName
-                for i, e in enumerate(res.object):
-                    if e.tag == \
-                            '{http://www.vmware.com/vcloud/v1.5}ComputerName':
-                        break
-                e = ET.Element(
-                    '{http://www.vmware.com/vcloud/v1.5}CustomizationScript')
-                e.text = script
-                res.object.insert(i, e)
-
-            # Remove AdminPassword from customization section due to an API
-            # quirk
-            admin_pass = res.object.find(fixxpath(res.object, 'AdminPassword'))
-            if admin_pass is not None:
-                res.object.remove(admin_pass)
-
-            # Update VM's GuestCustomizationSection
-            headers = {
-                'Content-Type':
-                'application/vnd.vmware.vcloud.guestCustomizationSection+xml'
-            }
-            res = self.connection.request(
-                '%s/guestCustomizationSection' % get_url_path(vm.get('href')),
-                data=ET.tostring(res.object),
-                method='PUT',
-                headers=headers
-            )
-            self._wait_for_task_completion(res.object.get('href'))
-
-    def _change_vm_ipmode(self, vapp_or_vm_id, vm_ipmode):
-        if vm_ipmode is None:
-            return
-
-        vms = self._get_vm_elements(vapp_or_vm_id)
-
-        for vm in vms:
-            res = self.connection.request(
-                '%s/networkConnectionSection' % get_url_path(vm.get('href')))
-            net_conns = res.object.findall(
-                fixxpath(res.object, 'NetworkConnection'))
-            for c in net_conns:
-                c.find(fixxpath(c, 'IpAddressAllocationMode')).text = vm_ipmode
-
-            headers = {
-                'Content-Type':
-                'application/vnd.vmware.vcloud.networkConnectionSection+xml'
-            }
-
-            res = self.connection.request(
-                '%s/networkConnectionSection' % get_url_path(vm.get('href')),
-                data=ET.tostring(res.object),
-                method='PUT',
-                headers=headers
-            )
-            self._wait_for_task_completion(res.object.get('href'))
-
-    def _get_network_href(self, network_name):
-        network_href = None
-
-        # Find the organisation's network href
-        res = self.connection.request(self.org)
-        links = res.object.findall(fixxpath(res.object, 'Link'))
-        for l in links:
-            if l.attrib['type'] == \
-                    'application/vnd.vmware.vcloud.orgNetwork+xml' \
-                    and l.attrib['name'] == network_name:
-                network_href = l.attrib['href']
-
-        if network_href is None:
-            raise ValueError(
-                '%s is not a valid organisation network name' % network_name)
-        else:
-            return network_href
-
-    def _get_vm_elements(self, vapp_or_vm_id):
-        res = self.connection.request(get_url_path(vapp_or_vm_id))
-        if res.object.tag.endswith('VApp'):
-            vms = res.object.findall(fixxpath(res.object, 'Children/Vm'))
-        elif res.object.tag.endswith('Vm'):
-            vms = [res.object]
-        else:
-            raise ValueError(
-                'Specified ID value is not a valid VApp or Vm identifier.')
-        return vms
-
-    def _is_node(self, node_or_image):
-        return isinstance(node_or_image, Node)
-
-    def _to_node(self, node_elm):
-        # Parse snapshots and VMs as extra
-        if node_elm.find(fixxpath(node_elm, "SnapshotSection")) is None:
-            snapshots = None
-        else:
-            snapshots = []
-            for snapshot_elem in node_elm.findall(
-                    fixxpath(node_elm, 'SnapshotSection/Snapshot')):
-                snapshots.append({
-                    "created": snapshot_elem.get("created"),
-                    "poweredOn": snapshot_elem.get("poweredOn"),
-                    "size": snapshot_elem.get("size"),
-                })
-
-        vms = []
-        for vm_elem in node_elm.findall(fixxpath(node_elm, 'Children/Vm')):
-            public_ips = []
-            private_ips = []
-
-            xpath = fixxpath(vm_elem,
-                             'NetworkConnectionSection/NetworkConnection')
-            for connection in vm_elem.findall(xpath):
-                ip = connection.find(fixxpath(connection, "IpAddress"))
-                if ip is not None:
-                    private_ips.append(ip.text)
-                external_ip = connection.find(
-                    fixxpath(connection, "ExternalIpAddress"))
-                if external_ip is not None:
-                    public_ips.append(external_ip.text)
-                elif ip is not None:
-                    public_ips.append(ip.text)
-
-            xpath = ('{http://schemas.dmtf.org/ovf/envelope/1}'
-                     'OperatingSystemSection')
-            os_type_elem = vm_elem.find(xpath)
-            if os_type_elem is not None:
-                os_type = os_type_elem.get(
-                    '{http://www.vmware.com/schema/ovf}osType')
-            else:
-                os_type = None
-            vm = {
-                'id': vm_elem.get('href'),
-                'name': vm_elem.get('name'),
-                'state': self.NODE_STATE_MAP[vm_elem.get('status')],
-                'public_ips': public_ips,
-                'private_ips': private_ips,
-                'os_type': os_type
-            }
-            vms.append(vm)
-
-        # Take the node IP addresses from all VMs
-        public_ips = []
-        private_ips = []
-        for vm in vms:
-            public_ips.extend(vm['public_ips'])
-            private_ips.extend(vm['private_ips'])
-
-        # Find vDC
-        vdc_id = next(link.get('href') for link
-                      in node_elm.findall(fixxpath(node_elm, 'Link'))
-                      if link.get('type') ==
-                      'application/vnd.vmware.vcloud.vdc+xml')
-        vdc = next(vdc for vdc in self.vdcs if vdc.id == vdc_id)
-
-        extra = {'vdc': vdc.name, 'vms': vms}
-        if snapshots is not None:
-            extra['snapshots'] = snapshots
-
-        node = Node(id=node_elm.get('href'),
-                    name=node_elm.get('name'),
-                    state=self.NODE_STATE_MAP[node_elm.get('status')],
-                    public_ips=public_ips,
-                    private_ips=private_ips,
-                    driver=self.connection.driver,
-                    extra=extra)
-        return node
-
-    def _to_vdc(self, vdc_elm):
-
-        def get_capacity_values(capacity_elm):
-            if capacity_elm is None:
-                return None
-            limit = int(capacity_elm.findtext(fixxpath(capacity_elm, 'Limit')))
-            used = int(capacity_elm.findtext(fixxpath(capacity_elm, 'Used')))
-            units = capacity_elm.findtext(fixxpath(capacity_elm, 'Units'))
-            return Capacity(limit, used, units)
-
-        cpu = get_capacity_values(
-            vdc_elm.find(fixxpath(vdc_elm, 'ComputeCapacity/Cpu')))
-        memory = get_capacity_values(
-            vdc_elm.find(fixxpath(vdc_elm, 'ComputeCapacity/Memory')))
-        storage = get_capacity_values(
-            vdc_elm.find(fixxpath(vdc_elm, 'StorageCapacity')))
-
-        return Vdc(id=vdc_elm.get('href'),
-                   name=vdc_elm.get('name'),
-                   driver=self,
-                   allocation_model=vdc_elm.findtext(
-                       fixxpath(vdc_elm, 'AllocationModel')),
-                   cpu=cpu,
-                   memory=memory,
-                   storage=storage)
-
-
-class VCloud_5_1_NodeDriver(VCloud_1_5_NodeDriver):
-
-    @staticmethod
-    def _validate_vm_memory(vm_memory):
-        if vm_memory is None:
-            return None
-        elif (vm_memory % 4) != 0:
-            # The vcd 5.1 virtual machine memory size must be a multiple of 4
-            # MB
-            raise ValueError(
-                '%s is not a valid vApp VM memory value' % (vm_memory))
-
-
-class VCloud_5_5_NodeDriver(VCloud_5_1_NodeDriver):
-    '''Use 5.5 Connection class to explicitly set 5.5 for the version in
-    Accept headers
-    '''
-    connectionCls = VCloud_5_5_Connection
-
-    def ex_create_snapshot(self, node):
-        """
-        Creates new snapshot of a virtual machine or of all
-        the virtual machines in a vApp. Prior to creation of the new
-        snapshots, any existing user created snapshots associated
-        with the virtual machines are removed.
-
-        :param  node: node
-        :type   node: :class:`Node`
-
-        :rtype: :class:`Node`
-        """
-        snapshot_xml = ET.Element(
-            "CreateSnapshotParams",
-            {'memory': 'true',
-             'name': 'name',
-             'quiesce': 'true',
-             'xmlns': "http://www.vmware.com/vcloud/v1.5",
-             'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"}
-        )
-        ET.SubElement(snapshot_xml, 'Description').text = 'Description'
-        content_type = 'application/vnd.vmware.vcloud.createSnapshotParams+xml'
-        headers = {
-            'Content-Type': content_type
-        }
-        return self._perform_snapshot_operation(node,
-                                                "createSnapshot",
-                                                snapshot_xml,
-                                                headers)
-
-    def ex_remove_snapshots(self, node):
-        """
-        Removes all user created snapshots for a vApp or virtual machine.
-
-        :param  node: node
-        :type   node: :class:`Node`
-
-        :rtype: :class:`Node`
-        """
-        return self._perform_snapshot_operation(node,
-                                                "removeAllSnapshots",
-                                                None,
-                                                None)
-
-    def ex_revert_to_snapshot(self, node):
-        """
-        Reverts a vApp or virtual machine to the current snapshot, if any.
-
-        :param  node: node
-        :type   node: :class:`Node`
-
-        :rtype: :class:`Node`
-        """
-        return self._perform_snapshot_operation(node,
-                                                "revertToCurrentSnapshot",
-                                                None,
-                                                None)
-
-    def _perform_snapshot_operation(self, node, operation, xml_data, headers):
-        res = self.connection.request(
-            '%s/action/%s' % (get_url_path(node.id), operation),
-            data=ET.tostring(xml_data) if xml_data else None,
-            method='POST',
-            headers=headers)
-        self._wait_for_task_completion(res.object.get('href'))
-        res = self.connection.request(get_url_path(node.id))
-        return self._to_node(res.object)
-
-    def ex_acquire_mks_ticket(self, vapp_or_vm_id, vm_num=0):
-        """
-        Retrieve a mks ticket that you can use to gain access to the console
-        of a running VM. If successful, returns a dict with the following
-        keys:
-
-          - host: host (or proxy) through which the console connection
-                is made
-          - vmx: a reference to the VMX file of the VM for which this
-               ticket was issued
-          - ticket: screen ticket to use to authenticate the client
-          - port: host port to be used for console access
-
-        :param  vapp_or_vm_id: vApp or VM ID you want to connect to.
-        :type   vapp_or_vm_id: ``str``
-
-        :param  vm_num: If a vApp ID is provided, vm_num is position in the
-                vApp VM list of the VM you want to get a screen ticket.
-                Default is 0.
-        :type   vm_num: ``int``
-
-        :rtype: ``dict``
-        """
-        vm = self._get_vm_elements(vapp_or_vm_id)[vm_num]
-        try:
-            res = self.connection.request('%s/screen/action/acquireMksTicket' %
-                                          (get_url_path(vm.get('href'))),
-                                          method='POST')
-            output = {
-                "host": res.object.find(fixxpath(res.object, 'Host')).text,
-                "vmx": res.object.find(fixxpath(res.object, 'Vmx')).text,
-                "ticket": res.object.find(fixxpath(res.object, 'Ticket')).text,
-                "port": res.object.find(fixxpath(res.object, 'Port')).text,
-            }
-            return output
-        except:
-            return None