libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anthonys...@apache.org
Subject [20/56] [abbrv] libcloud git commit: Removed sdist
Date Mon, 14 Nov 2016 23:51:07 GMT
http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/packet.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/packet.py b/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/packet.py
deleted file mode 100644
index 2560145..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/packet.py
+++ /dev/null
@@ -1,258 +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.
-"""
-Packet Driver
-"""
-
-from libcloud.utils.py3 import httplib
-
-from libcloud.common.base import ConnectionKey, JsonResponse
-from libcloud.compute.types import Provider, NodeState, InvalidCredsError
-from libcloud.compute.base import NodeDriver, Node
-from libcloud.compute.base import NodeImage, NodeSize, NodeLocation
-from libcloud.compute.base import KeyPair
-
-PACKET_ENDPOINT = "api.packet.net"
-
-
-class PacketResponse(JsonResponse):
-    valid_response_codes = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
-                            httplib.NO_CONTENT]
-
-    def parse_error(self):
-        if self.status == httplib.UNAUTHORIZED:
-            body = self.parse_body()
-            raise InvalidCredsError(body['message'])
-        else:
-            body = self.parse_body()
-            if 'message' in body:
-                error = '%s (code: %s)' % (body['message'], self.status)
-            else:
-                error = body
-            return error
-
-    def success(self):
-        return self.status in self.valid_response_codes
-
-
-class PacketConnection(ConnectionKey):
-    """
-    Connection class for the Packet driver.
-    """
-
-    host = PACKET_ENDPOINT
-    responseCls = PacketResponse
-
-    def add_default_headers(self, headers):
-        """
-        Add headers that are necessary for every request
-        """
-        headers['Content-Type'] = 'application/json'
-        headers['X-Auth-Token'] = self.key
-        headers['X-Consumer-Token'] = \
-            'kcrhMn7hwG8Ceo2hAhGFa2qpxLBvVHxEjS9ue8iqmsNkeeB2iQgMq4dNc1893pYu'
-        return headers
-
-
-class PacketNodeDriver(NodeDriver):
-    """
-    Packet NodeDriver
-    """
-
-    connectionCls = PacketConnection
-    type = Provider.PACKET
-    name = 'Packet'
-    website = 'http://www.packet.net/'
-
-    NODE_STATE_MAP = {'queued': NodeState.PENDING,
-                      'provisioning': NodeState.PENDING,
-                      'rebuilding': NodeState.PENDING,
-                      'powering_on': NodeState.REBOOTING,
-                      'powering_off': NodeState.REBOOTING,
-                      'rebooting': NodeState.REBOOTING,
-                      'inactive': NodeState.STOPPED,
-                      'deleted': NodeState.TERMINATED,
-                      'deprovisioning': NodeState.TERMINATED,
-                      'failed': NodeState.ERROR,
-                      'active': NodeState.RUNNING}
-
-    def list_nodes(self, ex_project_id):
-        data = self.connection.request('/projects/%s/devices' %
-                                       (ex_project_id),
-                                       params={'include': 'plan'}
-                                       ).object['devices']
-        return list(map(self._to_node, data))
-
-    def list_locations(self):
-        data = self.connection.request('/facilities')\
-            .object['facilities']
-        return list(map(self._to_location, data))
-
-    def list_images(self):
-        data = self.connection.request('/operating-systems')\
-            .object['operating_systems']
-        return list(map(self._to_image, data))
-
-    def list_sizes(self):
-        data = self.connection.request('/plans').object['plans']
-        return list(map(self._to_size, data))
-
-    def create_node(self, name, size, image, location, ex_project_id):
-        """
-        Create a node.
-
-        :return: The newly created node.
-        :rtype: :class:`Node`
-        """
-
-        params = {'hostname': name, 'plan': size.id,
-                  'operating_system': image.id, 'facility': location.id,
-                  'include': 'plan', 'billing_cycle': 'hourly'}
-
-        data = self.connection.request('/projects/%s/devices' %
-                                       (ex_project_id),
-                                       params=params, method='POST')
-
-        status = data.object.get('status', 'OK')
-        if status == 'ERROR':
-            message = data.object.get('message', None)
-            error_message = data.object.get('error_message', message)
-            raise ValueError('Failed to create node: %s' % (error_message))
-        return self._to_node(data=data.object)
-
-    def reboot_node(self, node):
-        params = {'type': 'reboot'}
-        res = self.connection.request('/devices/%s/actions' % (node.id),
-                                      params=params, method='POST')
-        return res.status == httplib.OK
-
-    def destroy_node(self, node):
-        res = self.connection.request('/devices/%s' % (node.id),
-                                      method='DELETE')
-        return res.status == httplib.OK
-
-    def list_key_pairs(self):
-        """
-        List all the available SSH keys.
-
-        :return: Available SSH keys.
-        :rtype: ``list`` of :class:`.KeyPair` objects
-        """
-        data = self.connection.request('/ssh-keys').object['ssh_keys']
-        return list(map(self._to_key_pairs, data))
-
-    def create_key_pair(self, name, public_key):
-        """
-        Create a new SSH key.
-
-        :param      name: Key name (required)
-        :type       name: ``str``
-
-        :param      public_key: Valid public key string (required)
-        :type       public_key: ``str``
-        """
-        params = {'label': name, 'key': public_key}
-        data = self.connection.request('/ssh-keys', method='POST',
-                                       params=params).object
-        return self._to_key_pairs(data)
-
-    def delete_key_pair(self, key):
-        """
-        Delete an existing SSH key.
-
-        :param      key: SSH key (required)
-        :type       key: :class:`KeyPair`
-        """
-        key_id = key.name
-        res = self.connection.request('/ssh-keys/%s' % (key_id),
-                                      method='DELETE')
-        return res.status == httplib.NO_CONTENT
-
-    def _to_node(self, data):
-        extra_keys = ['created_at', 'updated_at',
-                      'userdata', 'billing_cycle', 'locked']
-        if 'state' in data:
-            state = self.NODE_STATE_MAP.get(data['state'], NodeState.UNKNOWN)
-        else:
-            state = NodeState.UNKNOWN
-
-        if 'ip_addresses' in data and data['ip_addresses'] is not None:
-            ips = self._parse_ips(data['ip_addresses'])
-
-        if 'operating_system' in data and data['operating_system'] is not None:
-            image = self._to_image(data['operating_system'])
-
-        if 'plan' in data and data['plan'] is not None:
-            size = self._to_size(data['plan'])
-
-        extra = {}
-        for key in extra_keys:
-            if key in data:
-                extra[key] = data[key]
-
-        node = Node(id=data['id'], name=data['hostname'], state=state,
-                    image=image, size=size,
-                    public_ips=ips['public'], private_ips=ips['private'],
-                    extra=extra, driver=self)
-        return node
-
-    def _to_image(self, data):
-        extra = {'distro': data['distro'], 'version': data['version']}
-        return NodeImage(id=data['slug'], name=data['name'], extra=extra,
-                         driver=self)
-
-    def _to_location(self, data):
-        return NodeLocation(id=data['code'], name=data['name'], country=None,
-                            driver=self)
-
-    def _to_size(self, data):
-        extra = {'description': data['description'], 'line': data['line']}
-
-        ram = data['specs']['memory']['total'].lower()
-        if 'mb' in ram:
-            ram = int(ram.replace('mb', ''))
-        elif 'gb' in ram:
-            ram = int(ram.replace('gb', '')) * 1024
-
-        disk = 0
-        for disks in data['specs']['drives']:
-            disk += disks['count'] * int(disks['size'].replace('GB', ''))
-
-        price = data['pricing']['hourly']
-
-        return NodeSize(id=data['slug'], name=data['name'], ram=ram, disk=disk,
-                        bandwidth=0, price=price, extra=extra, driver=self)
-
-    def _to_key_pairs(self, data):
-        extra = {'label': data['label'],
-                 'created_at': data['created_at'],
-                 'updated_at': data['updated_at']}
-        return KeyPair(name=data['id'],
-                       fingerprint=data['fingerprint'],
-                       public_key=data['key'],
-                       private_key=None,
-                       driver=self,
-                       extra=extra)
-
-    def _parse_ips(self, data):
-        public_ips = []
-        private_ips = []
-        for address in data:
-            if 'address' in address and address['address'] is not None:
-                if 'public' in address and address['public'] is True:
-                    public_ips.append(address['address'])
-                else:
-                    private_ips.append(address['address'])
-        return {'public': public_ips, 'private': private_ips}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/profitbricks.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/profitbricks.py b/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/profitbricks.py
deleted file mode 100644
index 697b082..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/profitbricks.py
+++ /dev/null
@@ -1,1496 +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.
-"""ProfitBricks Compute driver
-"""
-import base64
-
-import copy
-import time
-
-try:
-    from lxml import etree as ET
-except ImportError:
-    from xml.etree import ElementTree as ET
-
-from libcloud.utils.networking import is_private_subnet
-from libcloud.utils.py3 import b
-from libcloud.compute.providers import Provider
-from libcloud.common.base import ConnectionUserAndKey, XmlResponse
-from libcloud.compute.base import Node, NodeDriver, NodeLocation, NodeSize
-from libcloud.compute.base import NodeImage, StorageVolume
-from libcloud.compute.base import UuidMixin
-from libcloud.compute.types import NodeState
-from libcloud.common.types import LibcloudError, MalformedResponseError
-
-__all__ = [
-    'API_VERSION',
-    'API_HOST',
-    'ProfitBricksNodeDriver',
-    'Datacenter',
-    'ProfitBricksNetworkInterface',
-    'ProfitBricksAvailabilityZone'
-]
-
-API_HOST = 'api.profitbricks.com'
-API_VERSION = '/1.3/'
-
-
-class ProfitBricksResponse(XmlResponse):
-    """
-    ProfitBricks response parsing.
-    """
-    def parse_error(self):
-        try:
-            body = ET.XML(self.body)
-        except:
-            raise MalformedResponseError('Failed to parse XML',
-                                         body=self.body,
-                                         driver=ProfitBricksNodeDriver)
-
-        for e in body.findall('.//detail'):
-            if ET.iselement(e[0].find('httpCode')):
-                http_code = e[0].find('httpCode').text
-            else:
-                http_code = None
-            if ET.iselement(e[0].find('faultCode')):
-                fault_code = e[0].find('faultCode').text
-            else:
-                fault_code = None
-            if ET.iselement(e[0].find('message')):
-                message = e[0].find('message').text
-            else:
-                message = None
-
-        return LibcloudError('HTTP Code: %s, Fault Code: %s, Message: %s' %
-                             (http_code, fault_code, message), driver=self)
-
-
-class ProfitBricksConnection(ConnectionUserAndKey):
-    """
-    Represents a single connection to the ProfitBricks endpoint.
-    """
-    host = API_HOST
-    api_prefix = API_VERSION
-    responseCls = ProfitBricksResponse
-
-    def add_default_headers(self, headers):
-        headers['Content-Type'] = 'text/xml'
-        headers['Authorization'] = 'Basic %s' % (base64.b64encode(
-            b('%s:%s' % (self.user_id, self.key))).decode('utf-8'))
-
-        return headers
-
-    def encode_data(self, data):
-        soap_env = ET.Element('soapenv:Envelope', {
-            'xmlns:soapenv': 'http://schemas.xmlsoap.org/soap/envelope/',
-            'xmlns:ws': 'http://ws.api.profitbricks.com/'
-        })
-        ET.SubElement(soap_env, 'soapenv:Header')
-        soap_body = ET.SubElement(soap_env, 'soapenv:Body')
-        soap_req_body = ET.SubElement(soap_body, 'ws:%s' % (data['action']))
-
-        if 'request' in data.keys():
-            soap_req_body = ET.SubElement(soap_req_body, 'request')
-            for key, value in data.items():
-                if key not in ['action', 'request']:
-                    child = ET.SubElement(soap_req_body, key)
-                    child.text = value
-        else:
-            for key, value in data.items():
-                if key != 'action':
-                    child = ET.SubElement(soap_req_body, key)
-                    child.text = value
-
-        soap_post = ET.tostring(soap_env)
-
-        return soap_post
-
-    def request(self, action, params=None, data=None, headers=None,
-                method='POST', raw=False):
-        action = self.api_prefix + action
-
-        return super(ProfitBricksConnection, self).request(action=action,
-                                                           params=params,
-                                                           data=data,
-                                                           headers=headers,
-                                                           method=method,
-                                                           raw=raw)
-
-
-class Datacenter(UuidMixin):
-    """
-    Class which stores information about ProfitBricks datacenter
-    instances.
-
-    :param      id: The datacenter ID.
-    :type       id: ``str``
-
-    :param      name: The datacenter name.
-    :type       name: ``str``
-
-    :param version: Datacenter version.
-    :type version: ``str``
-
-
-    Note: This class is ProfitBricks specific.
-    """
-    def __init__(self, id, name, version, driver, extra=None):
-        self.id = str(id)
-        self.name = name
-        self.version = version
-        self.driver = driver
-        self.extra = extra or {}
-        UuidMixin.__init__(self)
-
-    def __repr__(self):
-        return ((
-            '<Datacenter: id=%s, name=%s, version=%s, driver=%s> ...>')
-            % (self.id, self.name, self.version,
-                self.driver.name))
-
-
-class ProfitBricksNetworkInterface(object):
-    """
-    Class which stores information about ProfitBricks network
-    interfaces.
-
-    :param      id: The network interface ID.
-    :type       id: ``str``
-
-    :param      name: The network interface name.
-    :type       name: ``str``
-
-    :param      state: The network interface name.
-    :type       state: ``int``
-
-    Note: This class is ProfitBricks specific.
-    """
-    def __init__(self, id, name, state, extra=None):
-        self.id = id
-        self.name = name
-        self.state = state
-        self.extra = extra or {}
-
-    def __repr__(self):
-        return (('<ProfitBricksNetworkInterface: id=%s, name=%s>')
-                % (self.id, self.name))
-
-
-class ProfitBricksAvailabilityZone(object):
-    """
-    Extension class which stores information about a ProfitBricks
-    availability zone.
-
-    Note: This class is ProfitBricks specific.
-    """
-
-    def __init__(self, name):
-        self.name = name
-
-    def __repr__(self):
-        return (('<ProfitBricksAvailabilityZone: name=%s>')
-                % (self.name))
-
-
-class ProfitBricksNodeDriver(NodeDriver):
-    """
-    Base ProfitBricks node driver.
-    """
-    connectionCls = ProfitBricksConnection
-    name = 'ProfitBricks'
-    website = 'http://www.profitbricks.com'
-    type = Provider.PROFIT_BRICKS
-
-    PROVISIONING_STATE = {
-        'INACTIVE': NodeState.PENDING,
-        'INPROCESS': NodeState.PENDING,
-        'AVAILABLE': NodeState.RUNNING,
-        'DELETED': NodeState.TERMINATED,
-    }
-
-    NODE_STATE_MAP = {
-        'NOSTATE': NodeState.UNKNOWN,
-        'RUNNING': NodeState.RUNNING,
-        'BLOCKED': NodeState.STOPPED,
-        'PAUSE': NodeState.STOPPED,
-        'SHUTDOWN': NodeState.PENDING,
-        'SHUTOFF': NodeState.STOPPED,
-        'CRASHED': NodeState.STOPPED,
-    }
-
-    REGIONS = {
-        '1': {'region': 'us/las', 'country': 'USA'},
-        '2': {'region': 'de/fra', 'country': 'DEU'},
-        '3': {'region': 'de/fkb', 'country': 'DEU'},
-    }
-
-    AVAILABILITY_ZONE = {
-        '1': {'name': 'AUTO'},
-        '2': {'name': 'ZONE_1'},
-        '3': {'name': 'ZONE_2'},
-    }
-
-    """
-    ProfitBricks is unique in that they allow the user to define all aspects
-    of the instance size, i.e. disk size, core size, and memory size.
-
-    These are instance types that match up with what other providers support.
-
-    You can configure disk size, core size, and memory size using the ``ex_``
-    parameters on the create_node method.
-    """
-
-    PROFIT_BRICKS_GENERIC_SIZES = {
-        '1': {
-            'id': '1',
-            'name': 'Micro',
-            'ram': 1024,
-            'disk': 50,
-            'cores': 1
-        },
-        '2': {
-            'id': '2',
-            'name': 'Small Instance',
-            'ram': 2048,
-            'disk': 50,
-            'cores': 1
-        },
-        '3': {
-            'id': '3',
-            'name': 'Medium Instance',
-            'ram': 4096,
-            'disk': 50,
-            'cores': 2
-        },
-        '4': {
-            'id': '4',
-            'name': 'Large Instance',
-            'ram': 7168,
-            'disk': 50,
-            'cores': 4
-        },
-        '5': {
-            'id': '5',
-            'name': 'ExtraLarge Instance',
-            'ram': 14336,
-            'disk': 50,
-            'cores': 8
-        },
-        '6': {
-            'id': '6',
-            'name': 'Memory Intensive Instance Medium',
-            'ram': 28672,
-            'disk': 50,
-            'cores': 4
-        },
-        '7': {
-            'id': '7',
-            'name': 'Memory Intensive Instance Large',
-            'ram': 57344,
-            'disk': 50,
-            'cores': 8
-        }
-    }
-
-    """
-    Core Functions
-    """
-
-    def list_sizes(self):
-        """
-        Lists all sizes
-
-        :rtype: ``list`` of :class:`NodeSize`
-        """
-        sizes = []
-
-        for key, values in self.PROFIT_BRICKS_GENERIC_SIZES.items():
-            node_size = self._to_node_size(values)
-            sizes.append(node_size)
-
-        return sizes
-
-    def list_images(self):
-        """
-        List all images.
-
-        :rtype: ``list`` of :class:`NodeImage`
-        """
-
-        action = 'getAllImages'
-        body = {'action': action}
-
-        return self._to_images(self.connection.request(action=action,
-                               data=body, method='POST').object)
-
-    def list_locations(self):
-        """
-        List all locations.
-        """
-        locations = []
-
-        for key, values in self.REGIONS.items():
-            location = self._to_location(values)
-            locations.append(location)
-
-        return locations
-
-    def list_nodes(self):
-        """
-        List all nodes.
-
-        :rtype: ``list`` of :class:`Node`
-        """
-        action = 'getAllServers'
-        body = {'action': action}
-
-        return self._to_nodes(self.connection.request(action=action,
-                              data=body, method='POST').object)
-
-    def reboot_node(self, node):
-        """
-        Reboots the node.
-
-        :rtype: ``bool``
-        """
-        action = 'resetServer'
-        body = {'action': action,
-                'serverId': node.id
-                }
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    def create_node(self, name, image, size=None, location=None,
-                    volume=None, ex_datacenter=None, ex_internet_access=True,
-                    ex_availability_zone=None, ex_ram=None, ex_cores=None,
-                    ex_disk=None, **kwargs):
-        """
-        Creates a node.
-
-        image is optional as long as you pass ram, cores, and disk
-        to the method. ProfitBricks allows you to adjust compute
-        resources at a much more granular level.
-
-        :param volume: If the volume already exists then pass this in.
-        :type volume: :class:`StorageVolume`
-
-        :param location: The location of the new data center
-            if one is not supplied.
-        :type location: : :class:`NodeLocation`
-
-        :param ex_datacenter: If you've already created the DC then pass
-                           it in.
-        :type ex_datacenter: :class:`Datacenter`
-
-        :param ex_internet_access: Configure public Internet access.
-        :type ex_internet_access: : ``bool``
-
-        :param ex_availability_zone: The availability zone.
-        :type ex_availability_zone: class: `ProfitBricksAvailabilityZone`
-
-        :param ex_ram: The amount of ram required.
-        :type ex_ram: : ``int``
-
-        :param ex_cores: The number of cores required.
-        :type ex_cores: : ``int``
-
-        :param ex_disk: The amount of disk required.
-        :type ex_disk: : ``int``
-
-        :return:    Instance of class ``Node``
-        :rtype:     :class:`Node`
-        """
-        if not ex_datacenter:
-            '''
-            We generate a name from the server name passed into the function.
-            '''
-
-            'Creating a Datacenter for the node since one was not provided.'
-            new_datacenter = self._create_new_datacenter_for_node(
-                name=name,
-                location=location
-            )
-            datacenter_id = new_datacenter.id
-
-            'Waiting for the Datacenter create operation to finish.'
-            self._wait_for_datacenter_state(datacenter=new_datacenter)
-        else:
-            datacenter_id = ex_datacenter.id
-            new_datacenter = None
-
-        if not size:
-            if not ex_ram:
-                raise ValueError('You need to either pass a '
-                                 'NodeSize or specify ex_ram as '
-                                 'an extra parameter.')
-            if not ex_cores:
-                raise ValueError('You need to either pass a '
-                                 'NodeSize or specify ex_cores as '
-                                 'an extra parameter.')
-
-        if not volume:
-            if not size:
-                if not ex_disk:
-                    raise ValueError('You need to either pass a '
-                                     'StorageVolume, a NodeSize, or specify '
-                                     'ex_disk as an extra parameter.')
-
-        '''
-        You can override the suggested sizes by passing in unique
-        values for ram, cores, and disk allowing you to size it
-        for your specific use.
-        '''
-
-        if not ex_disk:
-            ex_disk = size.disk
-
-        if not ex_ram:
-            ex_ram = size.ram
-
-        if not ex_cores:
-            ex_cores = size.extra['cores']
-
-        '''
-        A pasword is automatically generated if it is
-        not provided. This is then sent via email to
-        the admin contact on record.
-        '''
-
-        if 'auth' in kwargs:
-            auth = self._get_and_check_auth(kwargs["auth"])
-            password = auth.password
-        else:
-            password = None
-
-        '''
-        Create a StorageVolume that can be attached to the
-        server when it is created.
-        '''
-        if not volume:
-            volume = self._create_node_volume(ex_disk=ex_disk,
-                                              image=image,
-                                              password=password,
-                                              name=name,
-                                              ex_datacenter=ex_datacenter,
-                                              new_datacenter=new_datacenter)
-
-            storage_id = volume.id
-
-            'Waiting on the storage volume to be created before provisioning '
-            'the instance.'
-            self._wait_for_storage_volume_state(volume)
-        else:
-            if ex_datacenter:
-                datacenter_id = ex_datacenter.id
-            else:
-                datacenter_id = volume.extra['datacenter_id']
-
-            storage_id = volume.id
-
-        action = 'createServer'
-        body = {'action': action,
-                'request': 'true',
-                'serverName': name,
-                'cores': str(ex_cores),
-                'ram': str(ex_ram),
-                'bootFromStorageId': storage_id,
-                'internetAccess': str(ex_internet_access).lower(),
-                'dataCenterId': datacenter_id
-                }
-
-        if ex_availability_zone:
-            body['availabilityZone'] = ex_availability_zone.name
-
-        data = self.connection.request(action=action,
-                                       data=body,
-                                       method='POST').object
-        nodes = self._to_nodes(data)
-        return nodes[0]
-
-    def destroy_node(self, node, ex_remove_attached_disks=False):
-        """
-        Destroys a node.
-
-        :param node: The node you wish to destroy.
-        :type volume: :class:`Node`
-
-        :param ex_remove_attached_disks: True to destroy all attached volumes.
-        :type ex_remove_attached_disks: : ``bool``
-
-        :rtype:     : ``bool``
-        """
-        action = 'deleteServer'
-        body = {'action': action,
-                'serverId': node.id
-                }
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    """
-    Volume Functions
-    """
-
-    def list_volumes(self):
-        """
-        Lists all voumes.
-        """
-        action = 'getAllStorages'
-        body = {'action': action}
-
-        return self._to_volumes(self.connection.request(action=action,
-                                                        data=body,
-                                                        method='POST').object)
-
-    def attach_volume(self, node, volume, device=None, ex_bus_type=None):
-        """
-        Attaches a volume.
-
-        :param volume: The volume you're attaching.
-        :type volume: :class:`StorageVolume`
-
-        :param node: The node to which you're attaching the volume.
-        :type node: :class:`Node`
-
-        :param device: The device number order.
-        :type device: : ``int``
-
-        :param ex_bus_type: Bus type. Either IDE or VIRTIO (default).
-        :type ex_bus_type: ``str``
-
-        :return:    Instance of class ``StorageVolume``
-        :rtype:     :class:`StorageVolume`
-        """
-        action = 'connectStorageToServer'
-        body = {'action': action,
-                'request': 'true',
-                'storageId': volume.id,
-                'serverId': node.id,
-                'busType': ex_bus_type,
-                'deviceNumber': str(device)
-                }
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-        return volume
-
-    def create_volume(self, size, name=None,
-                      ex_datacenter=None, ex_image=None, ex_password=None):
-        """
-        Creates a volume.
-
-        :param ex_datacenter: The datacenter you're placing
-                              the storage in. (req)
-        :type ex_datacenter: :class:`Datacenter`
-
-        :param ex_image: The OS image for the volume.
-        :type ex_image: :class:`NodeImage`
-
-        :param ex_password: Optional password for root.
-        :type ex_password: : ``str``
-
-        :return:    Instance of class ``StorageVolume``
-        :rtype:     :class:`StorageVolume`
-        """
-        action = 'createStorage'
-        body = {'action': action,
-                'request': 'true',
-                'size': str(size),
-                'storageName': name,
-                'mountImageId': ex_image.id
-                }
-
-        if ex_datacenter:
-            body['dataCenterId'] = ex_datacenter.id
-
-        if ex_password:
-            body['profitBricksImagePassword'] = ex_password
-
-        data = self.connection.request(action=action,
-                                       data=body,
-                                       method='POST').object
-        volumes = self._to_volumes(data)
-        return volumes[0]
-
-    def detach_volume(self, volume):
-        """
-        Detaches a volume.
-
-        :param volume: The volume you're detaching.
-        :type volume: :class:`StorageVolume`
-
-        :rtype:     :``bool``
-        """
-        node_id = volume.extra['server_id']
-
-        action = 'disconnectStorageFromServer'
-        body = {'action': action,
-                'storageId': volume.id,
-                'serverId': node_id
-                }
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    def destroy_volume(self, volume):
-        """
-        Destroys a volume.
-
-        :param volume: The volume you're attaching.
-        :type volume: :class:`StorageVolume`
-
-        :rtype:     : ``bool``
-        """
-        action = 'deleteStorage'
-        body = {'action': action,
-                'storageId': volume.id}
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    def ex_update_volume(self, volume, storage_name=None, size=None):
-        """
-        Updates a volume.
-
-        :param volume: The volume you're attaching..
-        :type volume: :class:`StorageVolume`
-
-        :param storage_name: The name of the volume.
-        :type storage_name: : ``str``
-
-        :param size: The desired size.
-        :type size: ``int``
-
-        :rtype:     : ``bool``
-        """
-        action = 'updateStorage'
-        body = {'action': action,
-                'request': 'true',
-                'storageId': volume.id
-                }
-
-        if storage_name:
-            body['storageName'] = storage_name
-        if size:
-            body['size'] = str(size)
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    def ex_describe_volume(self, volume_id):
-        """
-        Describes a volume.
-
-        :param volume_id: The ID of the volume you're describing.
-        :type volume_id: :class:`StorageVolume`
-
-        :return:    Instance of class ``StorageVolume``
-        :rtype:     :class:`StorageVolume`
-        """
-        action = 'getStorage'
-        body = {'action': action,
-                'storageId': volume_id
-                }
-
-        data = self.connection.request(action=action,
-                                       data=body,
-                                       method='POST').object
-        volumes = self._to_volumes(data)
-        return volumes[0]
-
-    """
-    Extension Functions
-    """
-
-    ''' Server Extension Functions
-    '''
-    def ex_stop_node(self, node):
-        """
-        Stops a node.
-
-        This also deallocates the public IP space.
-
-        :param node: The node you wish to halt.
-        :type node: :class:`Node`
-
-        :rtype:     : ``bool``
-        """
-        action = 'stopServer'
-        body = {'action': action,
-                'serverId': node.id
-                }
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    def ex_start_node(self, node):
-        """
-        Starts a volume.
-
-        :param node: The node you wish to start.
-        :type node: :class:`Node`
-
-        :rtype:     : ``bool``
-        """
-        action = 'startServer'
-        body = {'action': action,
-                'serverId': node.id
-                }
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    def ex_list_availability_zones(self):
-        """
-        Returns a list of availability zones.
-        """
-
-        availability_zones = []
-
-        for key, values in self.AVAILABILITY_ZONE.items():
-            name = copy.deepcopy(values)["name"]
-
-            availability_zone = ProfitBricksAvailabilityZone(
-                name=name
-            )
-            availability_zones.append(availability_zone)
-
-        return availability_zones
-
-    def ex_describe_node(self, node):
-        """
-        Describes a node.
-
-        :param node: The node you wish to describe.
-        :type node: :class:`Node`
-
-        :return:    Instance of class ``Node``
-        :rtype:     :class:`Node`
-        """
-        action = 'getServer'
-        body = {'action': action,
-                'serverId': node.id
-                }
-
-        data = self.connection.request(action=action,
-                                       data=body,
-                                       method='POST').object
-        nodes = self._to_nodes(data)
-        return nodes[0]
-
-    def ex_update_node(self, node, name=None, cores=None,
-                       ram=None, availability_zone=None):
-        """
-        Updates a node.
-
-        :param cores: The number of CPUs the node should have.
-        :type device: : ``int``
-
-        :param ram: The amount of ram the machine should have.
-        :type ram: : ``int``
-
-        :param ex_availability_zone: Update the availability zone.
-        :type ex_availability_zone: :class:`ProfitBricksAvailabilityZone`
-
-        :rtype:     : ``bool``
-        """
-        action = 'updateServer'
-
-        body = {'action': action,
-                'request': 'true',
-                'serverId': node.id
-                }
-
-        if name:
-            body['serverName'] = name
-
-        if cores:
-            body['cores'] = str(cores)
-
-        if ram:
-            body['ram'] = str(ram)
-
-        if availability_zone:
-            body['availabilityZone'] = availability_zone.name
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    '''
-    Datacenter Extension Functions
-    '''
-
-    def ex_create_datacenter(self, name, location):
-        """
-        Creates a datacenter.
-
-        ProfitBricks has a concept of datacenters.
-        These represent buckets into which you
-        can place various compute resources.
-
-        :param name: The DC name.
-        :type name: : ``str``
-
-        :param location: The DC region.
-        :type location: : ``str``
-
-        :return:    Instance of class ``Datacenter``
-        :rtype:     :class:`Datacenter`
-        """
-        action = 'createDataCenter'
-
-        body = {'action': action,
-                'request': 'true',
-                'dataCenterName': name,
-                'location': location.lower()
-                }
-        data = self.connection.request(action=action,
-                                       data=body,
-                                       method='POST').object
-        datacenters = self._to_datacenters(data)
-        return datacenters[0]
-
-    def ex_destroy_datacenter(self, datacenter):
-        """
-        Destroys a datacenter.
-
-        :param datacenter: The DC you're destroying.
-        :type datacenter: :class:`Datacenter`
-
-        :rtype:     : ``bool``
-        """
-        action = 'deleteDataCenter'
-        body = {'action': action,
-                'dataCenterId': datacenter.id
-                }
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    def ex_describe_datacenter(self, datacenter_id):
-        """
-        Describes a datacenter.
-
-        :param datacenter_id: The DC you are describing.
-        :type datacenter_id: ``str``
-
-        :return:    Instance of class ``Datacenter``
-        :rtype:     :class:`Datacenter`
-        """
-
-        action = 'getDataCenter'
-        body = {'action': action,
-                'dataCenterId': datacenter_id
-                }
-
-        data = self.connection.request(action=action,
-                                       data=body,
-                                       method='POST').object
-        datacenters = self._to_datacenters(data)
-        return datacenters[0]
-
-    def ex_list_datacenters(self):
-        """
-        Lists all datacenters.
-
-        :return:    ``list`` of class ``Datacenter``
-        :rtype:     :class:`Datacenter`
-        """
-        action = 'getAllDataCenters'
-        body = {'action': action}
-
-        return self._to_datacenters(self.connection.request(
-                                    action=action,
-                                    data=body,
-                                    method='POST').object)
-
-    def ex_rename_datacenter(self, datacenter, name):
-        """
-        Update a datacenter.
-
-        :param datacenter: The DC you are renaming.
-        :type datacenter: :class:`Datacenter`
-
-        :param name: The DC name.
-        :type name: : ``str``
-
-        :rtype:     : ``bool``
-        """
-        action = 'updateDataCenter'
-        body = {'action': action,
-                'request': 'true',
-                'dataCenterId': datacenter.id,
-                'dataCenterName': name
-                }
-
-        self.connection.request(action=action,
-                                data=body,
-                                method='POST').object
-
-        return True
-
-    def ex_clear_datacenter(self, datacenter):
-        """
-        Clear a datacenter.
-
-        This removes all objects in a DC.
-
-        :param datacenter: The DC you're clearing.
-        :type datacenter: :class:`Datacenter`
-
-        :rtype:     : ``bool``
-        """
-        action = 'clearDataCenter'
-        body = {'action': action,
-                'dataCenterId': datacenter.id
-                }
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    '''
-    Network Interface Extension Functions
-    '''
-
-    def ex_list_network_interfaces(self):
-        """
-        Lists all network interfaces.
-
-        :return:    ``list`` of class ``ProfitBricksNetworkInterface``
-        :rtype:     :class:`ProfitBricksNetworkInterface`
-        """
-        action = 'getAllNic'
-        body = {'action': action}
-
-        return self._to_interfaces(
-            self.connection.request(action=action,
-                                    data=body,
-                                    method='POST').object)
-
-    def ex_describe_network_interface(self, network_interface):
-        """
-        Describes a network interface.
-
-        :param network_interface: The NIC you wish to describe.
-        :type network_interface: :class:`ProfitBricksNetworkInterface`
-
-        :return:    Instance of class ``ProfitBricksNetworkInterface``
-        :rtype:     :class:`ProfitBricksNetworkInterface`
-        """
-        action = 'getNic'
-        body = {'action': action,
-                'nicId': network_interface.id
-                }
-
-        return self._to_interface(
-            self.connection.request(
-                action=action,
-                data=body,
-                method='POST').object.findall('.//return')[0])
-
-    def ex_create_network_interface(self, node,
-                                    lan_id=None, ip=None, nic_name=None,
-                                    dhcp_active=True):
-        """
-        Creates a network interface.
-
-        :param lan_id: The ID for the LAN.
-        :type lan_id: : ``int``
-
-        :param ip: The IP address for the NIC.
-        :type ip: ``str``
-
-        :param nic_name: The name of the NIC, e.g. PUBLIC.
-        :type nic_name: ``str``
-
-        :param dhcp_active: Set to false to disable.
-        :type dhcp_active: ``bool``
-
-        :return:    Instance of class ``ProfitBricksNetworkInterface``
-        :rtype:     :class:`ProfitBricksNetworkInterface`
-        """
-        action = 'createNic'
-        body = {'action': action,
-                'request': 'true',
-                'serverId': node.id,
-                'dhcpActive': str(dhcp_active)
-                }
-
-        if lan_id:
-            body['lanId'] = str(lan_id)
-        else:
-            body['lanId'] = str(1)
-
-        if ip:
-            body['ip'] = ip
-
-        if nic_name:
-            body['nicName'] = nic_name
-
-        data = self.connection.request(action=action,
-                                       data=body,
-                                       method='POST').object
-        interfaces = self._to_interfaces(data)
-        return interfaces[0]
-
-    def ex_update_network_interface(self, network_interface, name=None,
-                                    lan_id=None, ip=None,
-                                    dhcp_active=None):
-        """
-        Updates a network interface.
-
-        :param lan_id: The ID for the LAN.
-        :type lan_id: : ``int``
-
-        :param ip: The IP address for the NIC.
-        :type ip: ``str``
-
-        :param name: The name of the NIC, e.g. PUBLIC.
-        :type name: ``str``
-
-        :param dhcp_active: Set to false to disable.
-        :type dhcp_active: ``bool``
-
-        :rtype:     : ``bool``
-        """
-        action = 'updateNic'
-        body = {'action': action,
-                'request': 'true',
-                'nicId': network_interface.id
-                }
-
-        if name:
-            body['nicName'] = name
-
-        if lan_id:
-            body['lanId'] = str(lan_id)
-
-        if ip:
-            body['ip'] = ip
-
-        if dhcp_active is not None:
-            body['dhcpActive'] = str(dhcp_active).lower()
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    def ex_destroy_network_interface(self, network_interface):
-        """
-        Destroy a network interface.
-
-        :param network_interface: The NIC you wish to describe.
-        :type network_interface: :class:`ProfitBricksNetworkInterface`
-
-        :rtype:     : ``bool``
-        """
-
-        action = 'deleteNic'
-        body = {'action': action,
-                'nicId': network_interface.id}
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    def ex_set_inet_access(self, datacenter,
-                           network_interface, internet_access=True):
-
-        action = 'setInternetAccess'
-
-        body = {'action': action,
-                'dataCenterId': datacenter.id,
-                'lanId': network_interface.extra['lan_id'],
-                'internetAccess': str(internet_access).lower()
-                }
-
-        self.connection.request(action=action,
-                                data=body, method='POST').object
-
-        return True
-
-    """
-    Private Functions
-    """
-
-    def _to_datacenters(self, object):
-        return [self._to_datacenter(
-            datacenter) for datacenter in object.findall('.//return')]
-
-    def _to_datacenter(self, datacenter):
-        datacenter_id = datacenter.find('dataCenterId').text
-        if ET.iselement(datacenter.find('dataCenterName')):
-            datacenter_name = datacenter.find('dataCenterName').text
-        else:
-            datacenter_name = None
-        version = datacenter.find('dataCenterVersion').text
-        if ET.iselement(datacenter.find('provisioningState')):
-            provisioning_state = datacenter.find('provisioningState').text
-        else:
-            provisioning_state = None
-        if ET.iselement(datacenter.find('location')):
-            location = datacenter.find('location').text
-        else:
-            location = None
-
-        provisioning_state = self.PROVISIONING_STATE.get(provisioning_state,
-                                                         NodeState.UNKNOWN)
-
-        return Datacenter(id=datacenter_id,
-                          name=datacenter_name,
-                          version=version,
-                          driver=self.connection.driver,
-                          extra={'provisioning_state': provisioning_state,
-                                 'location': location})
-
-    def _to_images(self, object):
-        return [self._to_image(image) for image in object.findall('.//return')]
-
-    def _to_image(self, image):
-        image_id = image.find('imageId').text
-        image_name = image.find('imageName').text
-        image_size = image.find('imageSize').text
-        image_type = image.find('imageType').text
-        os_type = image.find('osType').text
-        public = image.find('public').text
-        writeable = image.find('writeable').text
-
-        if ET.iselement(image.find('cpuHotpluggable')):
-            cpu_hotpluggable = image.find('cpuHotpluggable').text
-        else:
-            cpu_hotpluggable = None
-
-        if ET.iselement(image.find('memoryHotpluggable')):
-            memory_hotpluggable = image.find('memoryHotpluggable').text
-        else:
-            memory_hotpluggable = None
-
-        if ET.iselement(image.find('location')):
-            if image.find('region'):
-                image_region = image.find('region').text
-            else:
-                image_region = None
-        else:
-            image_region = None
-
-        return NodeImage(id=image_id,
-                         name=image_name,
-                         driver=self.connection.driver,
-                         extra={'image_size': image_size,
-                                'image_type': image_type,
-                                'cpu_hotpluggable': cpu_hotpluggable,
-                                'memory_hotpluggable': memory_hotpluggable,
-                                'os_type': os_type,
-                                'public': public,
-                                'location': image_region,
-                                'writeable': writeable})
-
-    def _to_nodes(self, object):
-        return [self._to_node(n) for n in object.findall('.//return')]
-
-    def _to_node(self, node):
-        """
-        Convert the request into a node Node
-        """
-        ATTRIBUTE_NAME_MAP = {
-            'dataCenterId': 'datacenter_id',
-            'dataCenterVersion': 'datacenter_version',
-            'serverId': 'node_id',
-            'serverName': 'node_name',
-            'cores': 'cores',
-            'ram': 'ram',
-            'internetAccess': 'internet_access',
-            'provisioningState': 'provisioning_state',
-            'virtualMachineState': 'virtual_machine_state',
-            'creationTime': 'creation_time',
-            'lastModificationTime': 'last_modification_time',
-            'osType': 'os_type',
-            'availabilityZone': 'availability_zone',
-            'cpuHotPlug': 'cpu_hotpluggable',
-            'ramHotPlug': 'memory_hotpluggable',
-            'nicHotPlug': 'nic_hotpluggable',
-            'discVirtioHotPlug': 'disc_virtio_hotplug',
-            'discVirtioHotUnPlug': 'disc_virtio_hotunplug'
-        }
-
-        extra = {}
-        for attribute_name, extra_name in ATTRIBUTE_NAME_MAP.items():
-            elem = node.find(attribute_name)
-
-            if ET.iselement(elem):
-                value = elem.text
-            else:
-                value = None
-
-            extra[extra_name] = value
-
-        public_ips = []
-        private_ips = []
-
-        if ET.iselement(node.find('nics')):
-            for nic in node.findall('.//nics'):
-                n_elements = list(nic.findall('.//ips'))
-                if len(n_elements) > 0:
-                    ip = n_elements[0].text
-                    if is_private_subnet(ip):
-                        private_ips.append(ip)
-                    else:
-                        public_ips.append(ip)
-
-        extra['provisioning_state'] = self.PROVISIONING_STATE.get(
-            extra['provisioning_state'], NodeState.UNKNOWN)
-
-        node_id = extra['node_id']
-        node_name = extra['node_name']
-        state = self.NODE_STATE_MAP.get(extra['virtual_machine_state'],
-                                        NodeState.UNKNOWN)
-
-        return Node(
-            id=node_id,
-            name=node_name,
-            state=state,
-            public_ips=public_ips,
-            private_ips=private_ips,
-            driver=self.connection.driver,
-            extra=extra)
-
-    def _to_volumes(self, object):
-        return [self._to_volume(
-            volume) for volume in object.findall('.//return')]
-
-    def _to_volume(self, volume, node=None):
-        ATTRIBUTE_NAME_MAP = {
-            'dataCenterId': 'datacenter_id',
-            'storageId': 'storage_id',
-            'storageName': 'storage_name',
-            'serverIds': 'server_id',
-            'creationTime': 'creation_time',
-            'lastModificationTime': 'last_modification_time',
-            'provisioningState': 'provisioning_state',
-            'size': 'size',
-        }
-
-        extra = {}
-        for attribute_name, extra_name in ATTRIBUTE_NAME_MAP.items():
-            elem = volume.find(attribute_name)
-
-            if ET.iselement(elem):
-                value = elem.text
-            else:
-                value = None
-
-            extra[extra_name] = value
-
-        if ET.iselement(volume.find('mountImage')):
-            image_id = volume.find('mountImage')[0].text
-            image_name = volume.find('mountImage')[1].text
-        else:
-            image_id = None
-            image_name = None
-
-        extra['image_id'] = image_id
-        extra['image_name'] = image_name
-        extra['size'] = int(extra['size']) if extra['size'] else 0
-        extra['provisioning_state'] = \
-            self.PROVISIONING_STATE.get(extra['provisioning_state'],
-                                        NodeState.UNKNOWN)
-
-        storage_id = extra['storage_id']
-        storage_name = extra['storage_name']
-        size = extra['size']
-
-        return StorageVolume(
-            id=storage_id,
-            name=storage_name,
-            size=size,
-            driver=self.connection.driver,
-            extra=extra)
-
-    def _to_interfaces(self, object):
-        return [self._to_interface(
-            interface) for interface in object.findall('.//return')]
-
-    def _to_interface(self, interface):
-        ATTRIBUTE_NAME_MAP = {
-            'nicId': 'nic_id',
-            'nicName': 'nic_name',
-            'serverId': 'server_id',
-            'lanId': 'lan_id',
-            'internetAccess': 'internet_access',
-            'macAddress': 'mac_address',
-            'dhcpActive': 'dhcp_active',
-            'gatewayIp': 'gateway_ip',
-            'provisioningState': 'provisioning_state',
-            'dataCenterId': 'datacenter_id',
-            'dataCenterVersion': 'datacenter_version'
-        }
-
-        extra = {}
-        for attribute_name, extra_name in ATTRIBUTE_NAME_MAP.items():
-            elem = interface.find(attribute_name)
-
-            if ET.iselement(elem):
-                value = elem.text
-            else:
-                value = None
-
-            extra[extra_name] = value
-
-        ips = []
-
-        if ET.iselement(interface.find('ips')):
-            for ip in interface.findall('.//ips'):
-                ips.append(ip.text)
-
-        extra['ips'] = ips
-
-        nic_id = extra['nic_id']
-        nic_name = extra['nic_name']
-        state = self.PROVISIONING_STATE.get(extra['provisioning_state'],
-                                            NodeState.UNKNOWN)
-
-        return ProfitBricksNetworkInterface(
-            id=nic_id,
-            name=nic_name,
-            state=state,
-            extra=extra)
-
-    def _to_location(self, data):
-
-        return NodeLocation(id=data["region"],
-                            name=data["region"],
-                            country=data["country"],
-                            driver=self.connection.driver)
-
-    def _to_node_size(self, data):
-        """
-        Convert the PROFIT_BRICKS_GENERIC_SIZES into NodeSize
-        """
-        return NodeSize(id=data["id"],
-                        name=data["name"],
-                        ram=data["ram"],
-                        disk=data["disk"],
-                        bandwidth=None,
-                        price=None,
-                        driver=self.connection.driver,
-                        extra={
-                            'cores': data["cores"]})
-
-    def _wait_for_datacenter_state(self, datacenter, state=NodeState.RUNNING,
-                                   timeout=300, interval=5):
-        """
-        Private function that waits the datacenter to transition into the
-        specified state.
-
-        :return: Datacenter object on success.
-        :rtype: :class:`.Datacenter`
-        """
-        wait_time = 0
-        datacenter = self.ex_describe_datacenter(datacenter_id=datacenter.id)
-
-        while (datacenter.extra['provisioning_state'] != state):
-            datacenter = \
-                self.ex_describe_datacenter(datacenter_id=datacenter.id)
-            if datacenter.extra['provisioning_state'] == state:
-                break
-
-            if wait_time >= timeout:
-                raise Exception('Datacenter didn\'t transition to %s state '
-                                'in %s seconds' % (state, timeout))
-
-            wait_time += interval
-            time.sleep(interval)
-
-        return datacenter
-
-    def _create_new_datacenter_for_node(self, name, location):
-        """
-        Creates a Datacenter for a node.
-        """
-        dc_name = name + '-DC'
-
-        if not location:
-            loc = 'us/las'
-        else:
-            loc = location.id
-        return self.ex_create_datacenter(name=dc_name, location=loc)
-
-    def _wait_for_storage_volume_state(self, volume, state=NodeState.RUNNING,
-                                       timeout=300, interval=5):
-        """
-        Wait for volume to transition into the specified state.
-
-        :return: Volume object on success.
-        :rtype: :class:`Volume`
-        """
-        wait_time = 0
-        volume = self.ex_describe_volume(volume_id=volume.id)
-
-        while (volume.extra['provisioning_state'] != state):
-            volume = self.ex_describe_volume(volume_id=volume.id)
-            if volume.extra['provisioning_state'] == state:
-                break
-
-            if wait_time >= timeout:
-                raise Exception('Volume didn\'t transition to %s state '
-                                'in %s seconds' % (state, timeout))
-
-            wait_time += interval
-            time.sleep(interval)
-
-        return volume
-
-    def _create_node_volume(self, ex_disk, image, password,
-                            name, ex_datacenter=None, new_datacenter=None):
-
-        volume_name = name + '-volume'
-
-        if ex_datacenter:
-            volume = self.create_volume(size=ex_disk,
-                                        ex_datacenter=ex_datacenter,
-                                        ex_image=image,
-                                        ex_password=password,
-                                        name=volume_name)
-        else:
-            volume = self.create_volume(size=ex_disk,
-                                        ex_datacenter=new_datacenter,
-                                        ex_image=image,
-                                        ex_password=password,
-                                        name=volume_name)
-
-        return volume

