Mini Shell
# 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 base64
try:
import simplejson as json
except ImportError:
import json
from libcloud.utils.py3 import httplib
from libcloud.utils.py3 import b
from libcloud.common.types import InvalidCredsError
from libcloud.compute.drivers.brightbox import BrightboxNodeDriver
from libcloud.compute.types import NodeState
from libcloud.test import MockHttp
from libcloud.test.compute import TestCaseMixin
from libcloud.test.file_fixtures import ComputeFileFixtures
from libcloud.test.secrets import BRIGHTBOX_PARAMS
USER_DATA = '#!/bin/sh\ntest_script.sh\n'
class BrightboxTest(unittest.TestCase, TestCaseMixin):
def setUp(self):
BrightboxNodeDriver.connectionCls.conn_class = BrightboxMockHttp
BrightboxMockHttp.type = None
BrightboxNodeDriver.connectionCls.token = 'test'
self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS)
def test_authentication(self):
BrightboxMockHttp.type = 'INVALID_CLIENT'
self.assertRaises(InvalidCredsError, self.driver.list_nodes)
BrightboxMockHttp.type = 'UNAUTHORIZED_CLIENT'
self.assertRaises(InvalidCredsError, self.driver.list_nodes)
def test_invalid_api_version(self):
kwargs = {'api_version': '2.0'}
self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS, **kwargs)
self.assertRaises(Exception, self.driver.list_locations)
def test_other_host(self):
kwargs = {'host': 'api.gbt.brightbox.com'}
self.driver = BrightboxNodeDriver(*BRIGHTBOX_PARAMS, **kwargs)
locations = self.driver.list_locations()
self.assertEqual(len(locations), 0)
def test_list_nodes(self):
nodes = self.driver.list_nodes()
self.assertEqual(len(nodes), 2)
self.assertEqual(len(nodes[0].public_ips), 1)
self.assertEqual(len(nodes[1].public_ips), 1)
self.assertEqual(len(nodes[0].private_ips), 1)
self.assertEqual(len(nodes[1].private_ips), 1)
self.assertTrue('109.107.35.16' in nodes[0].public_ips)
self.assertTrue('10.74.210.210' in nodes[0].private_ips)
self.assertTrue('10.240.228.234' in nodes[1].private_ips)
self.assertTrue(
'2a02:1348:14c:393a:24:19ff:fef0:e4ea' in nodes[1].public_ips)
self.assertEqual(nodes[0].state, NodeState.RUNNING)
self.assertEqual(nodes[1].state, NodeState.RUNNING)
def test_list_node_extras(self):
nodes = self.driver.list_nodes()
self.assertFalse(nodes[0].size is None)
self.assertFalse(nodes[1].size is None)
self.assertFalse(nodes[0].image is None)
self.assertFalse(nodes[1].image is None)
self.assertEqual(nodes[0].image.id, 'img-arm8f')
self.assertEqual(nodes[0].size.id, 'typ-urtky')
self.assertEqual(nodes[1].image.id, 'img-j93gd')
self.assertEqual(nodes[1].size.id, 'typ-qdiwq')
self.assertEqual(nodes[0].extra['fqdn'], 'srv-xvpn7.gb1.brightbox.com')
self.assertEqual(nodes[1].extra['fqdn'], 'srv-742vn.gb1.brightbox.com')
self.assertEqual(nodes[0].extra['hostname'], 'srv-xvpn7')
self.assertEqual(nodes[1].extra['hostname'], 'srv-742vn')
self.assertEqual(nodes[0].extra['status'], 'active')
self.assertEqual(nodes[1].extra['status'], 'active')
self.assertTrue('interfaces' in nodes[0].extra)
self.assertTrue('zone' in nodes[0].extra)
self.assertTrue('snapshots' in nodes[0].extra)
self.assertTrue('server_groups' in nodes[0].extra)
self.assertTrue('started_at' in nodes[0].extra)
self.assertTrue('created_at' in nodes[0].extra)
self.assertFalse('deleted_at' in nodes[0].extra)
def test_list_sizes(self):
sizes = self.driver.list_sizes()
self.assertEqual(len(sizes), 7)
self.assertEqual(sizes[0].id, 'typ-4nssg')
self.assertEqual(sizes[0].name, 'Brightbox Nano Instance')
self.assertEqual(sizes[0].ram, 512)
self.assertEqual(sizes[0].disk, 20480)
self.assertEqual(sizes[0].bandwidth, 0)
self.assertEqual(sizes[0].price, 0)
def test_list_images(self):
images = self.driver.list_images()
self.assertEqual(len(images), 3)
self.assertEqual(images[0].id, 'img-99q79')
self.assertEqual(images[0].name, 'CentOS 5.5 server')
self.assertTrue('ancestor' in images[0].extra)
self.assertFalse('licence_name' in images[0].extra)
def test_list_images_extras(self):
images = self.driver.list_images()
extra = images[-1].extra
self.assertEqual(extra['arch'], 'i686')
self.assertFalse(extra['compatibility_mode'])
self.assertEqual(extra['created_at'], '2012-01-22T05:36:24Z')
self.assertTrue('description' in extra)
self.assertEqual(extra['disk_size'], 671)
self.assertFalse('min_ram' in extra)
self.assertFalse(extra['official'])
self.assertEqual(extra['owner'], 'acc-tqs4c')
self.assertTrue(extra['public'])
self.assertEqual(extra['source'], 'oneiric-i386-20178.gz')
self.assertEqual(extra['source_type'], 'upload')
self.assertEqual(extra['status'], 'deprecated')
self.assertEqual(extra['username'], 'ubuntu')
self.assertEqual(extra['virtual_size'], 1025)
self.assertFalse('ancestor' in extra)
self.assertFalse('licence_name' in extra)
def test_list_locations(self):
locations = self.driver.list_locations()
self.assertEqual(locations[0].id, 'zon-6mxqw')
self.assertEqual(locations[0].name, 'gb1-a')
self.assertEqual(locations[1].id, 'zon-remk1')
self.assertEqual(locations[1].name, 'gb1-b')
def test_reboot_node_response(self):
node = self.driver.list_nodes()[0]
self.assertRaises(NotImplementedError, self.driver.reboot_node, [node])
def test_destroy_node(self):
node = self.driver.list_nodes()[0]
self.assertTrue(self.driver.destroy_node(node))
def test_create_node(self):
size = self.driver.list_sizes()[0]
image = self.driver.list_images()[0]
node = self.driver.create_node(
name='Test Node', image=image, size=size)
self.assertEqual('srv-p61uj', node.id)
self.assertEqual('Test Node', node.name)
self.assertEqual('gb1-a', node.extra['zone'].name)
def test_create_node_in_location(self):
size = self.driver.list_sizes()[0]
image = self.driver.list_images()[0]
location = self.driver.list_locations()[1]
node = self.driver.create_node(
name='Test Node', image=image, size=size, location=location)
self.assertEqual('srv-nnumd', node.id)
self.assertEqual('Test Node', node.name)
self.assertEqual('gb1-b', node.extra['zone'].name)
def test_create_node_with_user_data(self):
size = self.driver.list_sizes()[0]
image = self.driver.list_images()[0]
node = self.driver.create_node(
name='Test Node', image=image, size=size, ex_userdata=USER_DATA)
decoded = base64.b64decode(b(node.extra['user_data'])).decode('ascii')
self.assertEqual('gb1-a', node.extra['zone'].name)
self.assertEqual(USER_DATA, decoded)
def test_create_node_with_a_server_group(self):
size = self.driver.list_sizes()[0]
image = self.driver.list_images()[0]
node = self.driver.create_node(
name='Test Node', image=image, size=size, ex_servergroup='grp-12345')
self.assertEqual('gb1-a', node.extra['zone'].name)
self.assertEqual(len(node.extra['server_groups']), 1)
self.assertEqual(node.extra['server_groups'][0]['id'], 'grp-12345')
def test_create_node_with_a_list_of_server_groups(self):
size = self.driver.list_sizes()[0]
image = self.driver.list_images()[0]
node = self.driver.create_node(
name='Test Node', image=image, size=size, ex_servergroup=['grp-12345', 'grp-67890'])
self.assertEqual('gb1-a', node.extra['zone'].name)
self.assertEqual(len(node.extra['server_groups']), 2)
self.assertEqual(node.extra['server_groups'][0]['id'], 'grp-12345')
self.assertEqual(node.extra['server_groups'][1]['id'], 'grp-67890')
def test_list_cloud_ips(self):
cip_list = self.driver.ex_list_cloud_ips()
self.assertEqual(len(cip_list), 4)
self.assertEqual(cip_list[2]['status'], 'mapped')
cip_check = cip_list[0]
self.assertEqual(cip_check['id'], 'cip-tlrp3')
self.assertEqual(cip_check['public_ip'], '109.107.35.16')
self.assertEqual(
cip_check['reverse_dns'], 'cip-109-107-35-16.gb1.brightbox.com')
self.assertEqual(cip_check['status'], 'unmapped')
self.assertTrue(cip_check['server'] is None)
self.assertTrue(cip_check['server_group'] is None)
self.assertTrue(cip_check['interface'] is None)
self.assertTrue(cip_check['load_balancer'] is None)
def test_create_cloud_ip(self):
cip = self.driver.ex_create_cloud_ip()
self.assertEqual(cip['id'], 'cip-jsjc5')
self.assertEqual(
cip['reverse_dns'], 'cip-109-107-37-234.gb1.brightbox.com')
def test_create_cloud_ip_with_dns(self):
cip = self.driver.ex_create_cloud_ip('fred.co.uk')
self.assertEqual(cip['id'], 'cip-jsjc5')
self.assertEqual(cip['reverse_dns'], 'fred.co.uk')
def test_map_cloud_ip(self):
self.assertTrue(self.driver.ex_map_cloud_ip('cip-jsjc5', 'int-ztqbx'))
def test_unmap_cloud_ip(self):
self.assertTrue(self.driver.ex_unmap_cloud_ip('cip-jsjc5'))
def test_update_cloud_ip(self):
self.assertTrue(
self.driver.ex_update_cloud_ip('cip-jsjc5', 'fred.co.uk'))
def test_destroy_cloud_ip(self):
self.assertTrue(self.driver.ex_destroy_cloud_ip('cip-jsjc5'))
class BrightboxMockHttp(MockHttp):
fixtures = ComputeFileFixtures('brightbox')
def _token(self, method, url, body, headers):
if method == 'POST':
return self.test_response(httplib.OK, self.fixtures.load('token.json'))
def _token_INVALID_CLIENT(self, method, url, body, headers):
if method == 'POST':
return self.test_response(httplib.BAD_REQUEST, '{"error":"invalid_client"}')
def _token_UNAUTHORIZED_CLIENT(self, method, url, body, headers):
if method == 'POST':
return self.test_response(httplib.UNAUTHORIZED, '{"error":"unauthorized_client"}')
def _1_0_servers_INVALID_CLIENT(self, method, url, body, headers):
return self.test_response(httplib.BAD_REQUEST, '{"error":"invalid_client"}')
def _1_0_servers_UNAUTHORIZED_CLIENT(self, method, url, body, headers):
return self.test_response(httplib.UNAUTHORIZED, '{"error":"unauthorized_client"}')
def _1_0_images(self, method, url, body, headers):
if method == 'GET':
return self.test_response(httplib.OK, self.fixtures.load('list_images.json'))
def _1_0_servers(self, method, url, body, headers):
if method == 'GET':
return self.test_response(httplib.OK, self.fixtures.load('list_servers.json'))
elif method == 'POST':
body = json.loads(body)
encoded = base64.b64encode(b(USER_DATA)).decode('ascii')
if 'user_data' in body and body['user_data'] != encoded:
data = '{"error_name":"dodgy user data", "errors": ["User data not encoded properly"]}'
return self.test_response(httplib.BAD_REQUEST, data)
if body.get('zone', '') == 'zon-remk1':
node = json.loads(
self.fixtures.load('create_server_gb1_b.json'))
else:
node = json.loads(
self.fixtures.load('create_server_gb1_a.json'))
node['name'] = body['name']
if 'server_groups' in body:
node['server_groups'] = [{'id': x}
for x in body['server_groups']]
if 'user_data' in body:
node['user_data'] = body['user_data']
return self.test_response(httplib.ACCEPTED, json.dumps(node))
def _1_0_servers_srv_xvpn7(self, method, url, body, headers):
if method == 'DELETE':
return self.test_response(httplib.ACCEPTED, '')
def _1_0_server_types(self, method, url, body, headers):
if method == 'GET':
return self.test_response(httplib.OK, self.fixtures.load('list_server_types.json'))
def _1_0_zones(self, method, url, body, headers):
if method == 'GET':
if headers['Host'] == 'api.gbt.brightbox.com':
return self.test_response(httplib.OK, "{}")
else:
return self.test_response(httplib.OK, self.fixtures.load('list_zones.json'))
def _2_0_zones(self, method, url, body, headers):
data = '{"error_name":"unrecognised_endpoint", "errors": ["The request was for an unrecognised API endpoint"]}'
return self.test_response(httplib.BAD_REQUEST, data)
def _1_0_cloud_ips(self, method, url, body, headers):
if method == 'GET':
return self.test_response(httplib.OK, self.fixtures.load('list_cloud_ips.json'))
elif method == 'POST':
if body:
body = json.loads(body)
node = json.loads(self.fixtures.load('create_cloud_ip.json'))
if 'reverse_dns' in body:
node['reverse_dns'] = body['reverse_dns']
return self.test_response(httplib.ACCEPTED, json.dumps(node))
def _1_0_cloud_ips_cip_jsjc5(self, method, url, body, headers):
if method == 'DELETE':
return self.test_response(httplib.OK, '')
elif method == 'PUT':
body = json.loads(body)
if body.get('reverse_dns', None) == 'fred.co.uk':
return self.test_response(httplib.OK, '')
else:
return self.test_response(httplib.BAD_REQUEST, '{"error_name":"bad dns", "errors": ["Bad dns"]}')
def _1_0_cloud_ips_cip_jsjc5_map(self, method, url, body, headers):
if method == 'POST':
body = json.loads(body)
if 'destination' in body:
return self.test_response(httplib.ACCEPTED, '')
else:
data = '{"error_name":"bad destination", "errors": ["Bad destination"]}'
return self.test_response(httplib.BAD_REQUEST, data)
def _1_0_cloud_ips_cip_jsjc5_unmap(self, method, url, body, headers):
if method == 'POST':
return self.test_response(httplib.ACCEPTED, '')
def test_response(self, status, body):
return (status, body, {'content-type': 'application/json'}, httplib.responses[status])
if __name__ == '__main__':
sys.exit(unittest.main())
# vim: autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4
# filetype=python
Zerion Mini Shell 1.0