You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2013/10/07 13:15:57 UTC

[1/5] git commit: [LIBCLOUD-404]: Add Nephoscale driver.

Updated Branches:
  refs/heads/trunk bf681d8d1 -> 34ec154b1


[LIBCLOUD-404]: Add Nephoscale driver.

Signed-off-by: Tomaz Muraus <to...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/da2fd8d8
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/da2fd8d8
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/da2fd8d8

Branch: refs/heads/trunk
Commit: da2fd8d859b7998bbfd99e4c61de1e62f8dea0e4
Parents: bf681d8
Author: Markos Gogoulos <mg...@unweb.me>
Authored: Mon Sep 30 14:00:58 2013 +0300
Committer: Tomaz Muraus <to...@apache.org>
Committed: Mon Oct 7 12:55:06 2013 +0200

----------------------------------------------------------------------
 libcloud/compute/drivers/nephoscale.py          | 459 +++++++++++++++++++
 libcloud/compute/providers.py                   |   4 +-
 libcloud/compute/types.py                       |   2 +
 libcloud/data/pricing.json                      |  16 +
 .../fixtures/nephoscale/list_images.json        | 243 ++++++++++
 .../compute/fixtures/nephoscale/list_keys.json  |  25 +
 .../fixtures/nephoscale/list_locations.json     |  31 ++
 .../compute/fixtures/nephoscale/list_nodes.json | 161 +++++++
 .../fixtures/nephoscale/list_password_keys.json |  18 +
 .../compute/fixtures/nephoscale/list_sizes.json | 178 +++++++
 .../fixtures/nephoscale/list_ssh_keys.json      |  18 +
 .../fixtures/nephoscale/success_action.json     |  11 +
 libcloud/test/compute/test_nephoscale.py        | 189 ++++++++
 13 files changed, 1354 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/compute/drivers/nephoscale.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/nephoscale.py b/libcloud/compute/drivers/nephoscale.py
