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/02/01 23:52:03 UTC

svn commit: r1441655 - in /libcloud/trunk: ./ libcloud/compute/drivers/ libcloud/test/compute/ libcloud/test/compute/fixtures/softlayer/

Author: tomaz
Date: Fri Feb  1 22:52:01 2013
New Revision: 1441655

URL: http://svn.apache.org/viewvc?rev=1441655&view=rev
Log:
Fix Softlayer driver and make sure all the code is up to date and works
with the latest version of the actual Softlayer deployment (v3).

Contributed by Kevin McDonald, part of LIBCLOUD-287.

Added:
    libcloud/trunk/libcloud/test/compute/fixtures/softlayer/empty.xml
    libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObject.xml
    libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml
    libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject.xml
Modified:
    libcloud/trunk/CHANGES
    libcloud/trunk/libcloud/compute/drivers/softlayer.py
    libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests.xml
    libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getDatacenters.xml
    libcloud/trunk/libcloud/test/compute/test_softlayer.py

Modified: libcloud/trunk/CHANGES
URL: http://svn.apache.org/viewvc/libcloud/trunk/CHANGES?rev=1441655&r1=1441654&r2=1441655&view=diff
==============================================================================
--- libcloud/trunk/CHANGES (original)
+++ libcloud/trunk/CHANGES Fri Feb  1 22:52:01 2013
@@ -122,6 +122,11 @@ Changes with Apache Libcloud in developm
      relative path for the script argument. (LIBCLOUD-278)
      [Jaume Devesa]
 
+   - Fix Softlayer driver and make sure all the code is up to date and works
+     with the latest version of the actual Softlayer deployment (v3).
+     (LIBCLOUD-287)
+     [Kevin McDonald]
+
   *) Storage
 
     - Add a new local storage driver.

