Updated Branches:
  refs/heads/trunk d6ca80926 -> b6fa496d7

LIBCLOUD-388: Added deploy_node for basic zone, improved consistency of params 
in create_node

Signed-off-by: Tomaz Muraus <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/54b778f2
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/54b778f2
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/54b778f2

Branch: refs/heads/trunk
Commit: 54b778f264a1f85bb9e82763e2fea4f3b961bfab
Parents: d6ca809
Author: Sebastien Goasguen <[email protected]>
Authored: Wed Aug 28 11:18:50 2013 -0400
Committer: Tomaz Muraus <[email protected]>
Committed: Thu Aug 29 13:20:51 2013 +0200

----------------------------------------------------------------------
 docs/compute/examples.rst                       |   3 +-
 .../create_cloudstack_node_keypair_secgroup.py  |   9 +-
 libcloud/compute/drivers/cloudstack.py          | 126 ++++++++++++++-----
 .../cloudstack/queryAsyncJobResult_17164.json   |   2 +-
 libcloud/test/compute/test_cloudstack.py        |   2 +-
 5 files changed, 102 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/54b778f2/docs/compute/examples.rst
----------------------------------------------------------------------
diff --git a/docs/compute/examples.rst b/docs/compute/examples.rst
index a9418aa..6d71233 100644
--- a/docs/compute/examples.rst
+++ b/docs/compute/examples.rst
@@ -100,7 +100,8 @@ Create a node on a CloudStack provider using a provided key 
pair and security gr
 
     This example assumes the provided key pair already exists. If the key pair
     doesn't exist yet, you can create it using the provider's own UI, or
-    :func:`ex_create_keypair` driver method.
+    :func:`ex_create_keypair` driver method. This functionality is only 
available
+    in trunk.
 
 This example demonstrates how to create a node using an existing key pair.
 Created node also gets added to the provided security groups.

http://git-wip-us.apache.org/repos/asf/libcloud/blob/54b778f2/docs/examples/compute/create_cloudstack_node_keypair_secgroup.py
----------------------------------------------------------------------
diff --git a/docs/examples/compute/create_cloudstack_node_keypair_secgroup.py 
b/docs/examples/compute/create_cloudstack_node_keypair_secgroup.py
index d1c8d90..8f04410 100644
--- a/docs/examples/compute/create_cloudstack_node_keypair_secgroup.py
+++ b/docs/examples/compute/create_cloudstack_node_keypair_secgroup.py
@@ -13,11 +13,7 @@ TEMPLATE_ID = 'id of the template you want to use'
 KEYPAIR_NAME = 'keypairname'
 
 # The security groups you want this node to be added to
-SECURITY_GROUP_NAMES = 'secgroup1, secgroup2'
-
-# Extra arguments to pass to node creation
-EXTRA_ARGS = {"keypair": KEYPAIR_NAME,
-              "securitygroupnames": SECURITY_GROUP_NAMES}
+SECURITY_GROUP_NAMES = ['secgroup1', 'secgroup2']
 
 cls = get_driver(Provider.CLOUDSTACK)
 driver = cls(key=ACCESS_ID, secret=SECRET_KEY, secure=True,
@@ -29,4 +25,5 @@ size = [s for s in sizes if s.id == SIZE_ID][0]
 image = [i for i in images if i.id == IMAGE_ID][0]
 
 node = driver.create_node(name='test-node-1', image=image, size=size,
-                          extra_args=EXTRA_ARGS)
+                          ex_security_groups=SECURITY_GROUP_NAMES,
+                          ex_keyname=KEYPAIR_NAME)

http://git-wip-us.apache.org/repos/asf/libcloud/blob/54b778f2/libcloud/compute/drivers/cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/cloudstack.py 
b/libcloud/compute/drivers/cloudstack.py
index b9c08db..d870cbf 100644
--- a/libcloud/compute/drivers/cloudstack.py
+++ b/libcloud/compute/drivers/cloudstack.py
@@ -16,11 +16,14 @@
 from __future__ import with_statement
 
 import os
+import base64
+
+from libcloud.utils.py3 import b
 
 from libcloud.compute.providers import Provider
 from libcloud.common.cloudstack import CloudStackDriverMixIn
 from libcloud.compute.base import Node, NodeDriver, NodeImage, NodeLocation,\
-    NodeSize, StorageVolume
+    NodeSize, StorageVolume, is_private_subnet
 from libcloud.compute.types import NodeState, LibcloudError
 
 
