libcloud-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From to...@apache.org
Subject [2/3] git commit: Add CloudStackProject class. Add option to select project and disk offering on node creation.
Date Fri, 07 Mar 2014 21:51:52 GMT
Add CloudStackProject class. Add option to select project and disk offering on
node creation.

Closes #257.

Signed-off-by: Tomaz Muraus <tomaz@apache.org>


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

Branch: refs/heads/trunk
Commit: 583bfba634a74c0f1c43a987de44e4b9f6bd8e7b
Parents: aa509b0
Author: Jim Divine <jdivine@gmail.com>
Authored: Wed Mar 5 13:39:28 2014 -0600
Committer: Tomaz Muraus <tomaz@apache.org>
Committed: Fri Mar 7 22:45:14 2014 +0100

----------------------------------------------------------------------
 libcloud/compute/drivers/cloudstack.py          | 159 +++++++++++++++++--
 .../deployVirtualMachine_deployproject.json     |   1 +
 .../cloudstack/listProjects_default.json        |  49 ++++++
 .../cloudstack/queryAsyncJobResult_11117.json   |  63 ++++++++
 libcloud/test/compute/test_cloudstack.py        |  33 ++++
 5 files changed, 291 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/583bfba6/libcloud/compute/drivers/cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/cloudstack.py b/libcloud/compute/drivers/cloudstack.py
index 5d66e8d..83e09b8 100644
--- a/libcloud/compute/drivers/cloudstack.py
+++ b/libcloud/compute/drivers/cloudstack.py
@@ -157,6 +157,14 @@ RESOURCE_EXTRA_ATTRIBUTES_MAP = {
         'hypervisor': {
             'key_name': 'hypervisor',
             'transform_func': str
+        },
+        'project': {
+            'key_name': 'project',
+            'transform_func': str
+        },
+        'project_id': {
+            'key_name': 'projectid',
+            'transform_func': str
         }
     },
     'volume': {
@@ -188,6 +196,58 @@ RESOURCE_EXTRA_ATTRIBUTES_MAP = {
             'key_name': 'zonename',
             'transform_func': str
         }
+    },
+    'project': {
+        'account': {'key_name': 'account', 'transform_func': str},
+        'cpuavailable': {'key_name': 'cpuavailable', 'transform_func': int},
+        'cpulimit': {'key_name': 'cpulimit', 'transform_func': int},
+        'cputotal': {'key_name': 'cputotal', 'transform_func': int},
+        'domain': {'key_name': 'domain', 'transform_func': str},
+        'domainid': {'key_name': 'domainid', 'transform_func': str},
+        'ipavailable': {'key_name': 'ipavailable', 'transform_func': int},
+        'iplimit': {'key_name': 'iplimit', 'transform_func': int},
+        'iptotal': {'key_name': 'iptotal', 'transform_func': int},
+        'memoryavailable': {'key_name': 'memoryavailable',
+                            'transform_func': int},
+        'memorylimit': {'key_name': 'memorylimit', 'transform_func': int},
+        'memorytotal': {'key_name': 'memorytotal', 'transform_func': int},
+        'networkavailable': {'key_name': 'networkavailable',
+                             'transform_func': int},
+        'networklimit': {'key_name': 'networklimit', 'transform_func': int},
+        'networktotal': {'key_name': 'networktotal', 'transform_func': int},
+        'primarystorageavailable': {'key_name': 'primarystorageavailable',
+                                    'transform_func': int},
+        'primarystoragelimit': {'key_name': 'primarystoragelimit',
+                                'transform_func': int},
+        'primarystoragetotal': {'key_name': 'primarystoragetotal',
+                                'transform_func': int},
+        'secondarystorageavailable': {'key_name': 'secondarystorageavailable',
+                                      'transform_func': int},
+        'secondarystoragelimit': {'key_name': 'secondarystoragelimit',
+                                  'transform_func': int},
+        'secondarystoragetotal': {'key_name': 'secondarystoragetotal',
+                                  'transform_func': int},
+        'snapshotavailable': {'key_name': 'snapshotavailable',
+                              'transform_func': int},
+        'snapshotlimit': {'key_name': 'snapshotlimit', 'transform_func': int},
+        'snapshottotal': {'key_name': 'snapshottotal', 'transform_func': int},
+        'state': {'key_name': 'state', 'transform_func': str},
+        'tags': {'key_name': 'tags', 'transform_func': str},
+        'templateavailable': {'key_name': 'templateavailable',
+                              'transform_func': int},
+        'templatelimit': {'key_name': 'templatelimit', 'transform_func': int},
+        'templatetotal': {'key_name': 'templatetotal', 'transform_func': int},
+        'vmavailable': {'key_name': 'vmavailable', 'transform_func': int},
+        'vmlimit': {'key_name': 'vmlimit', 'transform_func': int},
+        'vmrunning': {'key_name': 'vmrunning', 'transform_func': int},
+        'vmtotal': {'key_name': 'vmtotal', 'transform_func': int},
+        'volumeavailable': {'key_name': 'volumeavailable',
+                            'transform_func': int},
+        'volumelimit': {'key_name': 'volumelimit', 'transform_func': int},
+        'volumetotal': {'key_name': 'volumetotal', 'transform_func': int},
+        'vpcavailable': {'key_name': 'vpcavailable', 'transform_func': int},
+        'vpclimit': {'key_name': 'vpclimit', 'transform_func': int},
+        'vpctotal': {'key_name': 'vpctotal', 'transform_func': int}
     }
 }
 