Modified: libcloud/trunk/libcloud/compute/drivers/softlayer.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/softlayer.py?rev=1441655&r1=1441654&r2=1441655&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/softlayer.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/softlayer.py Fri Feb  1 22:52:01 2013
@@ -29,9 +29,18 @@ from libcloud.compute.base import NodeDr
     NodeImage
 
 DATACENTERS = {
+    'hou02': {'country': 'US'},
     'sea01': {'country': 'US'},
     'wdc01': {'country': 'US'},
-    'dal01': {'country': 'US'}
+    'dal01': {'country': 'US'},
+    'dal02': {'country': 'US'},
+    'dal04': {'country': 'US'},
+    'dal05': {'country': 'US'},
+    'dal06': {'country': 'US'},
+    'dal07': {'country': 'US'},
+    'sjc01': {'country': 'US'},
+    'sng01': {'country': 'SG'},
+    'ams01': {'country': 'NL'},
 }
 
 NODE_STATE_MAP = {
@@ -40,113 +49,45 @@ NODE_STATE_MAP = {
     'PAUSED': NodeState.TERMINATED,
 }
 
-DEFAULT_PACKAGE = 46
-
-SL_IMAGES = [
-    {'id': 1684, 'name': 'CentOS 5 - Minimal Install (32 bit)'},
-    {'id': 1685, 'name': 'CentOS 5 - Minimal Install (64 bit)'},
-    {'id': 1686, 'name': 'CentOS 5 - LAMP Install (32 bit)'},
-    {'id': 1687, 'name': 'CentOS 5 - LAMP Install (64 bit)'},
-    {'id': 1688,
-     'name': 'Red Hat Enterprise Linux 5 - Minimal Install (32 bit)'},
-    {'id': 1689,
-     'name': 'Red Hat Enterprise Linux 5 - Minimal Install (64 bit)'},
-    {'id': 1690, 'name': 'Red Hat Enterprise Linux 5 - LAMP Install (32 bit)'},
-    {'id': 1691, 'name': 'Red Hat Enterprise Linux 5 - LAMP Install (64 bit)'},
-    {'id': 1692,
-     'name': 'Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (32 bit)'},
-    {'id': 1693,
-     'name': 'Ubuntu Linux 8 LTS Hardy Heron - Minimal Install (64 bit)'},
-    {'id': 1694,
-     'name': 'Ubuntu Linux 8 LTS Hardy Heron - LAMP Install (32 bit)'},
-    {'id': 1695,
-     'name': 'Ubuntu Linux 8 LTS Hardy Heron - LAMP Install (64 bit)'},
-    {'id': 1696,
-     'name': 'Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (32 bit)'},
-    {'id': 1697,
-     'name': 'Debian GNU/Linux 5.0 Lenny/Stable - Minimal Install (64 bit)'},
-    {'id': 1698,
-     'name': 'Debian GNU/Linux 5.0 Lenny/Stable - LAMP Install (32 bit)'},
-    {'id': 1699,
-     'name': 'Debian GNU/Linux 5.0 Lenny/Stable - LAMP Install (64 bit)'},
-    {'id': 1700, 'name': 'Windows Server 2003 Standard SP2 with R2 (32 bit)'},
-    {'id': 1701, 'name': 'Windows Server 2003 Standard SP2 with R2 (64 bit)'},
-    {'id': 1703,
-     'name': 'Windows Server 2003 Enterprise SP2 with R2 (64 bit)'},
-    {'id': 1705, 'name': 'Windows Server 2008 Standard Edition (64bit)'},
-    {'id': 1715, 'name': 'Windows Server 2003 Datacenter SP2 (64 bit)'},
-    {'id': 1716, 'name': 'Windows Server 2003 Datacenter SP2 (32 bit)'},
-    {'id': 1742, 'name': 'Windows Server 2008 Standard Edition SP2 (32bit)'},
-    {'id': 1752, 'name': 'Windows Server 2008 Standard Edition SP2 (64bit)'},
-    {'id': 1756, 'name': 'Windows Server 2008 Enterprise Edition SP2 (32bit)'},
-    {'id': 1761, 'name': 'Windows Server 2008 Enterprise Edition SP2 (64bit)'},
-    {'id': 1766, 'name': 'Windows Server 2008 Datacenter Edition SP2 (32bit)'},
-    {'id': 1770, 'name': 'Windows Server 2008 Datacenter Edition SP2 (64bit)'},
-    {'id': 1857, 'name': 'Windows Server 2008 R2 Standard Edition (64bit)'},
-    {'id': 1860, 'name': 'Windows Server 2008 R2 Enterprise Edition (64bit)'},
-    {'id': 1863, 'name': 'Windows Server 2008 R2 Datacenter Edition (64bit)'},
-]
-
-"""
-The following code snippet will print out all available "prices"
-    mask = { 'items': '' }
-    res = self.connection.request(
-        "SoftLayer_Product_Package",
-        "getObject",
-        res,
-        id=46,
-        object_mask=mask
-    )
-
-    from pprint import pprint; pprint(res)
-"""
-SL_TEMPLATES = {
-    'sl1': {
-        'imagedata': {
-            'name': '2 x 2.0 GHz, 1GB ram, 100GB',
-            'ram': 1024,
-            'disk': 100,
-            'bandwidth': None
-        },
-        'prices': [
-            {'id': 1644},  # 1 GB
-            {'id': 1639},  # 100 GB (SAN)
-            {'id': 1963},  # Private 2 x 2.0 GHz Cores
-            {'id': 21},  # 1 IP Address
-            {'id': 55},  # Host Ping
-            {'id': 58},  # Automated Notification
-            {'id': 1800},  # 0 GB Bandwidth
-            {'id': 57},  # Email and Ticket
-            {'id': 274},  # 1000 Mbps Public & Private Networks
-            {'id': 905},  # Reboot / Remote Console
-            {'id': 418},  # Nessus Vulnerability Assessment & Reporting
-            {'id': 420},  # Unlimited SSL VPN Users & 1 PPTP VPN User per account
-        ],
-    },
-    'sl2': {
-        'imagedata': {
-            'name': '2 x 2.0 GHz, 4GB ram, 350GB',
-            'ram': 4096,
-            'disk': 350,
-            'bandwidth': None
-        },
-        'prices': [
-            {'id': 1646},  # 4 GB
-            {'id': 1639},  # 100 GB (SAN) - This is the only available "First Disk"
-            {'id': 1638},  # 250 GB (SAN)
-            {'id': 1963},  # Private 2 x 2.0 GHz Cores
-            {'id': 21},  # 1 IP Address
-            {'id': 55},  # Host Ping
-            {'id': 58},  # Automated Notification
-            {'id': 1800},  # 0 GB Bandwidth
-            {'id': 57},  # Email and Ticket
-            {'id': 274},  # 1000 Mbps Public & Private Networks
-            {'id': 905},  # Reboot / Remote Console
-            {'id': 418},  # Nessus Vulnerability Assessment & Reporting
-            {'id': 420},  # Unlimited SSL VPN Users & 1 PPTP VPN User per account
-        ],
-    }
-}
+SL_BASE_TEMPLATES = [
+    {
+        'name': '1 CPU, 1GB ram, 25GB',
+        'ram': 1024,
+        'disk': 25,
+        'cpus': 1,
+    }, {
+        'name': '1 CPU, 1GB ram, 100GB',
+        'ram': 1024,
+        'disk': 100,
+        'cpus': 1,
+    }, {
+        'name': '2 CPU, 2GB ram, 100GB',
+        'ram': 4 * 1024,
+        'disk': 100,
+        'cpus': 2,
+    }, {
+        'name': '4 CPU, 4GB ram, 100GB',
+        'ram': 4 * 1024,
+        'disk': 100,
+        'cpus': 4,
+    }, {
+        'name': '8 CPU, 8GB ram, 100GB',
+        'ram': 8 * 1024,
+        'disk': 100,
+        'cpus': 8,
+    }]
+
+SL_TEMPLATES = {}
+for i, template in enumerate(SL_BASE_TEMPLATES):
+    # Add local disk templates
+    local = template.copy()
+    local['local_disk'] = True
+    SL_TEMPLATES['sl%s_local_disk' % (i + 1,)] = local
+
+    # Add san disk templates
+    san = template.copy()
+    san['local_disk'] = False
+    SL_TEMPLATES['sl%s_san_disk' % (i + 1,)] = san
 
 
 class SoftLayerException(LibcloudError):
@@ -168,17 +109,17 @@ class SoftLayerProxy(xmlrpclib.ServerPro
     transportCls = (SoftLayerTransport, SoftLayerSafeTransport)
     API_PREFIX = 'https://api.softlayer.com/xmlrpc/v3/'
 
-    def __init__(self, service, user_agent, verbose=0):
+    def __init__(self, service, user_agent, verbose=False):
         cls = self.transportCls[0]
-        if SoftLayerProxy.API_PREFIX[:8] == "https://":
+        if SoftLayerProxy.API_PREFIX[:8] == 'https://':
             cls = self.transportCls[1]
         t = cls(use_datetime=0)
         t.user_agent = user_agent
         xmlrpclib.ServerProxy.__init__(
             self,
-            uri="%s/%s" % (SoftLayerProxy.API_PREFIX, service),
+            uri='%s/%s' % (SoftLayerProxy.API_PREFIX, service),
             transport=t,
-            verbose=verbose
+            verbose=verbose,
         )
 
 
@@ -203,20 +144,23 @@ class SoftLayerConnection(object):
         headers.update(self._get_init_params(service, kwargs.get('id')))
         headers.update(
             self._get_object_mask(service, kwargs.get('object_mask')))
+
+        headers.update(
+            self._get_object_mask(service, kwargs.get('object_mask')))
         params = [{'headers': headers}] + list(args)
 
         try:
             return getattr(sl, method)(*params)
         except xmlrpclib.Fault:
             e = sys.exc_info()[1]
-            if e.faultCode == "SoftLayer_Account":
+            if e.faultCode == 'SoftLayer_Account':
                 raise InvalidCredsError(e.faultString)
             raise SoftLayerException(e)
 
     def _user_agent(self):
         return 'libcloud/%s (%s)%s' % (libcloud.__version__,
                                        self.driver.name,
-                                       "".join([" (%s)" % x for x in self.ua]))
+                                       ''.join([' (%s)' % x for x in self.ua]))
 
     def user_agent_append(self, s):
         self.ua.append(s)
@@ -262,7 +206,7 @@ class SoftLayerNodeDriver(NodeDriver):
     website = 'http://www.softlayer.com/'
     type = Provider.SOFTLAYER
 
-    features = {"create_node": ["generates_password"]}
+    features = {'create_node': ['generates_password']}
 
     def __init__(self, key, secret=None, secure=False):
         """
@@ -285,7 +229,7 @@ class SoftLayerNodeDriver(NodeDriver):
     def _to_node(self, host):
         try:
             password = \
-                host['softwareComponents'][0]['passwords'][0]['password']
+                host['operatingSystem']['passwords'][0]['password']
         except (IndexError, KeyError):
             password = None
 
@@ -293,13 +237,13 @@ class SoftLayerNodeDriver(NodeDriver):
             'hourlyRecurringFee', 0)
         recurringFee = host.get('billingItem', {}).get('recurringFee', 0)
         recurringMonths = host.get('billingItem', {}).get('recurringMonths', 0)
+        createDate = host.get('createDate', None)
 
         return Node(
             id=host['id'],
             name=host['hostname'],
             state=NODE_STATE_MAP.get(
-                host['powerState']['keyName'],
-                NodeState.UNKNOWN
+                host['powerState']['keyName'], NodeState.UNKNOWN
             ),
             public_ips=[host['primaryIpAddress']],
             private_ips=[host['primaryBackendIpAddress']],
@@ -309,59 +253,44 @@ class SoftLayerNodeDriver(NodeDriver):
                 'hourlyRecurringFee': hourlyRecurringFee,
                 'recurringFee': recurringFee,
                 'recurringMonths': recurringMonths,
+                'created': createDate,
             }
         )
 
-    def _to_nodes(self, hosts):
-        return [self._to_node(h) for h in hosts]
-
     def destroy_node(self, node):
-        billing_item = self.connection.request(
-            "SoftLayer_Virtual_Guest",
-            "getBillingItem",
-            id=node.id
+        self.connection.request(
+            'SoftLayer_Virtual_Guest', 'deleteObject', id=node.id
         )
+        return True
 
-        if billing_item:
-            res = self.connection.request(
-                "SoftLayer_Billing_Item",
-                "cancelService",
-                id=billing_item['id']
-            )
-            return res
-        else:
-            return False
+    def reboot_node(self, node):
+        self.connection.request(
+            'SoftLayer_Virtual_Guest', 'rebootSoft', id=node.id
+        )
+        return True
 
-    def _get_order_information(self, order_id, timeout=1200, check_interval=5):
+    def _get_order_information(self, node_id, timeout=1200, check_interval=5):
         mask = {
-            'orderTopLevelItems': {
-                'billingItem': {
-                    'resource': {
-                        'softwareComponents': {'passwords': ''},
-                        'powerState': '',
-                    }
-                },
-            }
+            'billingItem': '',
+            'powerState': '',
+            'operatingSystem': {'passwords': ''},
+            'provisionDate': '',
         }
 
         for i in range(0, timeout, check_interval):
-            try:
-                res = self.connection.request(
-                    "SoftLayer_Billing_Order",
-                    "getObject",
-                    id=order_id,
-                    object_mask=mask
-                )
-                item = res['orderTopLevelItems'][0]['billingItem']['resource']
-                if item['softwareComponents'][0]['passwords']:
-                    return item
+            res = self.connection.request(
+                'SoftLayer_Virtual_Guest',
+                'getObject',
+                id=node_id,
+                object_mask=mask
+            )
 
-            except (KeyError, IndexError):
-                pass
+            if res.get('provisionDate', None):
+                return res
 
             time.sleep(check_interval)
 
-        return None
+        raise SoftLayerException('Timeout on getting node details')
 
     def create_node(self, **kwargs):
         """Create a new SoftLayer node
@@ -370,55 +299,111 @@ class SoftLayerNodeDriver(NodeDriver):
 
         @keyword    ex_domain: e.g. libcloud.org
         @type       ex_domain: C{str}
+        @keyword    ex_cpus: e.g. 2
+        @type       ex_cpus: C{int}
+        @keyword    ex_disk: e.g. 100
+        @type       ex_disk: C{int}
+        @keyword    ex_ram: e.g. 2048
+        @type       ex_ram: C{int}
+        @keyword    ex_bandwidth: e.g. 100
+        @type       ex_bandwidth: C{int}
+        @keyword    ex_local_disk: e.g. True
+        @type       ex_local_disk: C{bool}
+        @keyword    ex_datacenter: e.g. Dal05
+        @type       ex_datacenter: C{str}
+        @keyword    ex_os: e.g. UBUNTU_LATEST
+        @type       ex_os: C{str}
         """
         name = kwargs['name']
-        image = kwargs['image']
-        size = kwargs['size']
+        os = 'DEBIAN_LATEST'
+        if 'ex_os' in kwargs:
+            os = kwargs['ex_os']
+        elif 'image' in kwargs:
+            os = kwargs['image'].id
+
+        size = kwargs.get('size', NodeSize(id=None, name='Custom', ram=None,
+                                           disk=None, bandwidth=None,
+                                           price=None,
+                                           driver=self.connection.driver))
+
+        ex_size_data = SL_TEMPLATES.get(size.id) or {}
+        cpu_count = kwargs.get('ex_cpus') or ex_size_data.get('cpus') or 1
+        ram = kwargs.get('ex_ram') or size.ram or 2048
+        bandwidth = kwargs.get('ex_bandwidth') or size.bandwidth or 10
+        hourly = 'true' if kwargs.get('ex_hourly', True) else 'false'
+
+        local_disk = 'true'
+        if ex_size_data.get('local_disk') is False:
+            local_disk = 'false'
+
+        if kwargs.get('ex_local_disk') is False:
+            local_disk = 'false'
+
+        disk_size = 100
+        if size.disk:
+            disk_size = size.disk
+        if kwargs.get('ex_disk'):
+            disk_size = kwargs.get('ex_disk')
+
+        datacenter = ''
+        if 'ex_datacenter' in kwargs:
+            datacenter = kwargs['ex_datacenter']
+        elif 'location' in kwargs:
+            datacenter = kwargs['location'].id
+
         domain = kwargs.get('ex_domain')
-        location = kwargs['location']
         if domain is None:
-            if name.find(".") != -1:
+            if name.find('.') != -1:
                 domain = name[name.find('.') + 1:]
-
         if domain is None:
             # TODO: domain is a required argument for the Sofylayer API, but it
             # it shouldn't be.
-            domain = "exmaple.com"
+            domain = 'example.com'
 
-        res = {'prices': SL_TEMPLATES[size.id]['prices']}
-        res['packageId'] = DEFAULT_PACKAGE
-        res['prices'].append({'id': image.id})  # Add OS to order
-        res['location'] = location.id
-        res['complexType'] = 'SoftLayer_Container_Product_Order_Virtual_Guest'
-        res['quantity'] = 1
-        res['useHourlyPricing'] = True
-        res['virtualGuests'] = [
-            {
-                'hostname': name,
-                'domain': domain
-            }
-        ]
+        newCCI = {
+            'hostname': name,
+            'domain': domain,
+            'startCpus': cpu_count,
+            'maxMemory': ram,
+            'networkComponents': [{'maxSpeed': bandwidth}],
+            'hourlyBillingFlag': hourly,
+            'operatingSystemReferenceCode': os,
+            'localDiskFlag': local_disk,
+            'blockDevices': [
+                {
+                    'device': '0',
+                    'diskImage': {
+                        'capacity': disk_size,
+                    }
+                }
+            ]
+
+        }
+
+        if datacenter:
+            newCCI['datacenter'] = {'name': datacenter}
 
         res = self.connection.request(
-            "SoftLayer_Product_Order",
-            "placeOrder",
-            res
+            'SoftLayer_Virtual_Guest', 'createObject', newCCI
         )
 
-        order_id = res['orderId']
-        raw_node = self._get_order_information(order_id)
+        node_id = res['id']
+        raw_node = self._get_order_information(node_id)
 
         return self._to_node(raw_node)
 
     def _to_image(self, img):
         return NodeImage(
-            id=img['id'],
-            name=img['name'],
+            id=img['template']['operatingSystemReferenceCode'],
+            name=img['itemPrice']['item']['description'],
             driver=self.connection.driver
         )
 
     def list_images(self, location=None):
-        return [self._to_image(i) for i in SL_IMAGES]
+        result = self.connection.request(
+            'SoftLayer_Virtual_Guest', 'getCreateObjectOptions'
+        )
+        return [self._to_image(i) for i in result['operatingSystems']]
 
     def _to_size(self, id, size):
         return NodeSize(
@@ -426,38 +411,32 @@ class SoftLayerNodeDriver(NodeDriver):
             name=size['name'],
             ram=size['ram'],
             disk=size['disk'],
-            bandwidth=size['bandwidth'],
+            bandwidth=size.get('bandwidth'),
             price=None,
             driver=self.connection.driver,
         )
 
     def list_sizes(self, location=None):
-        return [self._to_size(id, s['imagedata']) for id, s in
-                list(SL_TEMPLATES.items())]
+        return [self._to_size(id, s) for id, s in SL_TEMPLATES.items()]
 
     def _to_loc(self, loc):
-        return NodeLocation(
-            id=loc['id'],
-            name=loc['name'],
-            country=DATACENTERS[loc['name']]['country'],
-            driver=self
-        )
+        country = 'UNKNOWN'
+        if loc['name'] in DATACENTERS:
+            country = DATACENTERS[loc['name']]['country']
+        return NodeLocation(id=loc['name'], name=loc['longName'],
+                            country=country, driver=self)
 
     def list_locations(self):
         res = self.connection.request(
-            "SoftLayer_Location_Datacenter",
-            "getDatacenters"
+            'SoftLayer_Location_Datacenter', 'getDatacenters'
         )
-
-        # checking "in DATACENTERS", because some of the locations returned
-        # by getDatacenters are not useable.
-        return [self._to_loc(l) for l in res if l['name'] in DATACENTERS]
+        return [self._to_loc(l) for l in res]
 
     def list_nodes(self):
         mask = {
             'virtualGuests': {
                 'powerState': '',
-                'softwareComponents': {'passwords': ''},
+                'operatingSystem': {'passwords': ''},
                 'billingItem': '',
             },
         }
@@ -466,13 +445,4 @@ class SoftLayerNodeDriver(NodeDriver):
             "getVirtualGuests",
             object_mask=mask
         )
-        nodes = self._to_nodes(res)
-        return nodes
-
-    def reboot_node(self, node):
-        res = self.connection.request(
-            "SoftLayer_Virtual_Guest",
-            "rebootHard",
-            id=node.id
-        )
-        return res
+        return [self._to_node(h) for h in res]

Added: libcloud/trunk/libcloud/test/compute/fixtures/softlayer/empty.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/softlayer/empty.xml?rev=1441655&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/softlayer/empty.xml (added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/softlayer/empty.xml Fri Feb  1 22:52:01 2013
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<params/>
\ No newline at end of file

Modified: libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests.xml?rev=1441655&r1=1441654&r2=1441655&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests.xml (original)
+++ libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Account_getVirtualGuests.xml Fri Feb  1 22:52:01 2013
@@ -116,9 +116,8 @@
        </value>
       </member>
       <member>
-       <name>softwareComponents</name>
+       <name>operatingSystem</name>
        <value>
-        <array>
          <data>
           <value>
            <struct>
@@ -198,7 +197,6 @@
            </struct>
           </value>
          </data>
-        </array>
        </value>
       </member>
       <member>
@@ -1064,3 +1062,4 @@
  </value>
 </param>
 </params>
+

Modified: libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getDatacenters.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getDatacenters.xml?rev=1441655&r1=1441654&r2=1441655&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getDatacenters.xml (original)
+++ libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3_SoftLayer_Location_Datacenter_getDatacenters.xml Fri Feb  1 22:52:01 2013
@@ -15,13 +15,13 @@
       <member>
        <name>name</name>
        <value>
-        <string>dal00</string>
+        <string>dal05</string>
        </value>
       </member>
       <member>
        <name>longName</name>
        <value>
-        <string>Corporate HQ</string>
+        <string>Dallas 5</string>
        </value>
       </member>
      </struct>
@@ -92,6 +92,28 @@
       </member>
      </struct>
     </value>
+    <value>
+     <struct>
+      <member>
+       <name>id</name>
+       <value>
+        <int>12345</int>
+       </value>
+      </member>
+      <member>
+       <name>name</name>
+       <value>
+        <string>newcity01</string>
+       </value>
+      </member>
+      <member>
+       <name>longName</name>
+       <value>
+        <string>New City</string>
+       </value>
+      </member>
+     </struct>
+    </value>
    </data>
   </array>
  </value>

Added: libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObject.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObject.xml?rev=1441655&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObject.xml (added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_createObject.xml Fri Feb  1 22:52:01 2013
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<params>
+<param>
+ <value>
+  <struct>
+   <member>
+    <name>accountId</name>
+    <value>
+     <int>12345</int>
+    </value>
+   </member>
+   <member>
+    <name>createDate</name>
+    <value>
+     <string>2013-01-01T19:31:22-06:00</string>
+    </value>
+   </member>
+   <member>
+    <name>dedicatedAccountHostOnlyFlag</name>
+    <value>
+     <boolean>0</boolean>
+    </value>
+   </member>
+   <member>
+    <name>domain</name>
+    <value>
+     <string>domain.com</string>
+    </value>
+   </member>
+   <member>
+    <name>fullyQualifiedDomainName</name>
+    <value>
+     <string>hostname.domain.com</string>
+    </value>
+   </member>
+   <member>
+    <name>hostname</name>
+    <value>
+     <string>hostname</string>
+    </value>
+   </member>
+   <member>
+    <name>id</name>
+    <value>
+     <int>123456</int>
+    </value>
+   </member>
+   <member>
+    <name>lastPowerStateId</name>
+    <value>
+     <string/>
+    </value>
+   </member>
+   <member>
+    <name>lastVerifiedDate</name>
+    <value>
+  	  <string/>
+    </value>
+   </member>
+   <member>
+    <name>maxCpu</name>
+    <value>
+     <int>2</int>
+    </value>
+   </member>
+   <member>
+    <name>maxCpuUnits</name>
+    <value>
+     <string>CORE</string>
+    </value>
+   </member>
+   <member>
+    <name>maxMemory</name>
+    <value>
+     <int>2048</int>
+    </value>
+   </member>
+   <member>
+    <name>metricPollDate</name>
+    <value>
+     <string/>
+    </value>
+   </member>
+   <member>
+    <name>modifyDate</name>
+    <value>
+     <string/>
+    </value>
+   </member>
+   <member>
+    <name>privateNetworkOnlyFlag</name>
+    <value>
+     <boolean>0</boolean>
+    </value>
+   </member>
+   <member>
+    <name>startCpus</name>
+    <value>
+     <int>2</int>
+    </value>
+   </member>
+   <member>
+    <name>statusId</name>
+    <value>
+     <int>1001</int>
+    </value>
+   </member>
+   <member>
+    <name>globalIdentifier</name>
+    <value>
+     <string>f47ac10b-58cc-4372-a567-0e02b2c3d479</string>
+    </value>
+   </member>
+   <member>
+    <name>managedResourceFlag</name>
+    <value>
+     <boolean>0</boolean>
+    </value>
+   </member>
+   <member>
+    <name>powerState</name>
+    <value>
+     <struct>
+      <member>
+       <name>keyName</name>
+       <value>
+        <string>HALTED</string>
+       </value>
+      </member>
+      <member>
+       <name>name</name>
+       <value>
+        <string>Halted</string>
+       </value>
+      </member>
+     </struct>
+    </value>
+   </member>
+  </struct>
+ </value>
+ </param>
+</params>

Added: libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml?rev=1441655&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml (added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml Fri Feb  1 22:52:01 2013
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<params>
+<param>
+ <value>
+  <struct>
+   <member>
+    <name>operatingSystems</name>
+    <value>
+     <array>
+      <data>
+       <value>
+        <struct>
+         <member>
+          <name>itemPrice</name>
+          <value>
+           <struct>
+            <member>
+             <name>hourlyRecurringFee</name>
+             <value>
+              <string>0</string>
+             </value>
+            </member>
+            <member>
+             <name>recurringFee</name>
+             <value>
+              <string>0</string>
+             </value>
+            </member>
+            <member>
+             <name>item</name>
+             <value>
+              <struct>
+               <member>
+                <name>description</name>
+                <value>
+                 <string>CentOS 6.0 - Minimal Install (64 bit)</string>
+                </value>
+               </member>
+              </struct>
+             </value>
+            </member>
+           </struct>
+          </value>
+         </member>
+         <member>
+          <name>template</name>
+          <value>
+           <struct>
+            <member>
+             <name>operatingSystemReferenceCode</name>
+             <value>
+              <string>CENTOS_6_64</string>
+             </value>
+            </member>
+           </struct>
+          </value>
+         </member>
+        </struct>
+       </value>
+      </data>
+     </array>
+    </value>
+   </member>
+  </struct>
+ </value>
+</param>
+</params>
\ No newline at end of file

Added: libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject.xml?rev=1441655&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject.xml (added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/softlayer/v3__SoftLayer_Virtual_Guest_getObject.xml Fri Feb  1 22:52:01 2013
@@ -0,0 +1,519 @@
+<?xml version="1.0" encoding="utf-8"?>
+<params>
+<param>
+ <value>
+  <struct>
+   <member>
+    <name>accountId</name>
+    <value>
+     <int>12345</int>
+    </value>
+   </member>
+   <member>
+    <name>createDate</name>
+    <value>
+     <string>2013-01-01T19:31:22-06:00</string>
+    </value>
+   </member>
+   <member>
+    <name>dedicatedAccountHostOnlyFlag</name>
+    <value>
+     <boolean>0</boolean>
+    </value>
+   </member>
+   <member>
+    <name>domain</name>
+    <value>
+     <string>domain.com</string>
+    </value>
+   </member>
+   <member>
+    <name>fullyQualifiedDomainName</name>
+    <value>
+     <string>hostname.domain.com</string>
+    </value>
+   </member>
+   <member>
+    <name>hostname</name>
+    <value>
+     <string>hostname</string>
+    </value>
+   </member>
+   <member>
+    <name>id</name>
+    <value>
+     <int>123456</int>
+    </value>
+   </member>
+   <member>
+    <name>lastPowerStateId</name>
+    <value>
+     <int>1</int>
+    </value>
+   </member>
+   <member>
+    <name>lastVerifiedDate</name>
+    <value>
+     <string/>
+    </value>
+   </member>
+   <member>
+    <name>maxCpu</name>
+    <value>
+     <int>2</int>
+    </value>
+   </member>
+   <member>
+    <name>maxCpuUnits</name>
+    <value>
+     <string>CORE</string>
+    </value>
+   </member>
+   <member>
+    <name>maxMemory</name>
+    <value>
+     <int>2048</int>
+    </value>
+   </member>
+   <member>
+    <name>metricPollDate</name>
+    <value>
+     <string/>
+    </value>
+   </member>
+   <member>
+    <name>modifyDate</name>
+    <value>
+     <string>2013-01-01T19:36:47-06:00</string>
+    </value>
+   </member>
+   <member>
+    <name>privateNetworkOnlyFlag</name>
+    <value>
+     <boolean>0</boolean>
+    </value>
+   </member>
+   <member>
+    <name>startCpus</name>
+    <value>
+     <int>2</int>
+    </value>
+   </member>
+   <member>
+    <name>statusId</name>
+    <value>
+     <int>1001</int>
+    </value>
+   </member>
+   <member>
+    <name>uuid</name>
+    <value>
+     <string>f47ac10b-58cc-4372-a567-0e02b2c3d479</string>
+    </value>
+   </member>
+   <member>
+    <name>billingItem</name>
+    <value>
+     <struct>
+      <member>
+       <name>allowCancellationFlag</name>
+       <value>
+        <int>1</int>
+       </value>
+      </member>
+      <member>
+       <name>cancellationDate</name>
+       <value>
+        <string/>
+       </value>
+      </member>
+      <member>
+       <name>categoryCode</name>
+       <value>
+        <string>guest_core</string>
+       </value>
+      </member>
+      <member>
+       <name>createDate</name>
+       <value>
+        <string>2013-01-01T19:31:26-06:00</string>
+       </value>
+      </member>
+      <member>
+       <name>currentHourlyCharge</name>
+       <value>
+        <string>0</string>
+       </value>
+      </member>
+      <member>
+       <name>cycleStartDate</name>
+       <value>
+        <string>2013-01-01T19:38:00-06:00</string>
+       </value>
+      </member>
+      <member>
+       <name>description</name>
+       <value>
+        <string>2 x 2.0 GHz Cores</string>
+       </value>
+      </member>
+      <member>
+       <name>domainName</name>
+       <value>
+        <string>domain.com</string>
+       </value>
+      </member>
+      <member>
+       <name>hostName</name>
+       <value>
+        <string>hostname</string>
+       </value>
+      </member>
+      <member>
+       <name>hourlyRecurringFee</name>
+       <value>
+        <string>0</string>
+       </value>
+      </member>
+      <member>
+       <name>hoursUsed</name>
+       <value>
+        <string>1</string>
+       </value>
+      </member>
+      <member>
+       <name>id</name>
+       <value>
+        <int>12345678</int>
+       </value>
+      </member>
+      <member>
+       <name>laborFee</name>
+       <value>
+        <string>0</string>
+       </value>
+      </member>
+      <member>
+       <name>laborFeeTaxRate</name>
+       <value>
+        <string>.066</string>
+       </value>
+      </member>
+      <member>
+       <name>lastBillDate</name>
+       <value>
+        <string>2013-01-01T19:38:00-06:00</string>
+       </value>
+      </member>
+      <member>
+       <name>modifyDate</name>
+       <value>
+        <string>2013-01-01T19:38:00-06:00</string>
+       </value>
+      </member>
+      <member>
+       <name>nextBillDate</name>
+       <value>
+        <string>2013-01-19T00:00:00-06:00</string>
+       </value>
+      </member>
+      <member>
+       <name>oneTimeFee</name>
+       <value>
+        <string>0</string>
+       </value>
+      </member>
+      <member>
+       <name>oneTimeFeeTaxRate</name>
+       <value>
+        <string>.066</string>
+       </value>
+      </member>
+      <member>
+       <name>orderItemId</name>
+       <value>
+        <int>98765</int>
+       </value>
+      </member>
+      <member>
+       <name>parentId</name>
+       <value>
+        <string/>
+       </value>
+      </member>
+      <member>
+       <name>recurringFee</name>
+       <value>
+        <string>0</string>
+       </value>
+      </member>
+      <member>
+       <name>recurringFeeTaxRate</name>
+       <value>
+        <string>.066</string>
+       </value>
+      </member>
+      <member>
+       <name>recurringMonths</name>
+       <value>
+        <int>1</int>
+       </value>
+      </member>
+      <member>
+       <name>serviceProviderId</name>
+       <value>
+        <int>1</int>
+       </value>
+      </member>
+      <member>
+       <name>setupFee</name>
+       <value>
+        <string>0</string>
+       </value>
+      </member>
+      <member>
+       <name>setupFeeTaxRate</name>
+       <value>
+        <string>.066</string>
+       </value>
+      </member>
+      <member>
+       <name>resourceTableId</name>
+       <value>
+        <int>1412553</int>
+       </value>
+      </member>
+     </struct>
+    </value>
+   </member>
+   <member>
+    <name>globalIdentifier</name>
+    <value>
+     <string>f47ac10b-58cc-4372-a567-0e02b2c3d479</string>
+    </value>
+   </member>
+   <member>
+    <name>managedResourceFlag</name>
+    <value>
+     <boolean>0</boolean>
+    </value>
+   </member>
+   <member>
+    <name>operatingSystem</name>
+    <value>
+     <struct>
+      <member>
+       <name>hardwareId</name>
+       <value>
+        <string/>
+       </value>
+      </member>
+      <member>
+       <name>id</name>
+       <value>
+        <int>12345</int>
+       </value>
+      </member>
+      <member>
+       <name>manufacturerLicenseInstance</name>
+       <value>
+        <string/>
+       </value>
+      </member>
+      <member>
+       <name>passwords</name>
+       <value>
+        <array>
+         <data>
+          <value>
+           <struct>
+            <member>
+             <name>createDate</name>
+             <value>
+              <string>2013-01-01T19:33:12-06:00</string>
+             </value>
+            </member>
+            <member>
+             <name>id</name>
+             <value>
+              <int>12345</int>
+             </value>
+            </member>
+            <member>
+             <name>modifyDate</name>
+             <value>
+              <string>2013-01-01T19:33:12-06:00</string>
+             </value>
+            </member>
+            <member>
+             <name>password</name>
+             <value>
+              <string>abczyx</string>
+             </value>
+            </member>
+            <member>
+             <name>port</name>
+             <value>
+              <string/>
+             </value>
+            </member>
+            <member>
+             <name>softwareId</name>
+             <value>
+              <int>1809157</int>
+             </value>
+            </member>
+            <member>
+             <name>username</name>
+             <value>
+              <string>root</string>
+             </value>
+            </member>
+           </struct>
+          </value>
+         </data>
+        </array>
+       </value>
+      </member>
+      <member>
+       <name>softwareLicense</name>
+       <value>
+        <struct>
+         <member>
+          <name>id</name>
+          <value>
+           <int>1104</int>
+          </value>
+         </member>
+         <member>
+          <name>softwareDescriptionId</name>
+          <value>
+           <int>1025</int>
+          </value>
+         </member>
+         <member>
+          <name>softwareDescription</name>
+          <value>
+           <struct>
+            <member>
+             <name>controlPanel</name>
+             <value>
+              <int>0</int>
+             </value>
+            </member>
+            <member>
+             <name>id</name>
+             <value>
+              <int>1025</int>
+             </value>
+            </member>
+            <member>
+             <name>manufacturer</name>
+             <value>
+              <string>Ubuntu</string>
+             </value>
+            </member>
+            <member>
+             <name>name</name>
+             <value>
+              <string>Ubuntu</string>
+             </value>
+            </member>
+            <member>
+             <name>operatingSystem</name>
+             <value>
+              <int>1</int>
+             </value>
+            </member>
+            <member>
+             <name>referenceCode</name>
+             <value>
+              <string>UBUNTU_12_64</string>
+             </value>
+            </member>
+            <member>
+             <name>requiredUser</name>
+             <value>
+              <string>root</string>
+             </value>
+            </member>
+            <member>
+             <name>upgradeSoftwareDescriptionId</name>
+             <value>
+              <string/>
+             </value>
+            </member>
+            <member>
+             <name>upgradeSwDescId</name>
+             <value>
+              <string/>
+             </value>
+            </member>
+            <member>
+             <name>version</name>
+             <value>
+              <string>12.04-64 Minimal for CCI</string>
+             </value>
+            </member>
+            <member>
+             <name>virtualLicense</name>
+             <value>
+              <int>0</int>
+             </value>
+            </member>
+            <member>
+             <name>virtualizationPlatform</name>
+             <value>
+              <int>0</int>
+             </value>
+            </member>
+           </struct>
+          </value>
+         </member>
+        </struct>
+       </value>
+      </member>
+     </struct>
+    </value>
+   </member>
+   <member>
+    <name>powerState</name>
+    <value>
+     <struct>
+      <member>
+       <name>keyName</name>
+       <value>
+        <string>RUNNING</string>
+       </value>
+      </member>
+      <member>
+       <name>name</name>
+       <value>
+        <string>Running</string>
+       </value>
+      </member>
+     </struct>
+    </value>
+   </member>
+   <member>
+    <name>primaryBackendIpAddress</name>
+    <value>
+     <string>10.80.10.10</string>
+    </value>
+   </member>
+   <member>
+    <name>primaryIpAddress</name>
+    <value>
+     <string>173.193.10.10</string>
+    </value>
+   </member>
+   <member>
+    <name>provisionDate</name>
+    <value>
+     <string>2013-01-01T19:38:01-06:00</string>
+    </value>
+   </member>
+  </struct>
+ </value>
+ </param>
+</params>

Modified: libcloud/trunk/libcloud/test/compute/test_softlayer.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/test_softlayer.py?rev=1441655&r1=1441654&r2=1441655&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/test_softlayer.py (original)
+++ libcloud/trunk/libcloud/test/compute/test_softlayer.py Fri Feb  1 22:52:01 2013
@@ -18,21 +18,32 @@ import sys
 
 from xml.etree import ElementTree as ET
 
+from libcloud.common.types import InvalidCredsError
+
 from libcloud.utils.py3 import httplib
 from libcloud.utils.py3 import xmlrpclib
 from libcloud.utils.py3 import next
+from libcloud.utils.py3 import u
 
 from libcloud.compute.drivers.softlayer import SoftLayerNodeDriver as SoftLayer
+from libcloud.compute.drivers.softlayer import SoftLayerException
 from libcloud.compute.types import NodeState
 
 from libcloud.test import MockHttp               # pylint: disable-msg=E0611
-from libcloud.test.file_fixtures import ComputeFileFixtures # pylint: disable-msg=E0611
+from libcloud.test.file_fixtures import ComputeFileFixtures  # pylint: disable-msg=E0611
 from libcloud.test.secrets import SOFTLAYER_PARAMS
 
+
 class MockSoftLayerTransport(xmlrpclib.Transport):
 
     def request(self, host, handler, request_body, verbose=0):
         self.verbose = 0
+
+        if 'SOFTLAYEREXCEPTION' in u(request_body):
+            raise xmlrpclib.Fault('fail', 'Failed Call')
+        if 'INVALIDCREDSERROR' in u(request_body):
+            raise xmlrpclib.Fault('SoftLayer_Account', 'Failed Call')
+
         method = ET.XML(request_body).find('methodName').text
         mock = SoftLayerMockHttp(host, 80)
         mock.request('POST', "%s/%s" % (handler, method))
@@ -44,6 +55,7 @@ class MockSoftLayerTransport(xmlrpclib.T
             response = self.parse_response(resp.body)
         return response
 
+
 class SoftLayerTests(unittest.TestCase):
 
     def setUp(self):
@@ -59,36 +71,126 @@ class SoftLayerTests(unittest.TestCase):
 
     def test_list_locations(self):
         locations = self.driver.list_locations()
-        seattle = next(l for l in locations if l.name == 'sea01')
-        self.assertEqual(seattle.country, 'US')
-        self.assertEqual(seattle.id, '18171')
+        dal = next(l for l in locations if l.id == 'dal05')
+        self.assertEqual(dal.country, 'US')
+        self.assertEqual(dal.id, 'dal05')
+        self.assertEqual(dal.name, 'Dallas 5')
 
     def test_list_images(self):
         images = self.driver.list_images()
         image = images[0]
-        self.assertEqual(image.id, '1684')
+        self.assertEqual(image.id, 'CENTOS_6_64')
 
     def test_list_sizes(self):
         sizes = self.driver.list_sizes()
-        self.assertEqual(len(sizes), 2)
-        size = [s for s in sizes if s.id == 'sl1']
+        self.assertEqual(len(sizes), 10)
+        size = [s for s in sizes if s.id == 'sl2_local_disk']
         self.assertEqual(len(size), 1)
 
+    def test_create_node(self):
+        self.driver.create_node(name="Test",
+                                location=self.driver.list_locations()[0],
+                                size=self.driver.list_sizes()[0],
+                                image=self.driver.list_images()[0])
+
+    def test_create_fail(self):
+        self.assertRaises(
+            SoftLayerException,
+            self.driver.create_node,
+            name="SOFTLAYEREXCEPTION",
+            location=self.driver.list_locations()[0],
+            size=self.driver.list_sizes()[0],
+            image=self.driver.list_images()[0])
+
+    def test_create_creds_error(self):
+        self.assertRaises(
+            InvalidCredsError,
+            self.driver.create_node,
+            name="INVALIDCREDSERROR",
+            location=self.driver.list_locations()[0],
+            size=self.driver.list_sizes()[0],
+            image=self.driver.list_images()[0])
+
+    def test_create_node_no_location(self):
+        self.driver.create_node(name="Test",
+                                size=self.driver.list_sizes()[0],
+                                image=self.driver.list_images()[0])
+
+    def test_create_node_no_image(self):
+        self.driver.create_node(name="Test", size=self.driver.list_sizes()[0])
+
+    def test_create_node_san(self):
+        size = [s for s in self.driver.list_sizes() if 'san' in s.id][0]
+        self.driver.create_node(name="Test", size=size)
+
+    def test_create_node_domain_for_name(self):
+        size = [s for s in self.driver.list_sizes() if 'san' in s.id][0]
+        self.driver.create_node(name="libcloud.org")
+
+    def test_create_node_ex_options(self):
+        self.driver.create_node(name="Test",
+                                location=self.driver.list_locations()[0],
+                                size=self.driver.list_sizes()[0],
+                                image=self.driver.list_images()[0],
+                                ex_domain='libcloud.org',
+                                ex_cpus=2,
+                                ex_ram=2048,
+                                ex_disk=100,
+                                ex_bandwidth=10,
+                                ex_local_disk=False,
+                                ex_datacenter='Dal05',
+                                ex_os='UBUNTU_LATEST')
+
+    def test_reboot_node(self):
+        node = self.driver.list_nodes()[0]
+        self.driver.reboot_node(node)
+
+    def test_destroy_node(self):
+        node = self.driver.list_nodes()[0]
+        self.driver.destroy_node(node)
+
+
 class SoftLayerMockHttp(MockHttp):
     fixtures = ComputeFileFixtures('softlayer')
 
-    def _xmlrpc_v3__SoftLayer_Account_getVirtualGuests(
-        self, method, url, body, headers):
+    def _xmlrpc_v3__SoftLayer_Virtual_Guest_getCreateObjectOptions(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+            'v3__SoftLayer_Virtual_Guest_getCreateObjectOptions.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _xmlrpc_v3__SoftLayer_Account_getVirtualGuests(
+            self, method, url, body, headers):
         body = self.fixtures.load('v3_SoftLayer_Account_getVirtualGuests.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _xmlrpc_v3__SoftLayer_Location_Datacenter_getDatacenters(
-        self, method, url, body, headers):
-
+            self, method, url, body, headers):
         body = self.fixtures.load(
             'v3_SoftLayer_Location_Datacenter_getDatacenters.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _xmlrpc_v3__SoftLayer_Virtual_Guest_createObject(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+            'v3__SoftLayer_Virtual_Guest_createObject.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _xmlrpc_v3__SoftLayer_Virtual_Guest_getObject(
+            self, method, url, body, headers):
+        body = self.fixtures.load(
+            'v3__SoftLayer_Virtual_Guest_getObject.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _xmlrpc_v3__SoftLayer_Virtual_Guest_rebootSoft(
+            self, method, url, body, headers):
+        body = self.fixtures.load('empty.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _xmlrpc_v3__SoftLayer_Virtual_Guest_deleteObject(
+            self, method, url, body, headers):
+        body = self.fixtures.load('empty.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
 if __name__ == '__main__':
     sys.exit(unittest.main())