Author: tomaz
Date: Wed May 8 22:35:25 2013
New Revision: 1480490
URL: http://svn.apache.org/r1480490
Log:
Various bug fixes and improvements in the HostVirtual driver.
Contributed by Dinesh Bhoopathy, part of LIBCLOUD-249.
Modified:
libcloud/trunk/CHANGES
libcloud/trunk/libcloud/compute/drivers/hostvirtual.py
libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/create_node.json
libcloud/trunk/libcloud/test/compute/test_hostvirtual.py
Modified: libcloud/trunk/CHANGES
URL:
http://svn.apache.org/viewvc/libcloud/trunk/CHANGES?rev=1480490&r1=1480489&r2=1480490&view=diff
==============================================================================
--- libcloud/trunk/CHANGES (original)
+++ libcloud/trunk/CHANGES Wed May 8 22:35:25 2013
@@ -28,6 +28,10 @@ Changes with Apache Libcloud in deveplom
- Various improvements and bug-fixes in the VCloud driver. (LIBCLOUD-323)
[Michel Samia]
+ - Various bug fixes and improvements in the HostVirtual driver.
+ (LIBCLOUD-249)
+ [Dinesh Bhoopathy]
+
*) Load Balancer
- Add ex_list_current_usage method to the Rackspace driver.
Modified: libcloud/trunk/libcloud/compute/drivers/hostvirtual.py
URL:
http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/hostvirtual.py?rev=1480490&r1=1480489&r2=1480490&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/hostvirtual.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/hostvirtual.py Wed May 8 22:35:25
2013
@@ -17,14 +17,13 @@ libcloud driver for the Host Virtual Inc
Home page http://www.vr.org/
"""
+import time
+
try:
import simplejson as json
except ImportError:
import json
-
-from libcloud.utils.py3 import httplib
-
from libcloud.common.hostvirtual import HostVirtualResponse
from libcloud.common.hostvirtual import HostVirtualConnection
from libcloud.common.hostvirtual import HostVirtualException
@@ -36,7 +35,6 @@ from libcloud.compute.base import NodeAu
API_ROOT = '/vapi'
-#API_VERSION = '0.1'
NODE_STATE_MAP = {
'BUILDING': NodeState.PENDING,
'PENDING': NodeState.PENDING,
@@ -47,6 +45,8 @@ NODE_STATE_MAP = {
'TERMINATED': NodeState.TERMINATED # server is powered down
}
+DEFAULT_NODE_LOCATION_ID = 4
+
class HostVirtualComputeResponse(HostVirtualResponse):
pass
@@ -78,8 +78,8 @@ class HostVirtualNodeDriver(NodeDriver):
extra['image'] = data['os_id']
if 'location_id' in data:
extra['location'] = data['location_id']
-
- public_ips.append(data['ip'])
+ if 'ip' in data:
+ public_ips.append(data['ip'])
node = Node(id=data['mbpkgid'], name=data['fqdn'], state=state,
public_ips=public_ips, private_ips=private_ips,
@@ -137,40 +137,59 @@ class HostVirtualNodeDriver(NodeDriver):
nodes.append(node)
return nodes
+ def _wait_for_node(self, node_id, timeout=30, interval=5.0):
+ """
+ @param node_id: ID of the node to wait for.
+ @type node_id: C{int}
+
+ @param timeout: Timeout (in seconds).
+ @type timeout: C{int}
+
+ @param interval: How long to wait (in seconds) between each attempt.
+ @type interval: C{float}
+ """
+ # poll until we get a node
+ for i in range(0, timeout, int(interval)):
+ try:
+ node = self.ex_get_node(node_id)
+ return node
+ except HostVirtualException:
+ time.sleep(interval)
+
+ raise HostVirtualException(412, 'Timedout on getting node details')
+
def create_node(self, **kwargs):
- name = kwargs['name'] # expects fqdn ex: test.com
+ dc = None
+
size = kwargs['size']
image = kwargs['image']
- auth = kwargs['auth']
- dc = None
- if "location" in kwargs:
- dc = kwargs["location"].id
- else:
- dc = '3'
+ params = {'plan': size.name}
- params = {'fqdn': name,
- 'plan': size.name,
- 'image': image.id,
- 'location': dc
- }
+ dc = DEFAULT_NODE_LOCATION_ID
+ if 'location' in kwargs:
+ dc = kwargs['location'].id
- 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/buy_build',
+ # simply order a package first
+ result = self.connection.request(API_ROOT + '/cloud/buy/',
data=json.dumps(params),
method='POST').object
- return self._to_node(result)
+
+ # create a stub node
+ stub_node = self._to_node({
+ 'mbpkgid': result['id'],
+ 'status': 'PENDING',
+ 'fqdn': kwargs['name'],
+ 'plan_id': size.id,
+ 'os_id': image.id,
+ 'location_id': dc
+ })
+
+ # provisioning a server using the stub node
+ self.ex_provision_node(node=stub_node, auth=kwargs['auth'])
+
+ node = self._wait_for_node(stub_node.id)
+ return node
def reboot_node(self, node):
params = {'force': 0, 'mbpkgid': node.id}
@@ -182,7 +201,11 @@ class HostVirtualNodeDriver(NodeDriver):
return bool(result)
def destroy_node(self, node):
- params = {'mbpkgid': node.id}
+ params = {
+ 'mbpkgid': node.id,
+ #'reason': 'Submitted through Libcloud API'
+ }
+
result = self.connection.request(
API_ROOT + '/cloud/cancel', data=json.dumps(params),
method='POST').object
@@ -216,7 +239,7 @@ class HostVirtualNodeDriver(NodeDriver):
"""
params = {'force': 0, 'mbpkgid': node.id}
result = self.connection.request(
- API_ROOT + '/cloud/server/stop',
+ API_ROOT + '/cloud/server/shutdown',
data=json.dumps(params),
method='POST').object
@@ -239,9 +262,9 @@ class HostVirtualNodeDriver(NodeDriver):
return bool(result)
- def ex_build_node(self, **kwargs):
+ def ex_provision_node(self, **kwargs):
"""
- Build a server on a VR package and get it booted
+ Provision a server on a VR package and get it booted
@keyword node: node which should be used
@type node: L{Node}
@@ -255,7 +278,8 @@ class HostVirtualNodeDriver(NodeDriver):
@keyword location: which datacenter to create the server in
@type location: L{NodeLocation}
- @rtype: C{bool}
+ @return: Node representing the newly built server
+ @rtype: L{Node}
"""
node = kwargs['node']
Modified:
libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/create_node.json
URL:
http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/create_node.json?rev=1480490&r1=1480489&r2=1480490&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/create_node.json
(original)
+++ libcloud/trunk/libcloud/test/compute/fixtures/hostvirtual/create_node.json
Wed May 8 22:35:25 2013
@@ -1,17 +1,3 @@
{
- "mbpkgid": "76070",
- "package_status": "Active",
- "domu_package": null,
- "rescue": null,
- "locked": null,
- "state": null,
- "installed": null,
- "package": null,
- "ipv6": "",
- "city": null,
- "fqdn": "test.com",
- "uptime": false,
- "ip": null,
- "name": "VR512",
- "status": "BUILDING"
+ "id": "62291"
}
Modified: libcloud/trunk/libcloud/test/compute/test_hostvirtual.py
URL:
http://svn.apache.org/viewvc/libcloud/trunk/libcloud/test/compute/test_hostvirtual.py?rev=1480490&r1=1480489&r2=1480490&view=diff
==============================================================================
--- libcloud/trunk/libcloud/test/compute/test_hostvirtual.py (original)
+++ libcloud/trunk/libcloud/test/compute/test_hostvirtual.py Wed May 8
22:35:25 2013
@@ -103,13 +103,21 @@ class HostVirtualTest(unittest.TestCase)
size=size,
auth=auth
)
- self.assertEqual('76070', node.id)
- self.assertEqual('test.com', node.name)
+ self.assertEqual('62291', node.id)
+ self.assertEqual('server1.vr-cluster.org', node.name)
- def test_ex_build_node(self):
+ def test_ex_provision_node(self):
node = self.driver.list_nodes()[0]
auth = NodeAuthPassword('vr!@#hosted#@!')
- self.assertTrue(self.driver.ex_build_node(
+ self.assertTrue(self.driver.ex_provision_node(
+ node=node,
+ auth=auth
+ ))
+
+ def test_ex_provision_node(self):
+ node = self.driver.list_nodes()[0]
+ auth = NodeAuthPassword('vr!@#hosted#@!')
+ self.assertTrue(self.driver.ex_provision_node(
node=node,
auth=auth
))
@@ -126,8 +134,8 @@ class HostVirtualTest(unittest.TestCase)
auth=auth,
location=location
)
- self.assertEqual('76070', node.id)
- self.assertEqual('test.com', node.name)
+ self.assertEqual('62291', node.id)
+ self.assertEqual('server1.vr-cluster.org', node.name)
class HostVirtualMockHttp(MockHttp):
@@ -161,7 +169,7 @@ class HostVirtualMockHttp(MockHttp):
body = self.fixtures.load('node_reboot.json')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
- def _vapi_cloud_server_stop(self, method, url, body, headers):
+ def _vapi_cloud_server_shutdown(self, method, url, body, headers):
body = self.fixtures.load('node_stop.json')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
@@ -169,7 +177,7 @@ class HostVirtualMockHttp(MockHttp):
body = self.fixtures.load('node_start.json')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])
- def _vapi_cloud_buy_build(self, method, url, body, headers):
+ def _vapi_cloud_buy(self, method, url, body, headers):
body = self.fixtures.load('create_node.json')
return (httplib.OK, body, {}, httplib.responses[httplib.OK])