new file mode 100644
index 0000000..80dba81
--- /dev/null
+++ b/libcloud/compute/drivers/nephoscale.py
@@ -0,0 +1,459 @@
+# 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.
+
+"""
+NephoScale Cloud driver (http://www.nephoscale.com)
+API documentation: http://docs.nephoscale.com
+Created by Markos Gogoulos (https://mist.io)
+"""
+
+import base64
+import sys
+import string
+import random
+import time
+import os
+import binascii
+
+try:
+    import simplejson as json
+except:
+    import json
+
+from libcloud.utils.py3 import httplib
+from libcloud.utils.py3 import b
+from libcloud.utils.py3 import urlencode
+
+from libcloud.compute.providers import Provider
+from libcloud.compute.base import is_private_subnet
+from libcloud.common.base import JsonResponse, ConnectionUserAndKey
+from libcloud.compute.types import (NodeState, InvalidCredsError,
+                                   LibcloudError)
+from libcloud.compute.base import (Node, NodeDriver, NodeImage, NodeSize,
+                                    NodeLocation)
+
+API_HOST = 'api.nephoscale.com'
+
+NODE_STATE_MAP = {
+    'on': NodeState.RUNNING,
+    'off': NodeState.UNKNOWN,
+    'unknown': NodeState.UNKNOWN,
+}
+
+VALID_RESPONSE_CODES = [httplib.OK, httplib.ACCEPTED, httplib.CREATED,
+                        httplib.NO_CONTENT]
+
+#used in create_node and specifies how many times to get the list of nodes and
+#check if the newly created node is there. This is because when a request is
+#sent to create a node, NephoScale replies with the job id, and not the node
+#itself thus we don't have the ip addresses, that are required in deploy_node
+CONNECT_ATTEMPTS = 10
+
+
+class NodeKey(object):
+    def __init__(self, id, name, public_key=None, key_group=None,
+                 password=None):
+        self.id = id
+        self.name = name
+        self.key_group = key_group
+        self.password = password
+        self.public_key = public_key
+
+    def __repr__(self):
+        return (('<NodeKey: id=%s, name=%s>') %
+                (self.id, self.name))
+
+
+class NephoscaleResponse(JsonResponse):
+    """
+    Nephoscale API Response
+    """
+
+    def parse_error(self):
+        if self.status == httplib.UNAUTHORIZED:
+            raise InvalidCredsError('Authorization Failed')
+        if self.status == httplib.NOT_FOUND:
+            raise Exception("The resource you are looking for is not found.")
+
+        return self.body
+
+    def success(self):
+        return self.status in VALID_RESPONSE_CODES
+
+
+class NephoscaleConnection(ConnectionUserAndKey):
+    """
+    Nephoscale connection class.
+    Authenticates to the API through Basic Authentication
+    with username/password
+    """
+    host = API_HOST
+    responseCls = NephoscaleResponse
+
+    def add_default_headers(self, headers):
+        """
+        Add parameters that are necessary for every request
+        """
+        user_b64 = base64.b64encode(b('%s:%s' % (self.user_id, self.key)))
+        headers['Authorization'] = 'Basic %s' % (user_b64.decode('utf-8'))
+        return headers
+
+
+class NephoscaleNodeDriver(NodeDriver):
+    """
+    Nephoscale node driver class.
+
+    >>> from libcloud.compute.types import Provider
+    >>> from libcloud.compute.providers import get_driver
+    >>> driver = get_driver('nephoscale')
+    >>> conn = driver('nepho_user','nepho_password')
+    >>> conn.list_nodes()
+    """
+
+    type = Provider.NEPHOSCALE
+    api_name = 'nephoscale'
+    name = 'NephoScale'
+    website = 'http://www.nephoscale.com'
+    connectionCls = NephoscaleConnection
+    features = {'create_node': ['ssh_key']}
+
+    def list_locations(self):
+        """
+        List available zones for deployment
+
+        :rtype: ``list`` of :class:`NodeLocation`
+        """
+        result = self.connection.request('/datacenter/zone/').object
+        locations = []
+        for value in result.get('data', []):
+            location = NodeLocation(id=value.get('id'),
+                                    name=value.get('name'),
+                                    country='US',
+                                    driver=self)
+            locations.append(location)
+        return locations
+
+    def list_images(self):
+        """
+        List available images for deployment
+
+        :rtype: ``list`` of :class:`NodeImage`
+        """
+        result = self.connection.request('/image/server/').object
+        images = []
+        for value in result.get('data', []):
+            extra = {'architecture': value.get('architecture'),
+                     'disks': value.get('disks'),
+                     'billable_type': value.get('billable_type'),
+                     'pcpus': value.get('pcpus'),
+                     'cores': value.get('cores'),
+                     'uri': value.get('uri'),
+                     'storage': value.get('storage'),
+            }
+            image = NodeImage(id=value.get('id'),
+                              name=value.get('friendly_name'),
+                              driver=self,
+                              extra=extra)
+            images.append(image)
+        return images
+
+    def list_sizes(self):
+        """
+        List available sizes containing prices
+
+        :rtype: ``list`` of :class:`NodeSize`
+        """
+        result = self.connection.request('/server/type/cloud/').object
+        sizes = []
+        for value in result.get('data', []):
+            value_id = value.get('id')
+            size = NodeSize(id=value_id,
+                            name=value.get('friendly_name'),
+                            ram=value.get('ram'),
+                            disk=value.get('storage'),
+                            bandwidth=None,
+                            price=self._get_size_price(size_id=str(value_id)),
+                            driver=self)
+            sizes.append(size)
+
+        return sorted(sizes, key=lambda k: k.price)
+
+    def list_nodes(self):
+        """
+        List available nodes
+
+        :rtype: ``list`` of :class:`Node`
+        """
+        result = self.connection.request('/server/cloud/').object
+        nodes = [self._to_node(value) for value in result.get('data', [])]
+        return nodes
+
+    def rename_node(self, node, name, hostname=None):
+        """rename a cloud server, optionally specify hostname too"""
+        data = {'name': name}
+        if hostname:
+            data['hostname'] = hostname
+        params = urlencode(data)
+        result = self.connection.request('/server/cloud/%s/' % node.id,
+                                         data=params, method='PUT').object
+        return result.get('response') in VALID_RESPONSE_CODES
+
+    def reboot_node(self, node):
+        """reboot a running node"""
+        result = self.connection.request('/server/cloud/%s/initiator/restart/'
+                                         % node.id, method='POST').object
+        return result.get('response') in VALID_RESPONSE_CODES
+
+    def ex_start_node(self, node):
+        """start a stopped node"""
+        result = self.connection.request('/server/cloud/%s/initiator/start/'
+                                         % node.id, method='POST').object
+        return result.get('response') in VALID_RESPONSE_CODES
+
+    def ex_stop_node(self, node):
+        """stop a running node"""
+        result = self.connection.request('/server/cloud/%s/initiator/stop/'
+                                         % node.id, method='POST').object
+        return result.get('response') in VALID_RESPONSE_CODES
+
+    def destroy_node(self, node):
+        """destroy a node"""
+        result = self.connection.request('/server/cloud/%s/' % node.id,
+                                         method='DELETE').object
+        return result.get('response') in VALID_RESPONSE_CODES
+
+    def ex_list_keypairs(self, ssh=False, password=False, key_group=None):
+        """
+        List available console and server keys
+        There are two types of keys for NephoScale, ssh and password keys.
+        If run without arguments, lists all keys. Otherwise list only
+        ssh keys, or only password keys.
+        Password keys with key_group 4 are console keys. When a server
+        is created, it has two keys, one password or ssh key, and
+        one password console key.
+
+        :keyword ssh: if specified, show ssh keys only (optional)
+        :type    ssh: ``bool``
+
+        :keyword password: if specified, show password keys only (optional)
+        :type    password: ``bool``
+
+        :keyword key_group: if specified, show keys with this key_group only
+                            eg key_group=4 for console password keys (optional)
+        :type    key_group: ``int``
+
+        :rtype: ``list`` of :class:`NodeKey`
+        """
+        if (ssh and password):
+            raise LibcloudError('You can only supply ssh or password. To \
+get all keys call with no arguments')
+        if ssh:
+            result = self.connection.request('/key/sshrsa/').object
+        elif password:
+            result = self.connection.request('/key/password/').object
+        else:
+            result = self.connection.request('/key/').object
+        keys = [self._to_key(value) for value in result.get('data', [])]
+
+        if key_group:
+            keys = [key for key in keys if
+                    key.key_group == key_group]
+        return keys
+
+    def ex_create_keypair(self, name, public_key=None, password=None,
+                       key_group=None):
+        """Creates a key, ssh or password, for server or console
+           The group for the key (key_group) is 1 for Server and 4 for Console
+           Returns the id of the created key
+        """
+        if public_key:
+            if not key_group:
+                key_group = 1
+            data = {
+                'name': name,
+                'public_key': public_key,
+                'key_group': key_group
+
+            }
+            params = urlencode(data)
+            result = self.connection.request('/key/sshrsa/', data=params,
+                                         method='POST').object
+        else:
+            if not key_group:
+                key_group = 4
+            if not password:
+                password = self.random_password()
+                data = {
+                    'name': name,
+                    'password': password,
+                    'key_group': key_group
+                }
+            params = urlencode(data)
+            result = self.connection.request('/key/password/', data=params,
+                                         method='POST').object
+        return result.get('data', {}).get('id', '')
+
+    def ex_delete_keypair(self, key_id, ssh=False):
+        """Delete an ssh key or password given it's id
+        """
+        if ssh:
+            result = self.connection.request('/key/sshrsa/%s/' % key_id,
+                                             method='DELETE').object
+        else:
+            result = self.connection.request('/key/password/%s/' % key_id,
+                                         method='DELETE').object
+        return result.get('response') in VALID_RESPONSE_CODES
+
+    def create_node(self, name, size, image, server_key=None,
+                    console_key=None, zone=None, **kwargs):
+        """Creates the node, and sets the ssh key, console key
+        NephoScale will respond with a 200-200 response after sending a valid
+        request. If nowait=True is specified in the args, we then ask a few
+        times until the server is created and assigned a public IP address,
+        so that deploy_node can be run
+
+        >>> from libcloud.compute.types import Provider
+        >>> from libcloud.compute.providers import get_driver
+        >>> driver = get_driver('nephoscale')
+        >>> conn = driver('nepho_user','nepho_password')
+        >>> conn.list_nodes()
+        >>> name = 'staging-server'
+        >>> size = conn.list_sizes()[0]
+        <NodeSize: id=27, ...name=CS025 - 0.25GB, 10GB, ...>
+        >>> image = conn.list_images()[9]
+        <NodeImage: id=49, name=Linux Ubuntu Server 10.04 LTS 64-bit, ...>
+        >>> server_keys = conn.ex_list_keypairs(key_group=1)[0]
+        <NodeKey: id=71211, name=markos>
+        >>> server_key = conn.ex_list_keypairs(key_group=1)[0].id
+        70867
+        >>> console_keys = conn.ex_list_keypairs(key_group=4)[0]
+        <NodeKey: id=71213, name=mistio28434>
+        >>> console_key = conn.ex_list_keypairs(key_group=4)[0].id
+        70907
+        >>> node = conn.create_node(name=name, size=size, image=image, \
+                console_key=console_key, server_key=server_key)
+
+        We can also create an ssh key, plus a console key and
+        deploy node with them
+        >>> server_key = conn.ex_create_keypair(name, public_key=key)
+        71211
+        >>> console_key = conn.ex_create_keypair(name, key_group=4)
+        71213
+
+        We can increase the number of connect attempts to wait until
+        the node is created, so that deploy_node has ip address to
+        deploy the script
+        We can also specify the location
+        >>> location = conn.list_locations()[0]
+        >>> node = conn.create_node(name=name,
+                                    size=size,
+                                    image=image,
+                                    console_key=console_key,
+                                    server_key=server_key,
+                                    connect_attempts=10,
+                                    nowait=True,
+                                    zone=location.id)
+        """
+        try:
+            hostname = kwargs.get('hostname', name)
+            service_type = size.id
+            image = image.id
+            connect_attempts = int(kwargs.get('connect_attempts',
+                                   CONNECT_ATTEMPTS))
+        except Exception:
+            e = sys.exc_info()[1]
+            raise Exception("Error on create node: %s" % e)
+
+        data = {'name': name,
+                'hostname': hostname,
+                'service_type': service_type,
+                'image': image,
+                'server_key': server_key,
+                'console_key': console_key,
+                'zone': zone
+        }
+
+        params = urlencode(data)
+        try:
+            node = self.connection.request('/server/cloud/', data=params,
+                                           method='POST')
+        except Exception:
+            e = sys.exc_info()[1]
+            raise Exception("Failed to create node %s" % e)
+        node = Node(id='', name=name, state=NodeState.UNKNOWN, public_ips=[],
+                    private_ips=[], driver=self)
+
+        nowait = kwargs.get('ex_wait', False)
+        if not nowait:
+            return node
+        else:
+            #try to get the created node public ips, for use in deploy_node
+            #At this point we don't have the id of the newly created Node,
+            #so search name in nodes
+            created_node = False
+            while connect_attempts > 0:
+                nodes = self.list_nodes()
+                created_node = [c_node for c_node in nodes if
+                                         c_node.name == name]
+                if created_node:
+                    return created_node[0]
+                else:
+                    time.sleep(60)
+                    connect_attempts = connect_attempts - 1
+            return node
+
+    def _to_node(self, data):
+        """Convert node in Node instances
+        """
+
+        state = NODE_STATE_MAP.get(data.get('power_status'), '4')
+        public_ips = []
+        private_ips = []
+        ip_addresses = data.get('ipaddresses', '')
+        #E.g. "ipaddresses": "198.120.14.6, 10.132.60.1"
+        if ip_addresses:
+            for ip in ip_addresses.split(','):
+                ip = ip.replace(' ', '')
+                if is_private_subnet(ip):
+                    private_ips.append(ip)
+                else:
+                    public_ips.append(ip)
+        extra = {
+            'zone_data': data.get('zone'),
+            'zone': data.get('zone', {}).get('name'),
+            'image': data.get('image', {}).get('friendly_name'),
+            'create_time': data.get('create_time'),
+            'network_ports': data.get('network_ports'),
+            'is_console_enabled': data.get('is_console_enabled'),
+            'service_type': data.get('service_type', {}).get('friendly_name'),
+            'hostname': data.get('hostname')
+        }
+
+        node = Node(id=data.get('id'), name=data.get('name'), state=state,
+                    public_ips=public_ips, private_ips=private_ips,
+                    driver=self, extra=extra)
+        return node
+
+    def _to_key(self, data):
+        return NodeKey(id=data.get('id'),
+                      name=data.get('name'),
+                      password=data.get('password'),
+                      key_group=data.get('key_group'),
+                      public_key=data.get('public_key'))
+
+    def random_password(self, size=8):
+        value = os.urandom(size)
+        password = binascii.hexlify(value).decode('ascii')
+        return password[:size]

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/compute/providers.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/providers.py b/libcloud/compute/providers.py
index fbc9c63..32c60d6 100644
--- a/libcloud/compute/providers.py
+++ b/libcloud/compute/providers.py
@@ -126,7 +126,9 @@ DRIVERS = {
     Provider.ABIQUO:
         ('libcloud.compute.drivers.abiquo', 'AbiquoNodeDriver'),
     Provider.DIGITAL_OCEAN:
-        ('libcloud.compute.drivers.digitalocean', 'DigitalOceanNodeDriver')
+        ('libcloud.compute.drivers.digitalocean', 'DigitalOceanNodeDriver'),
+    Provider.NEPHOSCALE:
+        ('libcloud.compute.drivers.nephoscale', 'NephoscaleNodeDriver')
 }
 
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/compute/types.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/types.py b/libcloud/compute/types.py
index 926c750..aefbf5a 100644
--- a/libcloud/compute/types.py
+++ b/libcloud/compute/types.py
@@ -71,6 +71,7 @@ class Provider(object):
     :cvar KTUCLOUD: kt ucloud driver
     :cvar GRIDSPOT: Gridspot driver
     :cvar ABIQUO: Abiquo driver
