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 2011/03/18 03:20:23 UTC

svn commit: r1082793 - in /incubator/libcloud/trunk: libcloud/compute/ libcloud/compute/drivers/ test/compute/ test/compute/fixtures/bluebox/

Author: tomaz
Date: Fri Mar 18 02:20:23 2011
New Revision: 1082793

URL: http://svn.apache.org/viewvc?rev=1082793&view=rev
Log:
Add Bluebox compute driver.

Changes submitted by Christian Paredes <cp at redbluemagenta dot com> as a part
of LIBCLOUD-73.

Added:
    incubator/libcloud/trunk/libcloud/compute/drivers/bluebox.py
    incubator/libcloud/trunk/test/compute/fixtures/bluebox/
    incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_block_products_json.json
    incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_block_templates_json.json
    incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json
    incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json
    incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json
    incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_json.json
    incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_json_post.json
    incubator/libcloud/trunk/test/compute/test_bluebox.py
Modified:
    incubator/libcloud/trunk/libcloud/compute/drivers/__init__.py
    incubator/libcloud/trunk/libcloud/compute/providers.py
    incubator/libcloud/trunk/libcloud/compute/types.py

Modified: incubator/libcloud/trunk/libcloud/compute/drivers/__init__.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/compute/drivers/__init__.py?rev=1082793&r1=1082792&r2=1082793&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/compute/drivers/__init__.py (original)
+++ incubator/libcloud/trunk/libcloud/compute/drivers/__init__.py Fri Mar 18 02:20:23 2011
@@ -19,6 +19,7 @@ Drivers for working with different provi
 
 __all__ = [
     'brightbox',
+    'bluebox',
     'dummy',
     'ec2',
     'ecp',

Added: incubator/libcloud/trunk/libcloud/compute/drivers/bluebox.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/compute/drivers/bluebox.py?rev=1082793&view=auto
==============================================================================
--- incubator/libcloud/trunk/libcloud/compute/drivers/bluebox.py (added)
+++ incubator/libcloud/trunk/libcloud/compute/drivers/bluebox.py Fri Mar 18 02:20:23 2011
@@ -0,0 +1,234 @@
+# 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.
+
+"""
+libcloud driver for the Blue Box Blocks API
+
+This driver implements all libcloud functionality for the Blue Box Blocks API.
+
+Blue Box home page            http://bluebox.net
+Blue Box API documentation    https://boxpanel.bluebox.net/public/the_vault/index.php/Blocks_API
+"""
+
+import copy
+import urllib
+import base64
+
+try:
+    import json
+except:
+    import simplejson as json
+
+from libcloud.common.base import Response, ConnectionUserAndKey
+from libcloud.compute.providers import Provider
+from libcloud.compute.types import NodeState, InvalidCredsError
+from libcloud.compute.base import Node, NodeDriver
+from libcloud.compute.base import NodeSize, NodeImage, NodeLocation
+from libcloud.compute.base import NodeAuthPassword, NodeAuthSSHKey
+
+# Current end point for Blue Box API.
+BLUEBOX_API_HOST = "boxpanel.bluebox.net"
+
+# The API doesn't currently expose all of the required values for libcloud,
+# so we simply list what's available right now, along with all of the various
+# attributes that are needed by libcloud.
+BLUEBOX_INSTANCE_TYPES = {
+  '1gb': {
+    'id': '94fd37a7-2606-47f7-84d5-9000deda52ae',
+    'name': 'Block 1GB Virtual Server',
+    'ram': 1024,
+    'disk': 20,
+    'cpu': 0.5
+  },
+  '2gb': {
+    'id': 'b412f354-5056-4bf0-a42f-6ddd998aa092',
+    'name': 'Block 2GB Virtual Server',
+    'ram': 2048,
+    'disk': 25,
+    'cpu': 1
+  },
+  '4gb': {
+    'id': '0cd183d3-0287-4b1a-8288-b3ea8302ed58',
+    'name': 'Block 4GB Virtual Server',
+    'ram': 4096,
+    'disk': 50,
+    'cpu': 2
+  },
+  '8gb': {
+    'id': 'b9b87a5b-2885-4a2e-b434-44a163ca6251',
+    'name': 'Block 8GB Virtual Server',
+    'ram': 8192,
+    'disk': 100,
+    'cpu': 4
+  }
+}
+
+RAM_PER_CPU = 2048
+
+NODE_STATE_MAP = { 'queued': NodeState.PENDING,
+                   'building': NodeState.PENDING,
+                   'running': NodeState.RUNNING,
+                   'error': NodeState.TERMINATED,
+                   'unknown': NodeState.UNKNOWN }
+
+class BlueboxResponse(Response):
+    def parse_body(self):
+        try:
+            js = json.loads(self.body)
+            return js
+        except ValueError:
+            return self.body
+
+    def parse_error(self):
+        if int(self.status) == 401:
+            if not self.body:
+                raise InvalidCredsError(str(self.status) + ': ' + self.error)
+            else:
+                raise InvalidCredsError(self.body)
+        return self.body
+
+class BlueboxNodeSize(NodeSize):
+    def __init__(self, id, name, cpu, ram, disk, price, driver):
+        self.id = id
+        self.name = name
+        self.cpu = cpu
+        self.ram = ram
+        self.disk = disk
+        self.price = price
+        self.driver = driver
+
+    def __repr__(self):
+        return (('<NodeSize: id=%s, name=%s, cpu=%s, ram=%s, disk=%s, price=%s, driver=%s ...>')
+               % (self.id, self.name, self.cpu, self.ram, self.disk, self.price, self.driver.name))
+
+class BlueboxConnection(ConnectionUserAndKey):
+    """
+    Connection class for the Bluebox driver
+    """
+
+    host = BLUEBOX_API_HOST
+    secure = True
+    responseCls = BlueboxResponse
+
+    def add_default_headers(self, headers):
+        user_b64 = base64.b64encode('%s:%s' % (self.user_id, self.key))
+        headers['Authorization'] = 'Basic %s' % (user_b64)
+        return headers
+
+class BlueboxNodeDriver(NodeDriver):
+    """
+    Bluebox Blocks node driver
+    """
+
+    connectionCls = BlueboxConnection
+    type = Provider.BLUEBOX
+    api_name = 'bluebox'
+    name = 'Bluebox Blocks'
+
+    def list_nodes(self):
+        result = self.connection.request('/api/blocks.json')
+        return [self._to_node(i) for i in result.object]
+
+    def list_sizes(self, location=None):
+        sizes = []
+        for key, values in BLUEBOX_INSTANCE_TYPES.iteritems():
+            attributes = copy.deepcopy(values)
+            attributes.update({ 'price': self._get_size_price(size_id=key) })
+            sizes.append(BlueboxNodeSize(driver=self.connection.driver,
+                                         **attributes))
+
+        return sizes
+
+    def list_images(self, location=None):
+        result = self.connection.request('/api/block_templates.json')
+        images = []
+        for image in result.object:
+          images.extend([self._to_image(image)])
+
+        return images
+
+    def create_node(self, **kwargs):
+        headers = { 'Content-Type': 'application/x-www-form-urlencoded' }
+        size = kwargs["size"]
+
+        name = kwargs['name']
+        image = kwargs['image']
+        size = kwargs['size']
+
+        try:
+            auth = kwargs['auth']
+        except Exception:
+            raise Exception("SSH public key or password required.")
+
+        data = {
+            'hostname': name,
+            'product': size.id,
+            'template': image.id
+        }
+
+        ssh = None
+        password = None
+
+        if isinstance(auth, NodeAuthSSHKey):
+            ssh = auth.pubkey
+            data.update(ssh_public_key=ssh)
+        elif isinstance(auth, NodeAuthPassword):
+            password = auth.password
+            data.update(password=password)
+
+        if "ex_username" in kwargs:
+            data.update(username=kwargs["ex_username"])
+
+        if not ssh and not password:
+            raise Exception("SSH public key or password required.")
+
+        params = urllib.urlencode(data)
+        result = self.connection.request('/api/blocks.json', headers=headers, data=params, method='POST')
+        node = self._to_node(result.object)
+        return node
+
+    def destroy_node(self, node):
+        """
+        Destroy node by passing in the node object
+        """
+        url = '/api/blocks/%s.json' % (node.id)
+        result = self.connection.request(url, method='DELETE')
+
+        return result.status == 200
+
+    def list_locations(self):
+        return [NodeLocation(0, "Blue Box Seattle US", 'US', self)]
+
+    def reboot_node(self, node):
+        url = '/api/blocks/%s/reboot.json' % (node.id)
+        result = self.connection.request(url, method="PUT")
+        return result.status == 200
+
+    def _to_node(self, vm):
+        state = NODE_STATE_MAP[vm.get('status', NodeState.UNKNOWN)]
+        n = Node(id=vm['id'],
+                 name=vm['hostname'],
+                 state=state,
+                 public_ip=[ ip['address'] for ip in vm['ips'] ],
+                 private_ip=[],
+                 extra={'storage':vm['storage'], 'cpu':vm['cpu']},
+                 driver=self.connection.driver)
+        return n
+
+    def _to_image(self, image):
+        image = NodeImage(id=image['id'],
+                          name=image['description'],
+                          driver=self.connection.driver)
+        return image

Modified: incubator/libcloud/trunk/libcloud/compute/providers.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/compute/providers.py?rev=1082793&r1=1082792&r2=1082793&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/compute/providers.py (original)
+++ incubator/libcloud/trunk/libcloud/compute/providers.py Fri Mar 18 02:20:23 2011
@@ -75,6 +75,8 @@ DRIVERS = {
         ('libcloud.compute.drivers.brightbox', 'BrightboxNodeDriver'),
     Provider.NIMBUS:
         ('libcloud.compute.drivers.ec2', 'NimbusNodeDriver'),
+    Provider.BLUEBOX:
+        ('libcloud.compute.drivers.bluebox', 'BlueboxNodeDriver'),
 }
 
 def get_driver(provider):

Modified: incubator/libcloud/trunk/libcloud/compute/types.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/compute/types.py?rev=1082793&r1=1082792&r2=1082793&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/compute/types.py (original)
+++ incubator/libcloud/trunk/libcloud/compute/types.py Fri Mar 18 02:20:23 2011
@@ -52,6 +52,7 @@ class Provider(object):
     @cvar DREAMHOST: DreamHost Private Server
     @cvar CLOUDSIGMA: CloudSigma
     @cvar NIMBUS: Nimbus
+    @cvar BLUEBOX: Bluebox
     """
     DUMMY = 0
     EC2 = 1  # deprecated name
@@ -83,6 +84,7 @@ class Provider(object):
     CLOUDSIGMA = 25
     EC2_AP_NORTHEAST = 26
     NIMBUS = 27
+    BLUEBOX = 28
 
 class NodeState(object):
     """

Added: incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_block_products_json.json
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_block_products_json.json?rev=1082793&view=auto
==============================================================================
--- incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_block_products_json.json (added)
+++ incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_block_products_json.json Fri Mar 18 02:20:23 2011
@@ -0,0 +1 @@
+[{"cost": 0.15, "id": "94fd37a7-2606-47f7-84d5-9000deda52ae", "description": "Block 1GB Virtual Server"}, {"cost": 0.25, "id": "b412f354-5056-4bf0-a42f-6ddd998aa092", "description": "Block 2GB Virtual Server"}, {"cost": 0.35, "id": "0cd183d3-0287-4b1a-8288-b3ea8302ed58", "description": "Block 4GB Virtual Server"}, {"cost": 0.45, "id": "b9b87a5b-2885-4a2e-b434-44a163ca6251", "description": "Block 8GB Virtual Server"}]

Added: incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_block_templates_json.json
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_block_templates_json.json?rev=1082793&view=auto
==============================================================================
--- incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_block_templates_json.json (added)
+++ incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_block_templates_json.json Fri Mar 18 02:20:23 2011
@@ -0,0 +1 @@
+[{"public": true, "id": "c66b8145-f768-45ef-9878-395bf8b1b7ff", "description": "CentOS 5 (Latest Release)", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "1fc24f51-6d7d-4fa9-9a6e-0d6f36b692e2", "description": "Ubuntu 8.10 64bit", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "b6f152db-988c-4194-b292-d6dd2aa2dbab", "description": "Debian 5.0 64bit", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "4b697e48-282b-4140-8cf8-142e2a2711ee", "description": "Ubuntu 8.04 LTS 64bit", "created": "2009/07/31 15:58:20 -0700"}, {"public": true, "id": "a6a141bf-592a-4fa6-b130-4c14f69e82d0", "description": "Ubuntu 8.04 LTS 32Bit", "created": "2009/04/20 15:46:34 -0700"}, {"public": true, "id": "b181033f-aea7-4e6c-8bb4-11169775c0f8", "description": "Ubuntu 9.04 64bit", "created": "2010/01/26 11:31:19 -0800"}, {"public": true, "id": "b5371c5a-9da2-43ee-a745-99a4723f624c", "description": "ArchLinux 2009.08 64bit", "created": "2010/02/13 18:07
 :01 -0800"}, {"public": true, "id": "a00baa8f-b5d0-4815-8238-b471c4c4bf72", "description": "Ubuntu 9.10 64bit", "created": "2010/02/17 22:06:21 -0800"}, {"public": true, "id": "03807e08-a13d-44e4-b011-ebec7ef2c928", "description": "Ubuntu 10.04 LTS 64bit", "created": "2010/05/04 14:43:30 -0700"}, {"public": true, "id": "8b60e6de-7cbc-4c8e-b7df-5e2f9c4ffd6b", "description": "Ubuntu 10.04 LTS 32bit", "created": "2010/05/04 14:43:30 -0700"}]

Added: incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json?rev=1082793&view=auto
==============================================================================
--- incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json (added)
+++ incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json Fri Mar 18 02:20:23 2011
@@ -0,0 +1 @@
+{"ips": [{"address": "67.214.214.212"}], "memory": 1073741824, "template": "centos", "id": "99df878c-6e5c-4945-a635-d94da9fd3146", "storage": 21474836480, "hostname": "apitest.c44905.c44905.blueboxgrid.com", "description": "1 GB RAM + 20 GB Disk", "cpu": 0.5, "status": "running", "product": {"cost": 0.15, "id": "94fd37a7-2606-47f7-84d5-9000deda52ae", "description": "Block 1GB Virtual Server"}}

Added: incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json?rev=1082793&view=auto
==============================================================================
--- incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json (added)
+++ incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json Fri Mar 18 02:20:23 2011
@@ -0,0 +1 @@
+{"text":"Block destroyed."}

Added: incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json?rev=1082793&view=auto
==============================================================================
--- incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json (added)
+++ incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json Fri Mar 18 02:20:23 2011
@@ -0,0 +1 @@
+{ "status": "ok", "text": "Reboot initiated." }

Added: incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_json.json
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_json.json?rev=1082793&view=auto
==============================================================================
--- incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_json.json (added)
+++ incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_json.json Fri Mar 18 02:20:23 2011
@@ -0,0 +1 @@
+[{"ips":[{"address":"67.214.214.212"}],"memory":1073741824,"id":"99df878c-6e5c-4945-a635-d94da9fd3146","storage":21474836480,"hostname":"foo.apitest.blueboxgrid.com","description":"1 GB RAM + 20 GB Disk","cpu":0.5,"status":"running"}]

Added: incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_json_post.json
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_json_post.json?rev=1082793&view=auto
==============================================================================
--- incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_json_post.json (added)
+++ incubator/libcloud/trunk/test/compute/fixtures/bluebox/api_blocks_json_post.json Fri Mar 18 02:20:23 2011
@@ -0,0 +1 @@
+{"ips":[{"address":"67.214.214.212"}],"memory":1073741824,"id":"99df878c-6e5c-4945-a635-d94da9fd3146","storage":21474836480,"hostname":"foo.apitest.blueboxgrid.com","description":"1 GB RAM + 20 GB Disk","cpu":0.5,"status":"queued", "product": {"cost": 0.15, "id": "94fd37a7-2606-47f7-84d5-9000deda52ae", "description": "Block 1GB Virtual Server"}}

Added: incubator/libcloud/trunk/test/compute/test_bluebox.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/compute/test_bluebox.py?rev=1082793&view=auto
==============================================================================
--- incubator/libcloud/trunk/test/compute/test_bluebox.py (added)
+++ incubator/libcloud/trunk/test/compute/test_bluebox.py Fri Mar 18 02:20:23 2011
@@ -0,0 +1,112 @@
+# 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.
+import sys
+import unittest
+import httplib
+
+from libcloud.compute.drivers.bluebox import BlueboxNodeDriver as Bluebox
+from libcloud.compute.base import Node, NodeAuthPassword
+from libcloud.compute.types import NodeState
+
+
+from test import MockHttp
+from test.file_fixtures import ComputeFileFixtures
+from test.secrets import BLUEBOX_CUSTOMER_ID, BLUEBOX_API_KEY
+
+class BlueboxTest(unittest.TestCase):
+
+    def setUp(self):
+        Bluebox.connectionCls.conn_classes = (None, BlueboxMockHttp)
+        self.driver = Bluebox(BLUEBOX_CUSTOMER_ID, BLUEBOX_API_KEY)
+
+    def test_create_node(self):
+        node = self.driver.create_node(
+          name='foo',
+          size=self.driver.list_sizes()[0],
+          image=self.driver.list_images()[0],
+          auth=NodeAuthPassword("test123")
+        )
+        self.assertTrue(isinstance(node, Node))
+        self.assertEqual(node.state, NodeState.PENDING)
+        self.assertEqual(node.name, 'foo.apitest.blueboxgrid.com')
+
+    def test_list_nodes(self):
+        node = self.driver.list_nodes()[0]
+        self.assertEqual(node.name, 'foo.apitest.blueboxgrid.com')
+        self.assertEqual(node.state, NodeState.RUNNING)
+
+    def test_list_sizes(self):
+        sizes = self.driver.list_sizes()
+        self.assertEqual(len(sizes), 4)
+
+        ids = [s.id for s in sizes]
+
+        for size in sizes:
+            self.assertTrue(size.price > 0)
+
+        self.assertTrue('94fd37a7-2606-47f7-84d5-9000deda52ae' in ids)
+        self.assertTrue('b412f354-5056-4bf0-a42f-6ddd998aa092' in ids)
+        self.assertTrue('0cd183d3-0287-4b1a-8288-b3ea8302ed58' in ids)
+        self.assertTrue('b9b87a5b-2885-4a2e-b434-44a163ca6251' in ids)
+
+    def test_list_images(self):
+        images = self.driver.list_images()
+        image = images[0]
+        self.assertEqual(len(images), 10)
+        self.assertEqual(image.name, 'CentOS 5 (Latest Release)')
+        self.assertEqual(image.id, 'c66b8145-f768-45ef-9878-395bf8b1b7ff')
+
+    def test_reboot_node(self):
+        node = self.driver.list_nodes()[0]
+        ret = self.driver.reboot_node(node)
+        self.assertTrue(ret)
+
+    def test_destroy_node(self):
+        node = self.driver.list_nodes()[0]
+        ret = self.driver.destroy_node(node)
+        self.assertTrue(ret)
+
+class BlueboxMockHttp(MockHttp):
+
+    fixtures = ComputeFileFixtures('bluebox')
+
+    def _api_blocks_json(self, method, url, body, headers):
+        if method == "POST":
+            body = self.fixtures.load('api_blocks_json_post.json')
+        else:
+            body = self.fixtures.load('api_blocks_json.json')
+        return (httplib.OK, body, headers, httplib.responses[httplib.OK])
+
+    def _api_block_products_json(self, method, url, body, headers):
+        body = self.fixtures.load('api_block_products_json.json')
+        return (httplib.OK, body, headers, httplib.responses[httplib.OK])
+
+    def _api_block_templates_json(self, method, url, body, headers):
+        body = self.fixtures.load('api_block_templates_json.json')
+        return (httplib.OK, body, headers, httplib.responses[httplib.OK])
+
+    def _api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json(self, method, url, body, headers):
+        if method == 'DELETE':
+            body = self.fixtures.load('api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json_delete.json')
+        else:
+            body = self.fixtures.load('api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_json.json')
+        return (httplib.OK, body, headers, httplib.responses[httplib.OK])
+
+    def _api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json(self, method, url, body, headers):
+        body = self.fixtures.load('api_blocks_99df878c_6e5c_4945_a635_d94da9fd3146_reboot_json.json')
+        return (httplib.OK, body, headers, httplib.responses[httplib.OK])
+
+if __name__ == '__main__':
+    sys.exit(unittest.main())