@@ -402,6 +462,25 @@ class CloudStackNetwork(object):
                    self.networkofferingid, self.zoneid, self.driver.name))
 
 
+class CloudStackProject(object):
+    """
+    Class representing a CloudStack Project.
+    """
+
+    def __init__(self, id, name, display_text, driver, extra=None):
+        self.id = id
+        self.name = name
+        self.display_text = display_text
+        self.driver = driver
+        self.extra = extra or {}
+
+    def __repr__(self):
+        return (('<CloudStackProject: id=%s, display_text=%s, name=%s, '
+                 'driver=%s>')
+                % (self.id, self.display_text, self.name,
+                   self.driver.name))
+
+
 class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
     """
     Driver for the CloudStack API.
@@ -516,13 +595,22 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
 
         return locations
 
-    def list_nodes(self):
+    def list_nodes(self, project=None):
         """
         @inherits: :class:`NodeDriver.list_nodes`
+
+        :keyword    project: Limit nodes returned to those configured under
+                             the defined project.
+        :type       project: :class:`.CloudStackProject`
+
         :rtype: ``list`` of :class:`CloudStackNode`
         """
-        vms = self._sync_request('listVirtualMachines')
-        addrs = self._sync_request('listPublicIpAddresses')
+
+        args = {}
+        if project:
+            args['projectid'] = project.id
+        vms = self._sync_request('listVirtualMachines', params=args)
+        addrs = self._sync_request('listPublicIpAddresses', params=args)
 
         public_ips_map = {}
         for addr in addrs.get('publicipaddress', []):
@@ -604,6 +692,13 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
                               into.
         :type       networks: ``list`` of :class:`.CloudStackNetwork`
 
+        :keyword    project: Optional project to create the new node under.
+        :type       project: :class:`.CloudStackProject`
+
+        :keyword    diskoffering:  Optional disk offering to add to the new
+                                   node.
+        :type       diskoffering:  :class:`.CloudStackDiskOffering`
+
         :keyword    ex_keyname:  Name of existing keypair
         :type       ex_keyname:  ``str``
 
@@ -636,6 +731,8 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
         image = kwargs.get('image', None)
         location = kwargs.get('location', None)
         networks = kwargs.get('networks', None)
+        project = kwargs.get('project', None)
+        diskoffering = kwargs.get('diskoffering', None)
         ex_key_name = kwargs.get('ex_keyname', None)
         ex_user_data = kwargs.get('ex_userdata', None)
         ex_security_groups = kwargs.get('ex_security_groups', None)
@@ -659,6 +756,12 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
             networks = ','.join([network.id for network in networks])
             server_params['networkids'] = networks
 
+        if project:
+            server_params['projectid'] = project.id
+
+        if diskoffering:
+            server_params['diskofferingid'] = diskoffering.id
+
         if ex_key_name:
             server_params['keypair'] = ex_key_name
 
@@ -771,16 +874,44 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
                 extra['tags'] = self._get_resource_tags(net['tags'])
 
             networks.append(CloudStackNetwork(
-                net['displaytext'],
-                net['name'],
-                net['networkofferingid'],
-                net['id'],
-                net['zoneid'],
-                self,
-                extra=extra))
+                            net['displaytext'],
+                            net['name'],
+                            net['networkofferingid'],
+                            net['id'],
+                            net['zoneid'],
+                            self,
+                            extra=extra))
 
         return networks
 
+    def ex_list_projects(self):
+        """
+        List the available projects
+
+        :rtype ``list`` of :class:`CloudStackProject`
+        """
+
+        res = self._sync_request(command='listProjects',
+                                 method='GET')
+        projs = res.get('project', [])
+
+        projects = []
+        extra_map = RESOURCE_EXTRA_ATTRIBUTES_MAP['project']
+        for proj in projs:
+            extra = self._get_extra_dict(proj, extra_map)
+
+            if 'tags' in proj:
+                extra['tags'] = self._get_resource_tags(proj['tags'])
+
+            projects.append(CloudStackProject(
+                            id=proj['id'],
+                            name=proj['name'],
+                            display_text=proj['displaytext'],
+                            driver=self,
+                            extra=extra))
+
+        return projects
+
     def create_volume(self, size, name, location=None, snapshot=None):
         """
         Creates a data volume