+    @cvar NEPHOSCALE: NephoScale driver
     """
     DUMMY = 'dummy'
     EC2 = 'ec2_us_east'
@@ -117,6 +118,7 @@ class Provider(object):
     HOSTVIRTUAL = 'hostvirtual'
     ABIQUO = 'abiquo'
     DIGITAL_OCEAN = 'digitalocean'
+    NEPHOSCALE = 'nephoscale'
 
     # Deprecated constants which are still supported
     EC2_US_EAST = 'ec2_us_east'

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/data/pricing.json
----------------------------------------------------------------------
diff --git a/libcloud/data/pricing.json b/libcloud/data/pricing.json
index 905d657..7a9b731 100644
--- a/libcloud/data/pricing.json
+++ b/libcloud/data/pricing.json
@@ -171,6 +171,22 @@
             "m3.2xlarge": 1.40
         },
 
+        "nephoscale" : {
+            "1": 0.60,
+            "3": 0.063,
+            "5": 0.031,
+            "7": 0.125,
+            "9": 0.188,
+            "11": 0.35,
+            "27": 0.0,
+            "46": 0.10,
+            "48": 0.15,
+            "50": 0.28,
+            "52": 0.48,
+            "54": 0.938,
+            "56": 0.75
+        },
+
         "nimbus" : {
             "m1.small": 0.0,
             "m1.large": 0.0,

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/test/compute/fixtures/nephoscale/list_images.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/nephoscale/list_images.json b/libcloud/test/compute/fixtures/nephoscale/list_images.json
new file mode 100644
index 0000000..1ede35d
--- /dev/null
+++ b/libcloud/test/compute/fixtures/nephoscale/list_images.json
@@ -0,0 +1,243 @@
+{
+    "success": true,
+    "total_count": 18,
+    "subcode": 0,
+    "message": "Your request was processed successfully.",
+    "data": [
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux CentOS 5.5 32-bit",
+            "uri": "https://api.nephoscale.com/image/server/3/",
+            "max_memory": 128,
+            "id": 3,
+            "is_default": true,
+            "create_time": "2010-12-20 14:25:36",
+            "architecture": "x86",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux CentOS 5.5 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/5/",
+            "max_memory": 128,
+            "id": 5,
+            "is_default": true,
+            "create_time": "2010-12-20 14:25:36",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Windows Server 2008 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/21/",
+            "max_memory": 128,
+            "id": 21,
+            "is_default": true,
+            "create_time": "2010-12-20 14:25:36",
+            "architecture": "x86_64",
+            "base_type": "windows"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux Debian Server 5.05 32-bit",
+            "uri": "https://api.nephoscale.com/image/server/23/",
+            "max_memory": 128,
+            "id": 23,
+            "is_default": true,
+            "create_time": "2010-12-20 16:51:20",
+            "architecture": "x86",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux Debian Server 5.05 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/25/",
+            "max_memory": 128,
+            "id": 25,
+            "is_default": true,
+            "create_time": "2010-12-20 16:55:42",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Windows Server 2003 Enterprise 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/33/",
+            "max_memory": 128,
+            "id": 33,
+            "is_default": true,
+            "create_time": "2011-03-02 14:20:49",
+            "architecture": "x86_64",
+            "base_type": "windows"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux CentOS 5.7 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/41/",
+            "max_memory": 128,
+            "id": 41,
+            "is_default": true,
+            "create_time": "2011-09-19 17:30:04",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux Ubuntu Server 10.04 LTS 32-bit",
+            "uri": "https://api.nephoscale.com/image/server/43/",
+            "max_memory": 128,
+            "id": 43,
+            "is_default": true,
+            "create_time": "2011-10-01 02:26:17",
+            "architecture": "x86",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux CentOS 5.7 32-bit",
+            "uri": "https://api.nephoscale.com/image/server/45/",
+            "max_memory": 128,
+            "id": 45,
+            "is_default": true,
+            "create_time": "2011-10-05 19:41:30",
+            "architecture": "x86",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux Ubuntu Server 10.04 LTS 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/49/",
+            "max_memory": 128,
+            "id": 49,
+            "is_default": true,
+            "create_time": "2011-10-08 05:01:10",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux Debian Server 6.0.3 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/51/",
+            "max_memory": 128,
+            "id": 51,
+            "is_default": true,
+            "create_time": "2011-10-08 19:54:41",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux Debian 5.0.9 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/55/",
+            "max_memory": 128,
+            "id": 55,
+            "is_default": false,
+            "create_time": "2011-10-13 12:53:36",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux Debian 5.0.9 32-bit",
+            "uri": "https://api.nephoscale.com/image/server/57/",
+            "max_memory": 128,
+            "id": 57,
+            "is_default": false,
+            "create_time": "2011-10-13 12:55:09",
+            "architecture": "x86",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux CentOS 6.2 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/59/",
+            "max_memory": 128,
+            "id": 59,
+            "is_default": true,
+            "create_time": "2011-10-15 17:11:34",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux CentOS 5.8 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/64/",
+            "max_memory": 128,
+            "id": 64,
+            "is_default": true,
+            "create_time": "2012-03-28 19:54:10",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Linux Ubuntu Server 12.04 LTS 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/75/",
+            "max_memory": 128,
+            "id": 75,
+            "is_default": true,
+            "create_time": "2012-05-18 08:41:03",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "cloud",
+            "is_active": true,
+            "friendly_name": "VOD Cloud Storage Proxy (FTP:HTTP)",
+            "uri": "https://api.nephoscale.com/image/server/101/",
+            "max_memory": 128,
+            "id": 101,
+            "is_default": false,
+            "create_time": "2012-08-30 08:49:55",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        },
+        {
+            "max_cpu": 64,
+            "deployable_type": "both",
+            "is_active": true,
+            "friendly_name": "Debian 7.1 64-bit",
+            "uri": "https://api.nephoscale.com/image/server/177/",
+            "max_memory": 128,
+            "id": 177,
+            "is_default": true,
+            "create_time": "2013-09-10 16:12:10",
+            "architecture": "x86_64",
+            "base_type": "linux"
+        }
+    ],
+    "response": 200
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/test/compute/fixtures/nephoscale/list_keys.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/nephoscale/list_keys.json b/libcloud/test/compute/fixtures/nephoscale/list_keys.json
new file mode 100644
index 0000000..f6f9205
--- /dev/null
+++ b/libcloud/test/compute/fixtures/nephoscale/list_keys.json
@@ -0,0 +1,25 @@
+{
+    "success": true,
+    "total_count": 2,
+    "subcode": 0,
+    "message": "Your request was processed successfully.",
+    "data": [
+        {
+            "name": "mistio-ssh",
+            "key_group": 1,
+            "uri": "https://api.nephoscale.com/key/sshrsa/72209/",
+            "key_type": 2,
+            "create_time": "2013-10-02 07:24:37",
+            "id": 72209
+        },
+        {
+            "name": "mistio-testing",
+            "key_group": 4,
+            "uri": "https://api.nephoscale.com/key/password/72211/",
+            "key_type": 1,
+            "create_time": "2013-10-02 07:27:10",
+            "id": 72211
+        }
+    ],
+    "response": 200
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/test/compute/fixtures/nephoscale/list_locations.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/nephoscale/list_locations.json b/libcloud/test/compute/fixtures/nephoscale/list_locations.json
new file mode 100644
index 0000000..952fac4
--- /dev/null
+++ b/libcloud/test/compute/fixtures/nephoscale/list_locations.json
@@ -0,0 +1,31 @@
+{
+    "success": true,
+    "total_count": 2,
+    "subcode": 0,
+    "message": "Your request was processed successfully.",
+    "data": [
+        {
+            "datacenter": {
+                "airport_code": "SJC",
+                "name": "SJC-1",
+                "uri": "https://api.nephoscale.com/datacenter/1/",
+                "id": 1
+            },
+            "uri": "https://api.nephoscale.com/datacenter/zone/86945/",
+            "id": 86945,
+            "name": "SJC-1"
+        },
+        {
+            "datacenter": {
+                "airport_code": "RIC",
+                "name": "RIC-1",
+                "uri": "https://api.nephoscale.com/datacenter/3/",
+                "id": 3
+            },
+            "uri": "https://api.nephoscale.com/datacenter/zone/87729/",
+            "id": 87729,
+            "name": "RIC-1"
+        }
+    ],
+    "response": 200
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/test/compute/fixtures/nephoscale/list_nodes.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/nephoscale/list_nodes.json b/libcloud/test/compute/fixtures/nephoscale/list_nodes.json
new file mode 100644
index 0000000..7fdff6c
--- /dev/null
+++ b/libcloud/test/compute/fixtures/nephoscale/list_nodes.json
@@ -0,0 +1,161 @@
+{
+    "success": true,
+    "total_count": 2,
+    "subcode": 0,
+    "message": "Your request was processed successfully.",
+    "data": [
+        {
+            "server_keys": [
+                {
+                    "key_type": 2,
+                    "key_group": 1,
+                    "id": 71757,
+                    "uri": "https://api.nephoscale.com/key/sshrsa/71157/"
+                }
+            ],
+            "name": "mongodb-staging",
+            "zone": {
+                "uri": "https://api.nephoscale.com/datacenter/zone/88211/",
+                "id": 87729,
+                "name": "RIC-1"
+            },
+            "image": {
+                "max_cpu": 64,
+                "deployable_type": "both",
+                "is_active": true,
+                "friendly_name": "Linux Ubuntu Server 10.04 LTS 64-bit",
+                "uri": "https://api.nephoscale.com/image/server/49/",
+                "max_memory": 128,
+                "id": 49,
+                "is_default": true,
+                "create_time": "2011-10-08 05:01:10",
+                "architecture": "x86_64",
+                "has_agent": true,
+                "base_type": "linux"
+            },
+            "hostname": "mongodb-staging",
+            "podzone": "P1A2",
+            "uri": "https://api.nephoscale.com/server/cloud/87241/",
+            "ipaddresses": "198.89.117.16",
+            "power_status": "on",
+            "create_time": "2013-09-25 07:38:53",
+            "postinit_state": 1,
+            "console_keys": [
+                {
+                    "key_type": 1,
+                    "key_group": 4,
+                    "id": 71761,
+                    "uri": "https://api.nephoscale.com/key/password/71761/"
+                }
+            ],
+            "memory": 512,
+            "service_type": {
+                "sku": {
+                    "name": "CS05",
+                    "description": "Cloud Server 0.5 GB RAM, 1 Core"
+                },
+                "uri": "https://api.nephoscale.com/server/type/cloud/5/",
+                "friendly_name": "CS05 - 0.5GB, 1Core, 25GB",
+                "id": 5,
+                "billable_type": 1
+            },
+            "network_ports": [
+                {
+                    "macaddress": "00:16:3e:06:dc:41",
+                    "devname": "eth0",
+                    "network_domain": {
+                        "domain_type": 0,
+                        "name": "default_public_network_RIC"
+                    }
+                },
+                {
+                    "macaddress": "00:16:3e:06:dc:45",
+                    "devname": "eth1",
+                    "network_domain": {
+                        "domain_type": 1,
+                        "name": "default_private_network_RIC"
+                    }
+                }
+            ],
+            "id": 88241,
+            "is_console_enabled": true
+        },
+        {
+            "server_keys": [
+                {
+                    "key_type": 2,
+                    "key_group": 1,
+                    "id": 72049,
+                    "uri": "https://api.nephoscale.com/key/sshrsa/72049/"
+                }
+            ],
+            "name": "backup-server2",
+            "zone": {
+                "uri": "https://api.nephoscale.com/datacenter/zone/88751/",
+                "id": 87729,
+                "name": "RIC-1"
+            },
+            "image": {
+                "max_cpu": 64,
+                "deployable_type": "both",
+                "is_active": true,
+                "friendly_name": "Linux Debian Server 6.0.3 64-bit",
+                "uri": "https://api.nephoscale.com/image/server/51/",
+                "max_memory": 128,
+                "id": 51,
+                "is_default": true,
+                "create_time": "2011-10-08 19:54:41",
+                "architecture": "x86_64",
+                "has_agent": true,
+                "base_type": "linux"
+            },
+            "hostname": "backup-server2",
+            "podzone": "P1A2",
+            "uri": "https://api.nephoscale.com/server/cloud/88751/",
+            "ipaddresses": "198.89.112.115",
+            "power_status": "on",
+            "create_time": "2013-10-02 05:02:50",
+            "postinit_state": 1,
+            "console_keys": [
+                {
+                    "key_type": 1,
+                    "key_group": 4,
+                    "id": 72165,
+                    "uri": "https://api.nephoscale.com/key/password/72165/"
+                }
+            ],
+            "memory": 512,
+            "service_type": {
+                "sku": {
+                    "name": "CS05",
+                    "description": "Cloud Server 0.5 GB RAM, 1 Core"
+                },
+                "uri": "https://api.nephoscale.com/server/type/cloud/5/",
+                "friendly_name": "CS05 - 0.5GB, 1Core, 25GB",
+                "id": 5,
+                "billable_type": 1
+            },
+            "network_ports": [
+                {
+                    "macaddress": "00:16:3e:06:f5:2f",
+                    "devname": "eth0",
+                    "network_domain": {
+                        "domain_type": 0,
+                        "name": "default_public_network_RIC"
+                    }
+                },
+                {
+                    "macaddress": "00:16:3e:06:f5:33",
+                    "devname": "eth1",
+                    "network_domain": {
+                        "domain_type": 1,
+                        "name": "default_private_network_RIC"
+                    }
+                }
+            ],
+            "id": 88751,
+            "is_console_enabled": true
+        }
+    ],
+    "response": 200
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/test/compute/fixtures/nephoscale/list_password_keys.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/nephoscale/list_password_keys.json b/libcloud/test/compute/fixtures/nephoscale/list_password_keys.json
new file mode 100644
index 0000000..ca3c629
--- /dev/null
+++ b/libcloud/test/compute/fixtures/nephoscale/list_password_keys.json
@@ -0,0 +1,18 @@
+{
+    "success": true,
+    "total_count": 1,
+    "subcode": 0,
+    "message": "Your request was processed successfully.",
+    "data": [
+        {
+            "name": "mistio-testing",
+            "key_group": 4,
+            "uri": "https://api.nephoscale.com/key/password/72211/",
+            "key_type": 1,
+            "create_time": "2013-10-02 07:27:10",
+            "password": "23d493j5",
+            "id": 72211
+        }
+    ],
+    "response": 200
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/test/compute/fixtures/nephoscale/list_sizes.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/nephoscale/list_sizes.json b/libcloud/test/compute/fixtures/nephoscale/list_sizes.json
new file mode 100644
index 0000000..c6d89f3
--- /dev/null
+++ b/libcloud/test/compute/fixtures/nephoscale/list_sizes.json
@@ -0,0 +1,178 @@
+{
+    "success": true,
+    "total_count": 13,
+    "subcode": 0,
+    "message": "Your request was processed successfully.",
+    "data": [
+        {
+            "sku": {
+                "name": "CS16.16",
+                "description": "Cloud Server 16 GB RAM, 16 Cores"
+            },
+            "storage": 800,
+            "ram": 16384,
+            "friendly_name": "CS16.16 - 16GB, 16Core, 800GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/1/",
+            "vcpus": 16,
+            "id": 1,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS1",
+                "description": "Cloud Server 1 GB RAM, 1 Core"
+            },
+            "storage": 50,
+            "ram": 1024,
+            "friendly_name": "CS1 - 1GB, 1Core, 50GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/3/",
+            "vcpus": 1,
+            "id": 3,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS05",
+                "description": "Cloud Server 0.5 GB RAM, 1 Core"
+            },
+            "storage": 25,
+            "ram": 512,
+            "friendly_name": "CS05 - 0.5GB, 1Core, 25GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/5/",
+            "vcpus": 1,
+            "id": 5,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS2.2",
+                "description": "Cloud Server 2 GB RAM, 2 Cores"
+            },
+            "storage": 100,
+            "ram": 2048,
+            "friendly_name": "CS2.2 - 2GB, 2Core, 100GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/7/",
+            "vcpus": 2,
+            "id": 7,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS4.4",
+                "description": "Cloud Server 4 GB RAM, 4 Cores"
+            },
+            "storage": 200,
+            "ram": 4096,
+            "friendly_name": "CS4.4 - 4GB, 4Core, 200GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/9/",
+            "vcpus": 4,
+            "id": 9,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS8.8",
+                "description": "Cloud Server 8 GB RAM, 8 Cores"
+            },
+            "storage": 400,
+            "ram": 8192,
+            "friendly_name": "CS8.8 - 8GB, 8Core, 400GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/11/",
+            "vcpus": 8,
+            "id": 11,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS025",
+                "description": "Cloud Server 0.25 GB RAM"
+            },
+            "storage": 15,
+            "ram": 256,
+            "friendly_name": "CS025 - 0.25GB, 10GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/27/",
+            "vcpus": 1,
+            "id": 27,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS2.1",
+                "description": "Cloud Server 2 GB RAM, 1 Core"
+            },
+            "storage": 75,
+            "ram": 2048,
+            "friendly_name": "CS2.1 - 2GB, 1Core, 75GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/46/",
+            "vcpus": 1,
+            "id": 46,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS4.2",
+                "description": "Cloud Server 4 GB RAM, 2 Cores"
+            },
+            "storage": 150,
+            "ram": 4096,
+            "friendly_name": "CS4.2 - 4GB, 2Core, 150GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/48/",
+            "vcpus": 2,
+            "id": 48,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS8.4",
+                "description": "Cloud Server 8 GB RAM, 4 Cores"
+            },
+            "storage": 300,
+            "ram": 8192,
+            "friendly_name": "CS8.4 - 8GB, 4Core, 300GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/50/",
+            "vcpus": 4,
+            "id": 50,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS16.8",
+                "description": "Cloud Server 16 GB RAM, 8 Cores"
+            },
+            "storage": 600,
+            "ram": 16384,
+            "friendly_name": "CS16.8 - 16GB, 8Core, 600GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/52/",
+            "vcpus": 8,
+            "id": 52,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS32.16",
+                "description": "Cloud Server 32 GB RAM, 16 Cores"
+            },
+            "storage": 1200,
+            "ram": 32768,
+            "friendly_name": "CS32.16 - 32GB, 16Core, 1200GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/54/",
+            "vcpus": 16,
+            "id": 54,
+            "billable_type": 1
+        },
+        {
+            "sku": {
+                "name": "CS32.8",
+                "description": "Cloud Server 32 GB RAM, 8 Cores"
+            },
+            "storage": 1000,
+            "ram": 32768,
+            "friendly_name": "CS32.8 - 32GB, 8Core, 1000GB",
+            "uri": "https://api.nephoscale.com/server/type/cloud/56/",
+            "vcpus": 8,
+            "id": 56,
+            "billable_type": 1
+        }
+    ],
+    "response": 200
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/test/compute/fixtures/nephoscale/list_ssh_keys.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/nephoscale/list_ssh_keys.json b/libcloud/test/compute/fixtures/nephoscale/list_ssh_keys.json
new file mode 100644
index 0000000..dc83a8f
--- /dev/null
+++ b/libcloud/test/compute/fixtures/nephoscale/list_ssh_keys.json
@@ -0,0 +1,18 @@
+{
+    "success": true,
+    "total_count": 1,
+    "subcode": 0,
+    "message": "Your request was processed successfully.",
+    "data": [
+        {
+            "public_key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBs+gQwoeFNa+4pYz2AKz5Op7EqrzeP3YsyTKxx7P9gt4aSt5w8Z+lRn3p3CVG+th5i6lZqOxWgCZ1kp2KEKNbSsA2HWl3OwkY8IqHGSEeMrF+3A2Ncz88kUIAWzCswxPY4uqb/yA4EzEQDk7PJj7Q1DruObhOm7qyHT40n2KJ3TqHJQlV9XE3RcXSaQcwUt0YFXFMx8wkgy0NKqqSiQuH8RofyfnOABEzKAARGbcQjZWxh2ITzUmwMxUCBa0X5wvblgcE6/pRZN5Xq6NQr2XEU5Z48+mLy6asdasdwrM0v10Y7ojDL/TosK/8T5+d5yaRsvtBlBstDZhNWY31n5iCLxx user@mistio",
+            "name": "mistio-ssh",
+            "key_group": 1,
+            "uri": "https://api.nephoscale.com/key/sshrsa/72209/",
+            "key_type": 2,
+            "create_time": "2013-10-02 07:24:37",
+            "id": 72209
+        }
+    ],
+    "response": 200
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/test/compute/fixtures/nephoscale/success_action.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/nephoscale/success_action.json b/libcloud/test/compute/fixtures/nephoscale/success_action.json
new file mode 100644
index 0000000..62db155
--- /dev/null
+++ b/libcloud/test/compute/fixtures/nephoscale/success_action.json
@@ -0,0 +1,11 @@
+{
+    "subcode": 0,
+    "message": "Your request was processed successfully.",
+    "data": {
+        "id": 141229,
+        "resource_type": "/job",
+        "uri": "https://api.nephoscale.com/job/141229/"
+    },
+    "response": 202,
+    "success": true
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/da2fd8d8/libcloud/test/compute/test_nephoscale.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_nephoscale.py b/libcloud/test/compute/test_nephoscale.py
new file mode 100644
index 0000000..7a83808
--- /dev/null
+++ b/libcloud/test/compute/test_nephoscale.py
@@ -0,0 +1,189 @@
+# 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.
+#
+#Created by Markos Gogoulos (https://mist.io)
+#
+
+import sys
+import unittest
+from libcloud.utils.py3 import httplib
+
+from libcloud.compute.drivers.nephoscale import NephoscaleNodeDriver
+from libcloud.compute.base import Node
+
+from libcloud.test import MockHttp
+from libcloud.test.compute import TestCaseMixin
+from libcloud.test.file_fixtures import ComputeFileFixtures
+from libcloud.common.types import InvalidCredsError, LibcloudError
+
+
+class NephoScaleTest(unittest.TestCase, TestCaseMixin):
+    def setUp(self):
+        NephoscaleNodeDriver.connectionCls.conn_classes = (
+                                  None, NephoscaleMockHttp)
+        self.driver = NephoscaleNodeDriver('user', 'password')
+
+    def test_list_sizes(self):
+        sizes = self.driver.list_sizes()
+        self.assertEqual(len(sizes), 13)
+        for size in sizes:
+            self.assertEqual(type(size.disk), int)
+            self.assertEqual(type(size.ram), int)
+
+    def test_list_images(self):
+        images = self.driver.list_images()
+        self.assertEqual(len(images), 18)
+        for image in images:
+            arch = image.extra.get('architecture')
+            self.assertTrue(arch.startswith('x86'))
+
+    def test_list_locations(self):
+        locations = self.driver.list_locations()
+        self.assertEqual(len(locations), 2)
+        self.assertEqual(locations[0].name, "SJC-1")
+
+    def test_list_nodes(self):
+        nodes = self.driver.list_nodes()
+        self.assertEqual(len(nodes), 2)
+        self.assertEqual(nodes[0].extra.get('zone'), 'RIC-1')
+        self.assertEqual(nodes[0].name, 'mongodb-staging')
+        self.assertEqual(nodes[0].extra.get('service_type'),
+                         'CS05 - 0.5GB, 1Core, 25GB')
+
+    def test_list_keys(self):
+        keys = self.driver.ex_list_keypairs()
+        self.assertEqual(len(keys), 2)
+        self.assertEqual(keys[0].name, 'mistio-ssh')
+
+    def test_list_ssh_keys(self):
+        ssh_keys = self.driver.ex_list_keypairs(ssh=True)
+        self.assertEqual(len(ssh_keys), 1)
+        self.assertTrue(ssh_keys[0].public_key.startswith('ssh-rsa'))
+
+    def test_list_password_keys(self):
+        password_keys = self.driver.ex_list_keypairs(password=True)
+        self.assertEqual(len(password_keys), 1)
+        self.assertEquals(password_keys[0].password, '23d493j5')
+
+    def test_reboot_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.reboot_node(node)
+        self.assertTrue(result)
+
+    def test_destroy_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.destroy_node(node)
+        self.assertTrue(result)
+
+    def test_stop_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_stop_node(node)
+        self.assertTrue(result)
+
+    def test_start_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.ex_start_node(node)
+        self.assertTrue(result)
+
+    def test_rename_node(self):
+        node = self.driver.list_nodes()[0]
+        result = self.driver.rename_node(node, 'new-name')
+        self.assertTrue(result)
+
+    def test_create_node(self):
+        name = 'mongodb-staging'
+        size = self.driver.list_sizes()[0]
+        image = self.driver.list_images()[3]
+        node = self.driver.create_node(name=name,
+                                       size=size,
+                                       nowait=True,
+                                       image=image)
+        self.assertEqual(node.name, 'mongodb-staging')
+
+    def test_create_node_no_name(self):
+        size = self.driver.list_sizes()[0]
+        image = self.driver.list_images()[3]
+        self.assertRaises(TypeError, self.driver.create_node, size=size,
+                          image=image)
+
+    def test_delete_ssh_keys(self):
+        key = self.driver.ex_delete_keypair(key_id=72209, ssh=True)
+
+    def test_delete_password_keys(self):
+        key = self.driver.ex_delete_keypair(key_id=72211)
+
+
+class NephoscaleMockHttp(MockHttp):
+    fixtures = ComputeFileFixtures('nephoscale')
+
+    def _server_type_cloud(self, method, url, body, headers):
+        body = self.fixtures.load('list_sizes.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _server_cloud(self, method, url, body, headers):
+        if method == 'POST':
+            body = self.fixtures.load('success_action.json')
+        else:
+            body = self.fixtures.load('list_nodes.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _image_server(self, method, url, body, headers):
+        body = self.fixtures.load('list_images.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _datacenter_zone(self, method, url, body, headers):
+        body = self.fixtures.load('list_locations.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _key(self, method, url, body, headers):
+        body = self.fixtures.load('list_keys.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _key_sshrsa(self, method, url, body, headers):
+        body = self.fixtures.load('list_ssh_keys.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _key_password(self, method, url, body, headers):
+        body = self.fixtures.load('list_password_keys.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _server_cloud_88241(self, method, url, body, headers):
+        body = self.fixtures.load('success_action.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _server_cloud_88241_initiator_restart(self, method, url, body,
+                                              headers):
+        body = self.fixtures.load('success_action.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _server_cloud_88241_initiator_start(self, method, url, body, headers):
+        body = self.fixtures.load('success_action.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _server_cloud_88241_initiator_stop(self, method, url, body, headers):
+        body = self.fixtures.load('success_action.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _key_password_72211(self, method, url, body, headers):
+        body = self.fixtures.load('success_action.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _key_sshrsa_72209(self, method, url, body, headers):
+        body = self.fixtures.load('success_action.json')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())


[5/5] git commit: pep8 fixes in the tests.

Posted by to...@apache.org.
pep8 fixes in the tests.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/34ec154b
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/34ec154b
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/34ec154b

Branch: refs/heads/trunk
Commit: 34ec154b125c9a7cf1717131dfe938fcf07876aa
Parents: 0ece13d
Author: Tomaz Muraus <to...@apache.org>
Authored: Mon Oct 7 13:10:45 2013 +0200
Committer: Tomaz Muraus <to...@apache.org>
Committed: Mon Oct 7 13:10:45 2013 +0200

----------------------------------------------------------------------
 libcloud/test/compute/test_nephoscale.py | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/34ec154b/libcloud/test/compute/test_nephoscale.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_nephoscale.py b/libcloud/test/compute/test_nephoscale.py
index 7a83808..cc3636a 100644
--- a/libcloud/test/compute/test_nephoscale.py
+++ b/libcloud/test/compute/test_nephoscale.py
@@ -21,18 +21,16 @@ import unittest
 from libcloud.utils.py3 import httplib
 
 from libcloud.compute.drivers.nephoscale import NephoscaleNodeDriver
-from libcloud.compute.base import Node
 
 from libcloud.test import MockHttp
 from libcloud.test.compute import TestCaseMixin
 from libcloud.test.file_fixtures import ComputeFileFixtures
-from libcloud.common.types import InvalidCredsError, LibcloudError
 
 
 class NephoScaleTest(unittest.TestCase, TestCaseMixin):
     def setUp(self):
         NephoscaleNodeDriver.connectionCls.conn_classes = (
-                                  None, NephoscaleMockHttp)
+            NephoscaleMockHttp, NephoscaleMockHttp)
         self.driver = NephoscaleNodeDriver('user', 'password')
 
     def test_list_sizes(self):
@@ -119,10 +117,10 @@ class NephoScaleTest(unittest.TestCase, TestCaseMixin):
                           image=image)
 
     def test_delete_ssh_keys(self):
-        key = self.driver.ex_delete_keypair(key_id=72209, ssh=True)
+        self.assertTrue(self.driver.ex_delete_keypair(key_id=72209, ssh=True))
 
     def test_delete_password_keys(self):
-        key = self.driver.ex_delete_keypair(key_id=72211)
+        self.assertTrue(self.driver.ex_delete_keypair(key_id=72211))
 
 
 class NephoscaleMockHttp(MockHttp):


[2/5] git commit: Fix pep8 issues.

Posted by to...@apache.org.
Fix pep8 issues.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/4bdf8462
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/4bdf8462
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/4bdf8462

Branch: refs/heads/trunk
Commit: 4bdf8462a846579270f279e1c90feb623e985ba9
Parents: da2fd8d
Author: Tomaz Muraus <to...@apache.org>
Authored: Mon Oct 7 13:07:06 2013 +0200
Committer: Tomaz Muraus <to...@apache.org>
Committed: Mon Oct 7 13:07:06 2013 +0200

----------------------------------------------------------------------
 libcloud/compute/drivers/nephoscale.py | 51 ++++++++++++-----------------
 1 file changed, 21 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/4bdf8462/libcloud/compute/drivers/nephoscale.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/nephoscale.py b/libcloud/compute/drivers/nephoscale.py
index 80dba81..5d532c2 100644
--- a/libcloud/compute/drivers/nephoscale.py
+++ b/libcloud/compute/drivers/nephoscale.py
@@ -21,17 +21,10 @@ Created by Markos Gogoulos (https://mist.io)
 
 import base64
 import sys
-import string
-import random
 import time
 import os
 import binascii
 
-try:
-    import simplejson as json
-except:
-    import json
-
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import b
 from libcloud.utils.py3 import urlencode
@@ -40,9 +33,9 @@ from libcloud.compute.providers import Provider
 from libcloud.compute.base import is_private_subnet
 from libcloud.common.base import JsonResponse, ConnectionUserAndKey
 from libcloud.compute.types import (NodeState, InvalidCredsError,
-                                   LibcloudError)
+                                    LibcloudError)
 from libcloud.compute.base import (Node, NodeDriver, NodeImage, NodeSize,
-                                    NodeLocation)
+                                   NodeLocation)
 
 API_HOST = 'api.nephoscale.com'
 
@@ -115,7 +108,6 @@ class NephoscaleNodeDriver(NodeDriver):
     """
     Nephoscale node driver class.
 