http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/rackspace.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/rackspace.py b/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/rackspace.py
deleted file mode 100644
index 4aab926..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/rackspace.py
+++ /dev/null
@@ -1,253 +0,0 @@
-# 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.
-"""
-Rackspace driver
-"""
-from libcloud.compute.types import Provider, LibcloudError, VolumeSnapshotState
-from libcloud.compute.base import NodeLocation, VolumeSnapshot
-from libcloud.compute.drivers.openstack import OpenStack_1_0_Connection,\
-    OpenStack_1_0_NodeDriver, OpenStack_1_0_Response
-from libcloud.compute.drivers.openstack import OpenStack_1_1_Connection,\
-    OpenStack_1_1_NodeDriver
-
-from libcloud.common.rackspace import AUTH_URL
-from libcloud.utils.iso8601 import parse_date
-
-SERVICE_TYPE = 'compute'
-SERVICE_NAME_GEN1 = 'cloudServers'
-SERVICE_NAME_GEN2 = 'cloudServersOpenStack'
-ENDPOINT_ARGS_MAP = {
-    'dfw': {'service_type': SERVICE_TYPE,
-            'name': SERVICE_NAME_GEN2,
-            'region': 'DFW'},
-    'ord': {'service_type': SERVICE_TYPE,
-            'name': SERVICE_NAME_GEN2,
-            'region': 'ORD'},
-    'iad': {'service_type': SERVICE_TYPE,
-            'name': SERVICE_NAME_GEN2,
-            'region': 'IAD'},
-    'lon': {'service_type': SERVICE_TYPE,
-            'name': SERVICE_NAME_GEN2,
-            'region': 'LON'},
-    'syd': {'service_type': SERVICE_TYPE,
-            'name': SERVICE_NAME_GEN2,
-            'region': 'SYD'},
-    'hkg': {'service_type': SERVICE_TYPE,
-            'name': SERVICE_NAME_GEN2,
-            'region': 'HKG'},
-
-}
-
-
-class RackspaceFirstGenConnection(OpenStack_1_0_Connection):
-    """
-    Connection class for the Rackspace first-gen driver.
-    """
-    responseCls = OpenStack_1_0_Response
-    XML_NAMESPACE = 'http://docs.rackspacecloud.com/servers/api/v1.0'
-    auth_url = AUTH_URL
-    _auth_version = '2.0'
-    cache_busting = True
-
-    def __init__(self, *args, **kwargs):
-        self.region = kwargs.pop('region', None)
-        super(RackspaceFirstGenConnection, self).__init__(*args, **kwargs)
-
-    def get_endpoint(self):
-        if '2.0' in self._auth_version:
-            ep = self.service_catalog.get_endpoint(service_type=SERVICE_TYPE,
-                                                   name=SERVICE_NAME_GEN1)
-        else:
-            raise LibcloudError(
-                'Auth version "%s" not supported' % (self._auth_version))
-
-        public_url = ep.url
-
-        if not public_url:
-            raise LibcloudError('Could not find specified endpoint')
-
-        # This is a nasty hack, but it's required because of how the
-        # auth system works.
-        # Old US accounts can access UK API endpoint, but they don't
-        # have this endpoint in the service catalog. Same goes for the
-        # old UK accounts and US endpoint.
-        if self.region == 'us':
-            # Old UK account, which only have uk endpoint in the catalog
-            public_url = public_url.replace('https://lon.servers.api',
-                                            'https://servers.api')
-        elif self.region == 'uk':
-            # Old US account, which only has us endpoints in the catalog
-            public_url = public_url.replace('https://servers.api',
-                                            'https://lon.servers.api')
-
-        return public_url
-
-    def get_service_name(self):
-        return SERVICE_NAME_GEN1
-
-
-class RackspaceFirstGenNodeDriver(OpenStack_1_0_NodeDriver):
-    name = 'Rackspace Cloud (First Gen)'
-    website = 'http://www.rackspace.com'
-    connectionCls = RackspaceFirstGenConnection
-    type = Provider.RACKSPACE_FIRST_GEN
-    api_name = 'rackspace'
-
-    def __init__(self, key, secret=None, secure=True, host=None, port=None,
-                 region='us', **kwargs):
-        """
-        @inherits:  :class:`NodeDriver.__init__`
-
-        :param region: Region ID which should be used
-        :type region: ``str``
-        """
-        if region not in ['us', 'uk']:
-            raise ValueError('Invalid region: %s' % (region))
-
-        super(RackspaceFirstGenNodeDriver, self).__init__(key=key,
-                                                          secret=secret,
-                                                          secure=secure,
-                                                          host=host,
-                                                          port=port,
-                                                          region=region,
-                                                          **kwargs)
-
-    def list_locations(self):
-        """
-        Lists available locations
-
-        Locations cannot be set or retrieved via the API, but currently
-        there are two locations, DFW and ORD.
-
-        @inherits: :class:`OpenStack_1_0_NodeDriver.list_locations`
-        """
-        if self.region == 'us':
-            locations = [NodeLocation(0, "Rackspace DFW1/ORD1", 'US', self)]
-        elif self.region == 'uk':
-            locations = [NodeLocation(0, 'Rackspace UK London', 'UK', self)]
-
-        return locations
-
-    def _ex_connection_class_kwargs(self):
-        kwargs = self.openstack_connection_kwargs()
-        kwargs['region'] = self.region
-        return kwargs
-
-
-class RackspaceConnection(OpenStack_1_1_Connection):
-    """
-    Connection class for the Rackspace next-gen OpenStack base driver.
-    """
-
-    auth_url = AUTH_URL
-    _auth_version = '2.0'
-
-    def __init__(self, *args, **kwargs):
-        self.region = kwargs.pop('region', None)
-        self.get_endpoint_args = kwargs.pop('get_endpoint_args', None)
-        super(RackspaceConnection, self).__init__(*args, **kwargs)
-
-    def get_service_name(self):
-        if not self.get_endpoint_args:
-            # if they used ex_force_base_url, assume the Rackspace default
-            return SERVICE_NAME_GEN2
-
-        return self.get_endpoint_args.get('name', SERVICE_NAME_GEN2)
-
-    def get_endpoint(self):
-        if not self.get_endpoint_args:
-            raise LibcloudError(
-                'RackspaceConnection must have get_endpoint_args set')
-
-        if '2.0' in self._auth_version:
-            ep = self.service_catalog.get_endpoint(**self.get_endpoint_args)
-        else:
-            raise LibcloudError(
-                'Auth version "%s" not supported' % (self._auth_version))
-
-        public_url = ep.url
-
-        if not public_url:
-            raise LibcloudError('Could not find specified endpoint')
-
-        return public_url
-
-
-class RackspaceNodeDriver(OpenStack_1_1_NodeDriver):
-    name = 'Rackspace Cloud (Next Gen)'
-    website = 'http://www.rackspace.com'
-    connectionCls = RackspaceConnection
-    type = Provider.RACKSPACE
-
-    _networks_url_prefix = '/os-networksv2'
-
-    def __init__(self, key, secret=None, secure=True, host=None, port=None,
-                 region='dfw', **kwargs):
-        """
-        @inherits:  :class:`NodeDriver.__init__`
-
-        :param region: ID of the region which should be used.
-        :type region: ``str``
-        """
-        valid_regions = ENDPOINT_ARGS_MAP.keys()
-
-        if region not in valid_regions:
-            raise ValueError('Invalid region: %s' % (region))
-
-        if region == 'lon':
-            self.api_name = 'rackspacenovalon'
-        elif region == 'syd':
-            self.api_name = 'rackspacenovasyd'
-        else:
-            self.api_name = 'rackspacenovaus'
-
-        super(RackspaceNodeDriver, self).__init__(key=key, secret=secret,
-                                                  secure=secure, host=host,
-                                                  port=port,
-                                                  region=region,
-                                                  **kwargs)
-
-    def _to_snapshot(self, api_node):
-        if 'snapshot' in api_node:
-            api_node = api_node['snapshot']
-
-        extra = {'volume_id': api_node['volumeId'],
-                 'name': api_node['displayName'],
-                 'created': api_node['createdAt'],
-                 'description': api_node['displayDescription'],
-                 'status': api_node['status']}
-
-        state = self.SNAPSHOT_STATE_MAP.get(
-            api_node['status'],
-            VolumeSnapshotState.UNKNOWN
-        )
-
-        try:
-            created_td = parse_date(api_node['createdAt'])
-        except ValueError:
-            created_td = None
-
-        snapshot = VolumeSnapshot(id=api_node['id'], driver=self,
-                                  size=api_node['size'],
-                                  extra=extra,
-                                  created=created_td,
-                                  state=state)
-        return snapshot
-
-    def _ex_connection_class_kwargs(self):
-        endpoint_args = ENDPOINT_ARGS_MAP[self.region]
-        kwargs = self.openstack_connection_kwargs()
-        kwargs['region'] = self.region
-        kwargs['get_endpoint_args'] = endpoint_args
-        return kwargs