@@ -873,10 +1004,10 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver):
                 extra['tags'] = self._get_resource_tags(vol['tags'])
 
             list_volumes.append(StorageVolume(id=vol['id'],
-                                name=vol['name'],
-                                size=vol['size'],
-                                driver=self,
-                                extra=extra))
+                                              name=vol['name'],
+                                              size=vol['size'],
+                                              driver=self,
+                                              extra=extra))
         return list_volumes
 
     def list_key_pairs(self, **kwargs):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/583bfba6/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployproject.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployproject.json
b/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployproject.json
new file mode 100644
index 0000000..bf7b25e
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/deployVirtualMachine_deployproject.json
@@ -0,0 +1 @@
+{ "deployvirtualmachineresponse" : {"jobid":11117,"id":"19253fbf-abb7-4013-a8a1-97df3b93f206"}
}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/583bfba6/libcloud/test/compute/fixtures/cloudstack/listProjects_default.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/listProjects_default.json b/libcloud/test/compute/fixtures/cloudstack/listProjects_default.json
new file mode 100644
index 0000000..b100edf
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/listProjects_default.json
@@ -0,0 +1,49 @@
+{ "listprojectsresponse": {
+    "count": 1,
+    "project": [
+        {
+            "id": "e7ce14a8-abb7-48b9-931f-5f426febed6d",
+            "name": "ExampleProjectName",
+            "displaytext": "ExampleProject",
+            "account": "CB0512",
+            "cpuavailable": 18,
+            "cpulimit": 32,
+            "cputotal": 14,
+            "domain": "ExampleDomain",
+            "domainid": "dc0314d4-09aa-4e8f-8a54-419ecf344635",
+            "ipavailable": 8,
+            "iplimit": 8,
+            "iptotal": 0,
+            "memoryavailable": 72000,
+            "memorylimit": 128000,
+            "memorytotal": 56000,
+            "networkavailable": 0,
+            "networklimit": 0,
+            "networktotal": 0,
+            "primarystorageavailable": 1204,
+            "primarystoragelimit": 1600,
+            "primarystoragetotal": 396,
+            "secondarystorageavailable": 3817,
+            "secondarystoragelimit": 4000,
+            "secondarystoragetotal": 183,
+            "snapshotavailable": 17,
+            "snapshotlimit": 20,
+            "snapshottotal": 3,
+            "state": "Active",
+            "tags": [],
+            "templateavailable": 17,
+            "templatelimit": 20,
+            "templatetotal": 3,
+            "vmavailable": 1,
+            "vmlimit": 8,
+            "vmrunning": 7,
+            "vmtotal": 7,
+            "volumeavailable": 1,
+            "volumelimit": 16,
+            "volumetotal": 15,
+            "vpcavailable": 20,
+            "vpclimit": 0,
+            "vpctotal": 0
+        }
+    ]
+} }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/583bfba6/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11117.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11117.json b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11117.json
new file mode 100644
index 0000000..8f7c76a
--- /dev/null
+++ b/libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_11117.json
@@ -0,0 +1,63 @@
+{ "queryasyncjobresultresponse": {
+    "accountid": "86d47ca2-726b-4b85-a18a-77d6b0d79829",
+    "userid": "20cd68f5-0633-48a5-826e-e4e2a00dd6b8",
+    "cmd": "org.apache.cloudstack.api.command.user.vm.DeployVMCmd",
+    "jobstatus": 1,
+    "jobprocstatus": 0,
+    "jobresultcode": 0,
+    "jobresulttype": "object",
+    "jobresult": {
+        "virtualmachine": {
+            "id": "19253fbf-abb7-4013-a8a1-97df3b93f206",
+            "name": "TestNode",
+            "projectid": "b90442d1-079b-4066-ab7d-41f8f3a5078b",
+            "project": "Test Project",
+            "domainid": "dc0314d4-09aa-4e8f-8a54-419ecf344635",
+            "domain": "Test Domain",
+            "created": "2014-03-06T15:39:44-0600",
+            "state": "Running",
+            "haenable": false,
+            "zoneid": "d630b15a-a9e1-4641-bee8-355005b7a14d",
+            "zonename": "TestZone",
+            "templateid": "a032e8a0-3411-48b7-9e78-ff66823e6561",
+            "templatename": "OL-6.3.1-64-13.11.01",
+            "templatedisplaytext": "OL-6.3.1-64-13.11.01",
+            "passwordenabled": true,
+            "serviceofferingid": "519f8667-26d0-40e5-a1cd-da04be1fd9b5",
+            "serviceofferingname": "Test Service Offering",
+            "cpunumber": 1,
+            "cpuspeed": 2000,
+            "memory": 2000,
+            "guestosid": "b8506c91-6d8e-4086-8659-f6296a7b71ac",
+            "rootdeviceid": 0,
+            "rootdevicetype": "ROOT",
+            "securitygroup": [],
+            "password": "mW6crjxag",
+            "nic": [
+                {
+                    "id": "1c144283-979a-4359-b695-3334dc403457",
+                    "networkid": "1bf4acce-19a5-4830-ab1d-444f8acb9986",
+                    "networkname": "Public",
+                    "netmask": "255.255.252.0",
+                    "gateway": "10.1.2.2",
+                    "ipaddress": "10.2.2.8",
+                    "isolationuri": "vlan://2950",
+                    "broadcasturi": "vlan://2950",
+                    "traffictype": "Guest",
+                    "type": "Shared",
+                    "isdefault": true,
+                    "macaddress": "06:ef:30:00:04:22"
+                }
+            ],
+            "hypervisor": "VMware",
+            "tags": [],
+            "affinitygroup": [],
+            "displayvm": true,
+            "isdynamicallyscalable": false,
+            "jobid": "e23b9f0c-b7ae-4ffe-aea0-c9cf436cc315",
+            "jobstatus": 0
+        }
+    },
+    "created": "2014-03-06T15:39:44-0600",
+    "jobid": "e23b9f0c-b7ae-4ffe-aea0-c9cf436cc315"
+} }

