Author: tomaz
Date: Tue Feb 5 19:26:10 2013
New Revision: 1442703
URL: http://svn.apache.org/viewvc?rev=1442703&view=rev
Log:
Minor improvements in the HostVirtual driver and add new ex_get_node and
ex_build_node extension method.
Contributed by Dinesh Bhoopathy, part of LIBCLOUD-249.
Added:
libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/get_node.json
Modified:
libcloud/trunk/CHANGES
libcloud/trunk/libcloud/common/hostvirtual.py
libcloud/trunk/libcloud/compute/drivers/hostvirtual.py
libcloud/trunk/libcloud/dns/drivers/hostvirtual.py
libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/list_nodes.json
libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/list_sizes.json
libcloud/trunk/libcloud/test/compute/test_hostvirtual.py
Modified: libcloud/trunk/CHANGES
URL:
http://svn.apache.org/viewvc/libcloud/trunk/CHANGES?rev=1442703&r1=1442702&r2=1442703&view=diff
==============================================================================
--- libcloud/trunk/CHANGES (original)
+++ libcloud/trunk/CHANGES Tue Feb 5 19:26:10 2013
@@ -144,6 +144,10 @@ Changes with Apache Libcloud in developm
Also update pricing to reflect new (decreased) prices.
[Tomaz Muraus]
+ - Minor improvements in the HostVirtual driver and add new ex_get_node and
+ ex_build_node extension method. (LIBCLOUD-249)
+ [Dinesh Bhoopathy]
+
*) Storage
- Add a new local storage driver.
Modified: libcloud/trunk/libcloud/common/hostvirtual.py
URL:
http://svn.apache.org/viewvc/libcloud/trunk/libcloud/common/hostvirtual.py?rev=1442703&r1=1442702&r2=1442703&view=diff
==============================================================================
--- libcloud/trunk/libcloud/common/hostvirtual.py (original)
+++ libcloud/trunk/libcloud/common/hostvirtual.py Tue Feb 5 19:26:10 2013
@@ -19,6 +19,7 @@ except ImportError:
from libcloud.utils.py3 import httplib
from libcloud.common.base import ConnectionKey, JsonResponse
+from libcloud.compute.types import InvalidCredsError
from libcloud.common.types import LibcloudError
API_HOST = 'www.vr.org'
@@ -57,13 +58,10 @@ class HostVirtualResponse(JsonResponse):
return data
def parse_error(self):
- context = self.connection.context
data = self.parse_body()
- status = int(self.status)
if self.status == httplib.UNAUTHORIZED:
- raise InvalidCredsError(
- data['error']['code'] + ': ' + data['error']['message'])
+ raise InvalidCredsError('%(code)s:%(message)s' % (data['error']))
elif self.status == httplib.PRECONDITION_FAILED:
raise HostVirtualException(
data['error']['code'], data['error']['message'])
Modified: libcloud/trunk/libcloud/compute/drivers/hostvirtual.py
URL:
http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/hostvirtual.py?rev=1442703&r1=1442702&r2=1442703&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/hostvirtual.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/hostvirtual.py Tue Feb 5 19:26:10
2013
@@ -29,7 +29,7 @@ from libcloud.common.hostvirtual import
from libcloud.common.hostvirtual import HostVirtualConnection
from libcloud.common.hostvirtual import HostVirtualException
from libcloud.compute.providers import Provider
-from libcloud.compute.types import NodeState, InvalidCredsError
+from libcloud.compute.types import NodeState
from libcloud.compute.base import Node, NodeDriver
from libcloud.compute.base import NodeImage, NodeSize, NodeLocation
from libcloud.compute.base import NodeAuthSSHKey, NodeAuthPassword
@@ -72,6 +72,13 @@ class HostVirtualNodeDriver(NodeDriver):
private_ips = []
extra = {}
+ if 'plan_id' in data:
+ extra['size'] = data['plan_id']
+ if 'os_id' in data:
+ extra['image'] = data['os_id']
+ if 'location_id' in data:
+ extra['location'] = data['location_id']
+
public_ips.append(data['ip'])
node = Node(id=data['mbpkgid'], name=data['fqdn'], state=state,
@@ -99,7 +106,7 @@ class HostVirtualNodeDriver(NodeDriver):
data=json.dumps(params)).object
sizes = []
for size in result:
- n = NodeSize(id=size['plan'],
+ n = NodeSize(id=size['plan_id'],
name=size['plan'],
ram=size['ram'],
disk=size['disk'],
@@ -116,9 +123,9 @@ class HostVirtualNodeDriver(NodeDriver):
i = NodeImage(id=image["id"],
name=image["os"],
driver=self.connection.driver,
- extra={
- 'hypervisor': image['tech'],
- 'arch': image['bits']})
+ extra=image)
+ del i.extra['id']
+ del i.extra['os']
images.append(i)
return images
@@ -143,7 +150,7 @@ class HostVirtualNodeDriver(NodeDriver):
dc = '3'
params = {'fqdn': name,
- 'plan': size.id,
+ 'plan': size.name,
'image': image.id,
'location': dc
}
@@ -158,10 +165,7 @@ class HostVirtualNodeDriver(NodeDriver):
params['password'] = password
if not ssh_key and not password:
- raise HostVirtualException(500, "Need SSH key or root password")
-
- if password is None:
- raise HostVirtualException(500, "Root password cannot be empty")
+ raise HostVirtualException(500, "Need SSH key or Root password")
result = self.connection.request(API_ROOT + '/cloud/buy_build',
data=json.dumps(params),
@@ -185,6 +189,22 @@ class HostVirtualNodeDriver(NodeDriver):
return bool(result)
+ def ex_get_node(self, node_id):
+ """
+ Get a single node.
+
+ @param node_id: id of the node that we need the node object for
+ @type node_id: C{str}
+
+ @rtype: L{Node}
+ """
+
+ params = {'mbpkgid': node_id}
+ result = self.connection.request(
+ API_ROOT + '/cloud/server', params=params).object
+ node = self._to_node(result)
+ return node
+
def ex_stop_node(self, node):
"""
Stop a node.
@@ -218,3 +238,72 @@ class HostVirtualNodeDriver(NodeDriver):
method='POST').object
return bool(result)
+
+ def ex_build_node(self, **kwargs):
+ """
+ Build a server on a VR package and get it booted
+
+ @keyword node: node which should be used
+ @type node: L{Node}
+
+ @keyword image: The distribution to deploy on your server (mandatory)
+ @type image: L{NodeImage}
+
+ @keyword auth: an SSH key or root password (mandatory)
+ @type auth: L{NodeAuthSSHKey} or L{NodeAuthPassword}
+
+ @keyword location: which datacenter to create the server in
+ @type location: L{NodeLocation}
+
+ @rtype: C{bool}
+ """
+
+ node = kwargs['node']
+
+ if 'image' in kwargs:
+ image = kwargs['image']
+ else:
+ image = node.extra['image']
+
+ params = {
+ 'mbpkgid': node.id,
+ 'image': image,
+ 'fqdn': node.name,
+ 'location': node.extra['location'],
+ }
+
+ auth = kwargs['auth']
+
+ ssh_key = None
+ password = None
+ if isinstance(auth, NodeAuthSSHKey):
+ ssh_key = auth.pubkey
+ params['ssh_key'] = ssh_key
+ elif isinstance(auth, NodeAuthPassword):
+ password = auth.password
+ params['password'] = password
+
+ if not ssh_key and not password:
+ raise HostVirtualException(500, "Need SSH key or Root password")
+
+ result = self.connection.request(API_ROOT + '/cloud/server/build',
+ data=json.dumps(params),
+ method='POST').object
+ return bool(result)
+
+ def ex_delete_node(self, node):
+ """
+ Delete a node.
+
+ @param node: Node which should be used
+ @type node: L{Node}
+
+ @rtype: C{bool}
+ """
+
+ params = {'mbpkgid': node.id}
+ result = self.connection.request(
+ API_ROOT + '/cloud/server/delete', data=json.dumps(params),
+ method='POST').object
+
+ return bool(result)
Modified: libcloud/trunk/libcloud/dns/drivers/hostvirtual.py
URL:
http://svn.apache.org/viewvc/libcloud/trunk/libcloud/dns/drivers/hostvirtual.py?rev=1442703&r1=1442702&r2=1442703&view=diff
==============================================================================
--- libcloud/trunk/libcloud/dns/drivers/hostvirtual.py (original)
+++ libcloud/trunk/libcloud/dns/drivers/hostvirtual.py Tue Feb 5 19:26:10 2013
@@ -21,8 +21,6 @@ from libcloud.utils.misc import merge_va
from libcloud.common.hostvirtual import HostVirtualResponse
from libcloud.common.hostvirtual import HostVirtualConnection
from libcloud.compute.drivers.hostvirtual import API_ROOT
-from libcloud.compute.drivers.hostvirtual import HostVirtualConnection
-from libcloud.compute.drivers.hostvirtual import HostVirtualResponse
from libcloud.dns.types import Provider, RecordType
from libcloud.dns.types import ZoneDoesNotExistError, RecordDoesNotExistError
from libcloud.dns.base import DNSDriver, Zone, Record
Added: libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/get_node.json
URL:
http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/get_node.json?rev=1442703&view=auto
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/get_node.json
(added)
+++ libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/get_node.json Tue
Feb 5 19:26:10 2013
@@ -0,0 +1,16 @@
+{
+ "host": "659",
+ "rescue": "0",
+ "fqdn": "server1.vr-cluster.org",
+ "mbpkgid": "62291",
+ "locked": "0",
+ "os_id": "1613",
+ "os": "Debian 6 i386 PV",
+ "ip": "208.111.45.250",
+ "installed": "0",
+ "state": "DOWN",
+ "package": "VR512",
+ "ipv6": "2607:f740:10::f98",
+ "city": "MAA - Chennai (Madras), India",
+ "status": "TERMINATED"
+}
Modified:
libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/list_nodes.json
URL:
http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/list_nodes.json?rev=1442703&r1=1442702&r2=1442703&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/list_nodes.json
(original)
+++ libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/list_nodes.json
Tue Feb 5 19:26:10 2013
@@ -1,62 +1,72 @@
-[
- {
- "host": "659",
- "rescue": "0",
- "fqdn": "server1.vr-cluster.org",
- "mbpkgid": "62291",
- "locked": "0",
- "os": "Debian 6 i386 PV",
- "ip": "208.111.45.250",
- "installed": "0",
- "state": "DOWN",
- "package": "VR512",
- "ipv6": "2607:f740:10::f98",
- "city": "MAA - Chennai (Madras), India",
- "status": "TERMINATED"
- },
- {
- "host": "902",
- "rescue": "0",
- "fqdn": "newbuild.vr.com",
- "mbpkgid": "62327",
- "locked": "0",
- "os": "CentOS 5.8 x64",
- "ip": "208.111.39.118",
- "installed": "0",
- "state": "DOWN",
- "package": "VR512",
- "ipv6": "2607:f740:0:3f::f0d",
- "city": "SJC - San Jose, CA",
- "status": "TERMINATED"
- },
- {
- "host": "1010",
- "rescue": "0",
- "fqdn": "3test.build.com",
- "mbpkgid": "62300",
- "locked": "0",
- "os": "CentOS 6.2 x64",
- "ip": "208.111.40.179",
- "installed": "0",
- "state": "DOWN",
- "package": "VR512",
- "ipv6": "2607:f740:c::f4f",
- "city": "LAX3 - Los Angeles, CA",
- "status": "TERMINATED"
- },
- {
- "host": "1028",
- "rescue": "0",
- "fqdn": "libcloud2.node.com",
- "mbpkgid": "74567",
- "locked": "0",
- "os": "CentOS 5.8 x64",
- "ip": "209.177.157.99",
- "installed": "1",
- "state": "UP",
- "package": "VR512",
- "ipv6": "2607:f740:b::eff",
- "city": "IAD2- Reston, VA",
- "status": "RUNNING"
- }
-]
+[{
+ "host": "659",
+ "rescue": "0",
+ "fqdn": "server1.vr-cluster.org",
+ "mbpkgid": "62291",
+ "locked": "0",
+ "os": "Debian 6 i386 PV",
+ "ip": "208.111.45.250",
+ "installed": "0",
+ "state": "DOWN",
+ "package": "VR512",
+ "ipv6": "2607:f740:10::f98",
+ "city": "MAA - Chennai (Madras), India",
+ "status": "TERMINATED",
+ "os_id" : "1613",
+ "location_id" : "3",
+ "plan_id" : "51"
+},
+{
+ "host": "902",
+ "rescue": "0",
+ "fqdn": "newbuild.vr.com",
+ "mbpkgid": "62327",
+ "locked": "0",
+ "os": "CentOS 5.8 x64",
+ "ip": "208.111.39.118",
+ "installed": "0",
+ "state": "DOWN",
+ "package": "VR512",
+ "ipv6": "2607:f740:0:3f::f0d",
+ "city": "SJC - San Jose, CA",
+ "status": "TERMINATED",
+ "os_id" : "1613",
+ "location_id" : "3",
+ "plan_id" : "51"
+},
+{
+ "host": "1010",
+ "rescue": "0",
+ "fqdn": "3test.build.com",
+ "mbpkgid": "62300",
+ "locked": "0",
+ "os": "CentOS 6.2 x64",
+ "ip": "208.111.40.179",
+ "installed": "0",
+ "state": "DOWN",
+ "package": "VR512",
+ "ipv6": "2607:f740:c::f4f",
+ "city": "LAX3 - Los Angeles, CA",
+ "status": "TERMINATED",
+ "os_id" : "1613",
+ "location_id" : "3",
+ "plan_id" : "51"
+},
+{
+ "host": "1028",
+ "rescue": "0",
+ "fqdn": "libcloud2.node.com",
+ "mbpkgid": "74567",
+ "locked": "0",
+ "os": "CentOS 5.8 x64",
+ "ip": "209.177.157.99",
+ "installed": "1",
+ "state": "UP",
+ "package": "VR512",
+ "ipv6": "2607:f740:b::eff",
+ "city": "IAD2- Reston, VA",
+ "status": "RUNNING",
+ "os_id" : "1613",
+ "location_id" : "3",
+ "plan_id" : "51"
+}]
Modified:
libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/list_sizes.json
URL:
http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/list_sizes.json?rev=1442703&r1=1442702&r2=1442703&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/list_sizes.json
(original)
+++ libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/list_sizes.json
Tue Feb 5 19:26:10 2013
@@ -1,82 +1,128 @@
[
{
+ "plan_id": "31",
"plan": "VR256",
"ram": "256MB",
"disk": "10GB",
"transfer": "200GB",
"price": "10.00",
- "available": "1421"
+ "available": "1167"
},
{
+ "plan_id": "41",
"plan": "VR384",
"ram": "384MB",
"disk": "15GB",
"transfer": "300GB",
"price": "15.00",
- "available": "939"
+ "available": "768"
},
{
+ "plan_id": "51",
"plan": "VR512",
"ram": "512MB",
"disk": "20GB",
"transfer": "400GB",
"price": "20.00",
- "available": "713"
+ "available": "620"
},
{
+ "plan_id": "61",
"plan": "VR768",
"ram": "768MB",
"disk": "30GB",
"transfer": "600GB",
"price": "30.00",
- "available": "476"
+ "available": "403"
},
{
+ "plan_id": "71",
"plan": "VR1024",
"ram": "1024MB",
"disk": "40GB",
"transfer": "800GB",
"price": "40.00",
- "available": "350"
+ "available": "304"
},
{
+ "plan_id": "81",
"plan": "VR1280",
"ram": "1280MB",
"disk": "50GB",
"transfer": "1000GB",
"price": "50.00",
- "available": "276"
+ "available": "234"
},
{
+ "plan_id": "91",
"plan": "VR1536",
"ram": "1536MB",
"disk": "60GB",
"transfer": "1200GB",
"price": "60.00",
- "available": "226"
+ "available": "190"
},
{
+ "plan_id": "101",
"plan": "VR2048",
"ram": "2048MB",
"disk": "80GB",
"transfer": "1600GB",
"price": "80.00",
- "available": "160"
+ "available": "138"
},
{
+ "plan_id": "128",
+ "plan": "VRBL1G",
+ "ram": "1024MB",
+ "disk": "50GB",
+ "transfer": "1000GB",
+ "price": "150.00",
+ "available": "34"
+ },
+ {
+ "plan_id": "111",
"plan": "VR4048",
"ram": "4048MB",
"disk": "160GB",
"transfer": "3200GB",
"price": "160.00",
- "available": "69"
+ "available": "60"
+ },
+ {
+ "plan_id": "137",
+ "plan": "VRBL2G",
+ "ram": "2048MB",
+ "disk": "100GB",
+ "transfer": "2000GB",
+ "price": "200.00",
+ "available": "16"
+ },
+ {
+ "plan_id": "146",
+ "plan": "VRBL4G",
+ "ram": "4048MB",
+ "disk": "150GB",
+ "transfer": "3000GB",
+ "price": "300.00",
+ "available": "8"
},
{
+ "plan_id": "119",
"plan": "VR8096",
"ram": "8096MB",
"disk": "320GB",
"transfer": "6400GB",
"price": "320.00",
- "available": "9"
+ "available": "11"
+ },
+ {
+ "plan_id": "155",
+ "plan": "VRBL8G",
+ "ram": "8096MB",
+ "disk": "200GB",
+ "transfer": "5000GB",
+ "price": "400.00",
+ "available": "4"
}
]
Modified: libcloud/trunk/libcloud/test/compute/test_hostvirtual.py
URL:
http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/test_hostvirtual.py?rev=1442703&r1=1442702&r2=1442703&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/test_hostvirtual.py (original)
+++ libcloud/trunk/libcloud/test/compute/test_hostvirtual.py Tue Feb 5
19:26:10 2013
@@ -45,9 +45,9 @@ class HostVirtualTest(unittest.TestCase)
def test_list_sizes(self):
sizes = self.driver.list_sizes()
- self.assertEqual(len(sizes), 10)
- self.assertEqual(sizes[0].id, 'VR256')
- self.assertEqual(sizes[4].id, 'VR1024')
+ self.assertEqual(len(sizes), 14)
+ self.assertEqual(sizes[0].id, '31')
+ self.assertEqual(sizes[4].id, '71')
self.assertEqual(sizes[2].ram, '512MB')
self.assertEqual(sizes[2].disk, '20GB')
self.assertEqual(sizes[3].bandwidth, '600GB')
@@ -70,11 +70,18 @@ class HostVirtualTest(unittest.TestCase)
node = self.driver.list_nodes()[0]
self.assertTrue(self.driver.reboot_node(node))
- def test_stop_node(self):
+ def test_ex_get_node(self):
+ node = self.driver.ex_get_node(node_id='62291')
+ self.assertEqual(node.id, '62291')
+ self.assertEqual(node.name, 'server1.vr-cluster.org')
+ self.assertEqual(node.state, NodeState.TERMINATED)
+ self.assertTrue('208.111.45.250' in node.public_ips)
+
+ def test_ex_stop_node(self):
node = self.driver.list_nodes()[0]
self.assertTrue(self.driver.ex_stop_node(node))
- def test_start_node(self):
+ def test_ex_start_node(self):
node = self.driver.list_nodes()[0]
self.assertTrue(self.driver.ex_start_node(node))
@@ -82,6 +89,10 @@ class HostVirtualTest(unittest.TestCase)
node = self.driver.list_nodes()[0]
self.assertTrue(self.driver.destroy_node(node))
+ def test_ex_delete_node(self):
+ node = self.driver.list_nodes()[0]
+ self.assertTrue(self.driver.ex_delete_node(node))
+
def test_create_node(self):
auth = NodeAuthPassword('vr!@#hosted#@!')
size = self.driver.list_sizes()[0]
@@ -95,6 +106,14 @@ class HostVirtualTest(unittest.TestCase)
self.assertEqual('76070', node.id)
self.assertEqual('test.com', node.name)
+ def test_ex_build_node(self):
+ node = self.driver.list_nodes()[0]
+ auth = NodeAuthPassword('vr!@#hosted#@!')
+ self.assertTrue(self.driver.ex_build_node(
+ node=node,
+ auth=auth
+ ))
+
def test_create_node_in_location(self):
auth = NodeAuthPassword('vr!@#hosted#@!')
size = self.driver.list_sizes()[0]
@@ -118,6 +137,10 @@ class HostVirtualMockHttp(MockHttp):
body = self.fixtures.load('list_nodes.json')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ def _vapi_cloud_server(self, method, url, body, headers):
+ body = self.fixtures.load('get_node.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
def _vapi_cloud_sizes(self, method, url, body, headers):
body = self.fixtures.load('list_sizes.json')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
@@ -150,6 +173,14 @@ class HostVirtualMockHttp(MockHttp):
body = self.fixtures.load('create_node.json')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+ def _vapi_cloud_server_build(self, method, url, body, headers):
+ body = self.fixtures.load('create_node.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+ def _vapi_cloud_server_delete(self, method, url, body, headers):
+ body = self.fixtures.load('node_destroy.json')
+ return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
if __name__ == '__main__':
sys.exit(unittest.main())