http://git-wip-us.apache.org/repos/asf/libcloud/blob/8afcda91/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/rimuhosting.py
----------------------------------------------------------------------
diff --git a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/rimuhosting.py b/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/rimuhosting.py
deleted file mode 100644
index 4cf8457..0000000
--- a/apache-libcloud-1.0.0rc2/libcloud/compute/drivers/rimuhosting.py
+++ /dev/null
@@ -1,339 +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.
-"""
-RimuHosting Driver
-"""
-try:
-    import simplejson as json
-except ImportError:
-    import json
-
-from libcloud.common.base import ConnectionKey, JsonResponse
-from libcloud.common.types import InvalidCredsError
-from libcloud.compute.types import Provider, NodeState
-from libcloud.compute.base import NodeDriver, NodeSize, Node, NodeLocation
-from libcloud.compute.base import NodeImage
-
-API_CONTEXT = '/r'
-API_HOST = 'rimuhosting.com'
-
-
-class RimuHostingException(Exception):
-    """
-    Exception class for RimuHosting driver
-    """
-
-    def __str__(self):
-        return self.args[0]
-
-    def __repr__(self):
-        return "<RimuHostingException '%s'>" % (self.args[0])
-
-
-class RimuHostingResponse(JsonResponse):
-    """
-    Response Class for RimuHosting driver
-    """
-    def success(self):
-        if self.status == 403:
-            raise InvalidCredsError()
-        return True
-
-    def parse_body(self):
-        try:
-            js = super(RimuHostingResponse, self).parse_body()
-            keys = list(js.keys())
-            if js[keys[0]]['response_type'] == "ERROR":
-                raise RimuHostingException(
-                    js[keys[0]]['human_readable_message']
-                )
-            return js[keys[0]]
-        except KeyError:
-            raise RimuHostingException('Could not parse body: %s'
-                                       % (self.body))
-
-
-class RimuHostingConnection(ConnectionKey):
-    """
-    Connection class for the RimuHosting driver
-    """
-
-    api_context = API_CONTEXT
-    host = API_HOST
-    port = 443
-    responseCls = RimuHostingResponse
-
-    def __init__(self, key, secure=True, retry_delay=None,
-                 backoff=None, timeout=None):
-        # override __init__ so that we can set secure of False for testing
-        ConnectionKey.__init__(self, key, secure, timeout=timeout,
-                               retry_delay=retry_delay, backoff=backoff)
-
-    def add_default_headers(self, headers):
-        # We want JSON back from the server. Could be application/xml
-        # (but JSON is better).
-        headers['Accept'] = 'application/json'
-        # Must encode all data as json, or override this header.
-        headers['Content-Type'] = 'application/json'
-
-        headers['Authorization'] = 'rimuhosting apikey=%s' % (self.key)
-        return headers
-
-    def request(self, action, params=None, data='', headers=None,
-                method='GET'):
-        if not headers:
-            headers = {}
-        if not params:
-            params = {}
-        # Override this method to prepend the api_context
-        return ConnectionKey.request(self, self.api_context + action,
-                                     params, data, headers, method)
-
-
-class RimuHostingNodeDriver(NodeDriver):
-    """
-    RimuHosting node driver
-    """
-
-    type = Provider.RIMUHOSTING
-    name = 'RimuHosting'
-    website = 'http://rimuhosting.com/'
-    connectionCls = RimuHostingConnection
-    features = {'create_node': ['password']}
-
-    def __init__(self, key, host=API_HOST, port=443,
-                 api_context=API_CONTEXT, secure=True):
-        """
-        :param    key: API key (required)
-        :type     key: ``str``
-
-        :param    host: hostname for connection
-        :type     host: ``str``
-
-        :param    port: Override port used for connections.
-        :type     port: ``int``
-
-        :param    api_context: Optional API context.
-        :type     api_context: ``str``
-
-        :param    secure: Weither to use HTTPS or HTTP.
-        :type     secure: ``bool``
-
-        :rtype: ``None``
-        """
-        # Pass in some extra vars so that
-        self.key = key
-        self.secure = secure
-        self.connection = self.connectionCls(key, secure)
-        self.connection.host = host
-        self.connection.api_context = api_context
-        self.connection.port = port
-        self.connection.driver = self
-        self.connection.connect()
-
-    def _order_uri(self, node, resource):
-        # Returns the order uri with its resourse appended.
-        return "/orders/%s/%s" % (node.id, resource)
-
-    # TODO: Get the node state.
-    def _to_node(self, order):
-        n = Node(id=order['slug'],
-                 name=order['domain_name'],
-                 state=NodeState.RUNNING,
-                 public_ips=(
-                     [order['allocated_ips']['primary_ip']] +
-                     order['allocated_ips']['secondary_ips']),
-                 private_ips=[],
-                 driver=self.connection.driver,
-                 extra={
-                     'order_oid': order['order_oid'],
-                     'monthly_recurring_fee': order.get(
-                         'billing_info').get('monthly_recurring_fee')})
-        return n
-
-    def _to_size(self, plan):
-        return NodeSize(
-            id=plan['pricing_plan_code'],
-            name=plan['pricing_plan_description'],
-            ram=plan['minimum_memory_mb'],
-            disk=plan['minimum_disk_gb'],
-            bandwidth=plan['minimum_data_transfer_allowance_gb'],
-            price=plan['monthly_recurring_amt']['amt_usd'],
-            driver=self.connection.driver
-        )
-
-    def _to_image(self, image):
-        return NodeImage(id=image['distro_code'],
-                         name=image['distro_description'],
-                         driver=self.connection.driver)
-
-    def list_sizes(self, location=None):
-        # Returns a list of sizes (aka plans)
-        # Get plans. Note this is really just for libcloud.
-        # We are happy with any size.
-        if location is None:
-            location = ''
-        else:
-            location = ";dc_location=%s" % (location.id)
-
-        res = self.connection.request(
-            '/pricing-plans;server-type=VPS%s' % (location)).object
-        return list(map(lambda x: self._to_size(x), res['pricing_plan_infos']))
-
-    def list_nodes(self):
-        # Returns a list of Nodes
-        # Will only include active ones.
-        res = self.connection.request('/orders;include_inactive=N').object
-        return list(map(lambda x: self._to_node(x), res['about_orders']))
-
-    def list_images(self, location=None):
-        # Get all base images.
-        # TODO: add other image sources. (Such as a backup of a VPS)
-        # All Images are available for use at all locations
-        res = self.connection.request('/distributions').object
-        return list(map(lambda x: self._to_image(x), res['distro_infos']))
-
-    def reboot_node(self, node):
-        # Reboot
-        # PUT the state of RESTARTING to restart a VPS.
-        # All data is encoded as JSON
-        data = {'reboot_request': {'running_state': 'RESTARTING'}}
-        uri = self._order_uri(node, 'vps/running-state')
-        self.connection.request(uri, data=json.dumps(data), method='PUT')
-        # XXX check that the response was actually successful
-        return True
-
-    def destroy_node(self, node):
-        # Shutdown a VPS.
-        uri = self._order_uri(node, 'vps')
-        self.connection.request(uri, method='DELETE')
-        # XXX check that the response was actually successful
-        return True
-
-    def create_node(self, **kwargs):
-        """Creates a RimuHosting instance
-
-        @inherits: :class:`NodeDriver.create_node`
-
-        :keyword    name: Must be a FQDN. e.g example.com.
-        :type       name: ``str``
-
-        :keyword    ex_billing_oid: If not set,
-                                    a billing method is automatically picked.
-        :type       ex_billing_oid: ``str``
-
-        :keyword    ex_host_server_oid: The host server to set the VPS up on.
-        :type       ex_host_server_oid: ``str``
-
-        :keyword    ex_vps_order_oid_to_clone: Clone another VPS to use as
-                                                the image for the new VPS.
-        :type       ex_vps_order_oid_to_clone: ``str``
-
-        :keyword    ex_num_ips: Number of IPs to allocate. Defaults to 1.
-        :type       ex_num_ips: ``int``
-
-        :keyword    ex_extra_ip_reason: Reason for needing the extra IPs.
-        :type       ex_extra_ip_reason: ``str``
-
-        :keyword    ex_memory_mb: Memory to allocate to the VPS.
-        :type       ex_memory_mb: ``int``
-
-        :keyword    ex_disk_space_mb: Diskspace to allocate to the VPS.
-            Defaults to 4096 (4GB).
-        :type       ex_disk_space_mb: ``int``
-
-        :keyword    ex_disk_space_2_mb: Secondary disk size allocation.
-                                        Disabled by default.
-        :type       ex_disk_space_2_mb: ``int``
-
-        :keyword    ex_control_panel: Control panel to install on the VPS.
-        :type       ex_control_panel: ``str``
-        """
-        # Note we don't do much error checking in this because we
-        # expect the API to error out if there is a problem.
-        name = kwargs['name']
-        image = kwargs['image']
-        size = kwargs['size']
-
-        data = {
-            'instantiation_options': {
-                'domain_name': name,
-                'distro': image.id
-            },
-            'pricing_plan_code': size.id,
-            'vps_parameters': {}
-        }
-
-        if 'ex_control_panel' in kwargs:
-            data['instantiation_options']['control_panel'] = \
-                kwargs['ex_control_panel']
-
-        auth = self._get_and_check_auth(kwargs.get('auth'))
-        data['instantiation_options']['password'] = auth.password
-
-        if 'ex_billing_oid' in kwargs:
-            # TODO check for valid oid.
-            data['billing_oid'] = kwargs['ex_billing_oid']
-
-        if 'ex_host_server_oid' in kwargs:
-            data['host_server_oid'] = kwargs['ex_host_server_oid']
-
-        if 'ex_vps_order_oid_to_clone' in kwargs:
-            data['vps_order_oid_to_clone'] = \
-                kwargs['ex_vps_order_oid_to_clone']
-
-        if 'ex_num_ips' in kwargs and int(kwargs['ex_num_ips']) > 1:
-            if 'ex_extra_ip_reason' not in kwargs:
-                raise RimuHostingException(
-                    'Need an reason for having an extra IP')
-            else:
-                if 'ip_request' not in data:
-                    data['ip_request'] = {}
-                data['ip_request']['num_ips'] = int(kwargs['ex_num_ips'])
-                data['ip_request']['extra_ip_reason'] = \
-                    kwargs['ex_extra_ip_reason']
-
-        if 'ex_memory_mb' in kwargs:
-            data['vps_parameters']['memory_mb'] = kwargs['ex_memory_mb']
-
-        if 'ex_disk_space_mb' in kwargs:
-            data['vps_parameters']['disk_space_mb'] = \
-                kwargs['ex_disk_space_mb']
-
-        if 'ex_disk_space_2_mb' in kwargs:
-            data['vps_parameters']['disk_space_2_mb'] =\
-                kwargs['ex_disk_space_2_mb']
-
-        # Don't send empty 'vps_parameters' attribute
-        if not data['vps_parameters']:
-            del data['vps_parameters']
-
-        res = self.connection.request(
-            '/orders/new-vps',
-            method='POST',
-            data=json.dumps({"new-vps": data})
-        ).object
-        node = self._to_node(res['about_order'])
-        node.extra['password'] = \
-            res['new_order_request']['instantiation_options']['password']
-        return node
-
-    def list_locations(self):
-        return [
-            NodeLocation('DCAUCKLAND', "RimuHosting Auckland", 'NZ', self),
-            NodeLocation('DCDALLAS', "RimuHosting Dallas", 'US', self),
-            NodeLocation('DCLONDON', "RimuHosting London", 'GB', self),
-            NodeLocation('DCSYDNEY', "RimuHosting Sydney", 'AU', self),
-        ]


Mime
View raw message