http://git-wip-us.apache.org/repos/asf/libcloud/blob/583bfba6/libcloud/test/compute/test_cloudstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_cloudstack.py b/libcloud/test/compute/test_cloudstack.py
index fc73116..b90c905 100644
--- a/libcloud/test/compute/test_cloudstack.py
+++ b/libcloud/test/compute/test_cloudstack.py
@@ -135,6 +135,20 @@ class CloudStackCommonTestCase(TestCaseMixin):
         self.assertEqual(node.name, 'test')
         self.assertEqual(node.extra['key_name'], 'foobar')
 
+    def test_create_node_project(self):
+        size = self.driver.list_sizes()[0]
+        image = self.driver.list_images()[0]
+        location = self.driver.list_locations()[0]
+        project = self.driver.ex_list_projects()[0]
+        CloudStackMockHttp.fixture_tag = 'deployproject'
+        node = self.driver.create_node(name='test',
+                                       location=location,
+                                       image=image,
+                                       size=size,
+                                       project=project)
+        self.assertEqual(node.name, 'TestNode')
+        self.assertEqual(node.extra['project'], 'Test Project')
+
     def test_list_images_no_images_available(self):
         CloudStackMockHttp.fixture_tag = 'notemplates'
 
@@ -182,6 +196,25 @@ class CloudStackCommonTestCase(TestCaseMixin):
                 fixture_networks[i]['networkofferingid'])
             self.assertEqual(network.zoneid, fixture_networks[i]['zoneid'])
 
+    def test_ex_list_projects(self):
+        _, fixture = CloudStackMockHttp()._load_fixture(
+            'listProjects_default.json')
+        fixture_projects = fixture['listprojectsresponse']['project']
+
+        projects = self.driver.ex_list_projects()
+
+        for i, project in enumerate(projects):
+            self.assertEqual(project.id, fixture_projects[i]['id'])
+            self.assertEqual(
+                project.display_text, fixture_projects[i]['displaytext'])
+            self.assertEqual(project.name, fixture_projects[i]['name'])
+            self.assertEqual(
+                project.extra['domainid'],
+                fixture_projects[i]['domainid'])
+            self.assertEqual(
+                project.extra['cpulimit'],
+                fixture_projects[i]['cpulimit'])
+
     def test_create_volume(self):
         volumeName = 'vol-0'
         location = self.driver.list_locations()[0]


Mime
View raw message