-    >>> from libcloud.compute.types import Provider
     >>> from libcloud.compute.providers import get_driver
     >>> driver = get_driver('nephoscale')
     >>> conn = driver('nepho_user','nepho_password')
@@ -161,7 +153,7 @@ class NephoscaleNodeDriver(NodeDriver):
                      'cores': value.get('cores'),
                      'uri': value.get('uri'),
                      'storage': value.get('storage'),
-            }
+                     }
             image = NodeImage(id=value.get('id'),
                               name=value.get('friendly_name'),
                               driver=self,
@@ -273,7 +265,7 @@ get all keys call with no arguments')
         return keys
 
     def ex_create_keypair(self, name, public_key=None, password=None,
-                       key_group=None):
+                          key_group=None):
         """Creates a key, ssh or password, for server or console
            The group for the key (key_group) is 1 for Server and 4 for Console
            Returns the id of the created key
@@ -289,7 +281,7 @@ get all keys call with no arguments')
             }
             params = urlencode(data)
             result = self.connection.request('/key/sshrsa/', data=params,
-                                         method='POST').object
+                                             method='POST').object
         else:
             if not key_group:
                 key_group = 4
@@ -302,7 +294,7 @@ get all keys call with no arguments')
                 }
             params = urlencode(data)
             result = self.connection.request('/key/password/', data=params,
-                                         method='POST').object
+                                             method='POST').object
         return result.get('data', {}).get('id', '')
 
     def ex_delete_keypair(self, key_id, ssh=False):
@@ -313,7 +305,7 @@ get all keys call with no arguments')
                                              method='DELETE').object
         else:
             result = self.connection.request('/key/password/%s/' % key_id,
-                                         method='DELETE').object
+                                             method='DELETE').object
         return result.get('response') in VALID_RESPONSE_CODES
 
     def create_node(self, name, size, image, server_key=None,
@@ -324,7 +316,6 @@ get all keys call with no arguments')
         times until the server is created and assigned a public IP address,
         so that deploy_node can be run
 
-        >>> from libcloud.compute.types import Provider
         >>> from libcloud.compute.providers import get_driver
         >>> driver = get_driver('nephoscale')
         >>> conn = driver('nepho_user','nepho_password')
@@ -347,7 +338,7 @@ get all keys call with no arguments')
 
         We can also create an ssh key, plus a console key and
         deploy node with them
-        >>> server_key = conn.ex_create_keypair(name, public_key=key)
+        >>> server_key = conn.ex_create_keypair(name, public_key='123')
         71211
         >>> console_key = conn.ex_create_keypair(name, key_group=4)
         71213
@@ -358,13 +349,13 @@ get all keys call with no arguments')
         We can also specify the location
         >>> location = conn.list_locations()[0]
         >>> node = conn.create_node(name=name,
-                                    size=size,
-                                    image=image,
-                                    console_key=console_key,
-                                    server_key=server_key,
-                                    connect_attempts=10,
-                                    nowait=True,
-                                    zone=location.id)
+            ...                     size=size,
+            ...                     image=image,
+            ...                     console_key=console_key,
+            ...                     server_key=server_key,
+            ...                     connect_attempts=10,
+            ...                     nowait=True,
+            ...                     zone=location.id)
         """
         try:
             hostname = kwargs.get('hostname', name)