@@ -155,6 +158,8 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, 
NodeDriver):
     website = 'http://cloudstack.org/'
     type = Provider.CLOUDSTACK
 
+    features = {"create_node": ["ssh_key", "generates_password"]}
+
     NODE_STATE_MAP = {
         'Running': NodeState.RUNNING,
         'Starting': NodeState.REBOOTING,
@@ -251,6 +256,14 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, 
NodeDriver):
                     private_ips.append(nic['ipaddress'])
 
             public_ips = public_ips_map.get(vm['id'], {}).keys()
+            public_ips.extend([ip for ip in private_ips
+                              if not is_private_subnet(ip)])
+
+            keypair, password = None, None
+            if 'keypair' in vm.keys():
+                keypair = vm['keypair']
+            if 'password' in vm.keys():
+                password = vm['password']
 
             node = CloudStackNode(
                 id=vm['id'],
@@ -259,7 +272,11 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, 
NodeDriver):
                 public_ips=public_ips,
                 private_ips=private_ips,
                 driver=self,
-                extra={'zoneid': vm['zoneid'], }
+                extra={'zoneid': vm['zoneid'],
+                       'password': password,
+                       'key_name': keypair,
+                       'created': vm['created']
+                       }
             )
 
             addresses = public_ips_map.get(vm['id'], {}).items()
@@ -281,7 +298,6 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, 
NodeDriver):
             node.extra['ip_forwarding_rules'] = rules
 
             rules = []
-
             for addr in addrs:
                 result = self._sync_request('listPortForwardingRules')
                 for r in result.get('portforwardingrule', []):
@@ -310,57 +326,103 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, 
NodeDriver):
                                   0, self))
         return sizes
 
-    def create_node(self, name, size, image, location=None, extra_args=None,
-                    **kwargs):
+    def create_node(self, **kwargs):
         """
+        Create a new node
+
         @inherits: L{NodeDriver.create_node}
 
-        @keyword  extra_args: Extra argument passed to the
-        "deployVirtualMachine" call. A list of available arguments can be found
-        at http://cloudstack.apache.org/docs/api/apidocs-4.0.0/root_admin/ \
-           deployVirtualMachine.html
-        @type     extra_args:   C{dict}
+        @keyword    ex_keyname:  Name of existing keypair
+        @type       ex_keyname:  C{str}
 
-        @rtype: L{CloudStackNode}
-        """
+        @keyword    ex_userdata: String containing user data
+        @type       ex_userdata: C{str}
 
-        if extra_args:
-            request_args = extra_args.copy()
-        else:
-            request_args = {}
+        @keyword    networks: The server is launched into a set of Networks.
+        @type       networks: L{CloudStackNetwork}
 
-        if location is None:
-            location = self.list_locations()[0]
+        @keyword    ex_security_groups: List of security groups to assign to
+                                        the node
+        @type       ex_security_groups: C{list} of C{str}
 
-        if 'network_id' in kwargs:
-            request_args['networkids'] = kwargs['network_id']
+        @rtype: L{CloudStackNode}
+        """
 
-        result = self._async_request(
-            'deployVirtualMachine', name=name, displayname=name,
-            serviceofferingid=size.id, templateid=image.id,
-            zoneid=location.id, **request_args
-        )
+        server_params = self._create_args_to_params(None, **kwargs)
 
-        node = result['virtualmachine']
-        state = self.NODE_STATE_MAP[node['state']]
+        node = self._async_request('deployVirtualMachine',
+                                   **server_params)['virtualmachine']
 
         public_ips = []
-        private_ips = [nic['ipaddress'] for nic in node['nic']]
+        private_ips = []
+        for nic in node['nic']:
+            if is_private_subnet(nic['ipaddress']):
+                private_ips.append(nic['ipaddress'])
+            else:
+                public_ips.append(nic['ipaddress'])
+
+        keypair, password = None, None
+        if keypair in node.keys():
+            keypair = node['keypair']
+        if password in node.keys():
+            password = node['password']
 
         return CloudStackNode(
             id=node['id'],
             name=node['displayname'],
-            state=state,
+            state=self.NODE_STATE_MAP[node['state']],
             public_ips=public_ips,
             private_ips=private_ips,
             driver=self,
-            extra={'zoneid': location.id,
+            extra={'zoneid': server_params['zoneid'],
                    'ip_addresses': [],
                    'ip_forwarding_rules': [],
-                   'port_forwarding_rules': []
+                   'port_forwarding_rules': [],
+                   'password': password,
+                   'key_name': keypair,
+                   'created': node['created']
                    }
+
         )
 
+    def _create_args_to_params(self, node, **kwargs):
+        server_params = {
+            'name': kwargs.get('name'),
+        }
+
+        if 'name' in kwargs:
+            server_params['displayname'] = kwargs.get('name')
+
+        if 'size' in kwargs:
+            server_params['serviceofferingid'] = kwargs.get('size').id
+
+        if 'image' in kwargs:
+            server_params['templateid'] = kwargs.get('image').id
+
+        if 'location' in kwargs:
+            server_params['zoneid'] = kwargs.get('location').id
+        else:
+            server_params['zoneid'] = self.list_locations()[0].id
+
+        if 'ex_keyname' in kwargs:
+            server_params['keypair'] = kwargs['ex_keyname']
+
+        if 'ex_userdata' in kwargs:
+            server_params['userdata'] = base64.b64encode(
+                b(kwargs['ex_userdata'])).decode('ascii')
+
+        if 'networks' in kwargs:
+            networks = kwargs['networks']
+            networks = ','.join([network.id for network in networks])
+            server_params['networkids'] = networks
+
+        if 'ex_security_groups' in kwargs:
+            security_groups = kwargs['ex_security_groups']
+            security_groups = ','.join(security_groups)
+            server_params['securitygroupnames'] = security_groups
+
+        return server_params
+
     def destroy_node(self, node):
         """
         @inherits: L{NodeDriver.reboot_node}