@@ -383,7 +374,7 @@ get all keys call with no arguments')
                 'server_key': server_key,
                 'console_key': console_key,
                 'zone': zone
-        }
+                }
 
         params = urlencode(data)
         try:
@@ -406,7 +397,7 @@ get all keys call with no arguments')
             while connect_attempts > 0:
                 nodes = self.list_nodes()
                 created_node = [c_node for c_node in nodes if
-                                         c_node.name == name]
+                                c_node.name == name]
                 if created_node:
                     return created_node[0]
                 else:
@@ -448,10 +439,10 @@ get all keys call with no arguments')
 
     def _to_key(self, data):
         return NodeKey(id=data.get('id'),
-                      name=data.get('name'),
-                      password=data.get('password'),
-                      key_group=data.get('key_group'),
-                      public_key=data.get('public_key'))
+                       name=data.get('name'),
+                       password=data.get('password'),
+                       key_group=data.get('key_group'),
+                       public_key=data.get('public_key'))
 
     def random_password(self, size=8):
         value = os.urandom(size)


[3/5] git commit: Remove try / except and raise which masks a more specific exception.

Posted by to...@apache.org.
Remove try / except and raise which masks a more specific exception.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/9bbf21c1
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/9bbf21c1
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/9bbf21c1

Branch: refs/heads/trunk
Commit: 9bbf21c1284180e783eea4573ce188c29782bca5
Parents: 4bdf846
Author: Tomaz Muraus <to...@apache.org>
Authored: Mon Oct 7 13:08:12 2013 +0200
Committer: Tomaz Muraus <to...@apache.org>
Committed: Mon Oct 7 13:08:12 2013 +0200