@@ -642,6 +704,7 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, 
NodeDriver):
                                             public_port,
                                             private_port)
         node.extra['port_forwarding_rules'].append(rule)
+        node.public_ips.append(address)
         return rule
 
     def ex_delete_port_forwarding_rule(self, node, rule):
@@ -658,6 +721,7 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, 
NodeDriver):
         """
 
         node.extra['port_forwarding_rules'].remove(rule)
+        node.public_ips.remove(rule.address)
         res = self._async_request('deletePortForwardingRule', id=rule.id)
         return res['success']
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/54b778f2/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json
----------------------------------------------------------------------
diff --git 
a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json 
b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json
index 31fd39e..33dc746 100644
--- a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json
+++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17164.json
@@ -1 +1 @@
-{ "queryasyncjobresultresponse" : 
{"jobid":17164,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN
 Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 
10.04 Server x64 PV 
r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute
 Micro 
PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"1.1.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}}
 }
+{ "queryasyncjobresultresponse" : 
{"jobid":17164,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"virtualmachine":{"id":2602,"name":"fred","displayname":"fred","account":"fakeaccount","domainid":801,"domain":"AA000062-libcloud-dev","created":"2011-06-23T05:48:31+0000","state":"Running","haenable":false,"zoneid":1,"zonename":"Sydney","templateid":421,"templatename":"XEN
 Basic Ubuntu 10.04 Server x64 PV r2.0","templatedisplaytext":"XEN Basic Ubuntu 
10.04 Server x64 PV 
r2.0","passwordenabled":false,"serviceofferingid":105,"serviceofferingname":"Compute
 Micro 
PRD","cpunumber":1,"cpuspeed":1200,"memory":384,"guestosid":12,"rootdeviceid":0,"rootdevicetype":"IscsiLUN","securitygroup":[],"nic":[{"id":3893,"networkid":860,"netmask":"255.255.240.0","gateway":"1.1.1.1","ipaddress":"192.168.1.2","traffictype":"Guest","type":"Virtual","isdefault":true}],"hypervisor":"XenServer"}}}
 }

http://git-wip-us.apache.org/repos/asf/libcloud/blob/54b778f2/libcloud/test/compute/test_cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudstack.py 
b/libcloud/test/compute/test_cloudstack.py
index 575fe53..ece5f2a 100644
--- a/libcloud/test/compute/test_cloudstack.py
+++ b/libcloud/test/compute/test_cloudstack.py
@@ -98,7 +98,7 @@ class CloudStackNodeDriverTest(unittest.TestCase, 
TestCaseMixin):
 
         self.assertEqual(node.name, 'fred')
         self.assertEqual(node.public_ips, [])
-        self.assertEqual(node.private_ips, ['1.1.1.2'])
+        self.assertEqual(node.private_ips, ['192.168.1.2'])
         self.assertEqual(node.extra['zoneid'], default_location.id)
 
     def test_list_images_no_images_available(self):

Reply via email to