----------------------------------------------------------------------
 libcloud/compute/drivers/nephoscale.py | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/9bbf21c1/libcloud/compute/drivers/nephoscale.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/nephoscale.py b/libcloud/compute/drivers/nephoscale.py
index 5d532c2..dc100ce 100644
--- a/libcloud/compute/drivers/nephoscale.py
+++ b/libcloud/compute/drivers/nephoscale.py
@@ -357,15 +357,11 @@ get all keys call with no arguments')
             ...                     nowait=True,
             ...                     zone=location.id)
         """
-        try:
-            hostname = kwargs.get('hostname', name)
-            service_type = size.id
-            image = image.id
-            connect_attempts = int(kwargs.get('connect_attempts',
-                                   CONNECT_ATTEMPTS))
-        except Exception:
-            e = sys.exc_info()[1]
-            raise Exception("Error on create node: %s" % e)
+        hostname = kwargs.get('hostname', name)
+        service_type = size.id
+        image = image.id
+        connect_attempts = int(kwargs.get('connect_attempts',
+                               CONNECT_ATTEMPTS))
 
         data = {'name': name,
                 'hostname': hostname,


[4/5] git commit: Updat docstring.

Posted by to...@apache.org.
Updat docstring.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/0ece13d2
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/0ece13d2
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/0ece13d2

Branch: refs/heads/trunk
Commit: 0ece13d2db28b0d42239f17c325cfa644c50f1c8
Parents: 9bbf21c
Author: Tomaz Muraus <to...@apache.org>
Authored: Mon Oct 7 13:09:11 2013 +0200
Committer: Tomaz Muraus <to...@apache.org>
Committed: Mon Oct 7 13:09:11 2013 +0200

----------------------------------------------------------------------
 libcloud/pricing.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/0ece13d2/libcloud/pricing.py
----------------------------------------------------------------------
diff --git a/libcloud/pricing.py b/libcloud/pricing.py
index a4e9747..5e4cb89 100644
--- a/libcloud/pricing.py
+++ b/libcloud/pricing.py
@@ -133,7 +133,7 @@ def get_size_price(driver_type, driver_name, size_id):
     :param size_id: Unique size ID (can be an integer or a string - depends on
                     the driver)
 
-    :rtype: ``int``
+    :rtype: ``float``
     :return: Size price.
     """
     pricing = get_pricing(driver_type=driver_type, driver_name=driver_name)