From ea151475919f4b53432379fdfefc3aa96373a5de Mon Sep 17 00:00:00 2001 From: Sebastien Goasguen Date: Thu, 6 Jun 2013 07:48:47 -0400 Subject: [PATCH] LIBCLOUD-337: Add tests for 333 and 332 and fixes 338 as well --- libcloud/compute/drivers/cloudstack.py | 51 +++++++++++++- .../authorizeSecurityGroupIngress_default.json | 2 + .../cloudstack/createSecurityGroup_default.json | 1 + .../cloudstack/deleteSSHKeyPair_default.json | 2 + .../cloudstack/deleteSecurityGroup_default.json | 2 + .../cloudstack/listSSHKeyPairs_default.json | 1 + .../cloudstack/listSecurityGroups_default.json | 1 + .../cloudstack/queryAsyncJobResult_17188.json | 1 + .../cloudstack/queryAsyncJobResult_17199.json | 1 + .../cloudstack/queryAsyncJobResult_17200.json | 1 + .../cloudstack/startVirtualMachine_default.json | 1 + .../cloudstack/stopVirtualMachine_default.json | 1 + libcloud/test/compute/test_cloudstack.py | 77 +++++++++++++++++++++- 13 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_default.json create mode 100644 libcloud/test/compute/fixtures/cloudstack/createSecurityGroup_default.json create mode 100644 libcloud/test/compute/fixtures/cloudstack/deleteSSHKeyPair_default.json create mode 100644 libcloud/test/compute/fixtures/cloudstack/deleteSecurityGroup_default.json create mode 100644 libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_default.json create mode 100644 libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_default.json create mode 100644 libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17188.json create mode 100644 libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17199.json create mode 100644 libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17200.json create mode 100644 libcloud/test/compute/fixtures/cloudstack/startVirtualMachine_default.json create mode 100644 libcloud/test/compute/fixtures/cloudstack/stopVirtualMachine_default.json diff --git libcloud/compute/drivers/cloudstack.py libcloud/compute/drivers/cloudstack.py index 7fc542e..7358b22 100644 --- libcloud/compute/drivers/cloudstack.py +++ libcloud/compute/drivers/cloudstack.py @@ -41,6 +41,14 @@ class CloudStackNode(Node): "Delete a NAT/firewall rule." return self.driver.ex_delete_ip_forwarding_rule(self, rule) + def ex_start(self): + "Starts a stopped virtual machine" + return self.driver.ex_start(self) + + def ex_stop(self): + "Stops a running virtual machine" + return self.driver.ex_stop(self) + class CloudStackAddress(object): "A public IP address." @@ -298,8 +306,47 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver): self._async_request('rebootVirtualMachine', id=node.id) return True + def ex_start(self, node): + """ + Starts/Resumes a stopped virtual machine + + @type node: L{CloudStackNode} + + @param id: The ID of the virtual machine (required) + @type id: C{uuid} + + @param hostid: destination Host ID to deploy the VM to + parameter available for root admin only + @type hostid: C{uuid} + + @rtype C{str} + """ + res = self._async_request('startVirtualMachine', id=node.id) + return res['virtualmachine']['state'] + + def ex_stop(self, node): + """ + Stops/Suspends a running virtual machine + + @type node: L{CloudStackNode} + + @param id: The ID of the virtual machine + @type id: C{uuid} + + @param forced: Force stop the VM + (vm is marked as Stopped even when command + fails to be send to the backend). + The caller knows the VM is stopped. + @type forced: C{bool} + + @rtype C{str} + """ + res = self._async_request('stopVirtualMachine', id=node.id) + return res['virtualmachine']['state'] + def ex_list_disk_offerings(self): - """Fetch a list of all available disk offerings. + """ + Fetch a list of all available disk offerings. @rtype: C{list} of L{CloudStackDiskOffering} """ @@ -364,7 +411,7 @@ class CloudStackNodeDriver(CloudStackDriverMixIn, NodeDriver): def ex_allocate_public_ip(self, node): """ - "Allocate a public IP and bind it to a node. + Allocate a public IP and bind it to a node. @param node: Node which should be used @type node: L{CloudStackNode} diff --git libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_default.json libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_default.json new file mode 100644 index 0000000..262ab05 --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/authorizeSecurityGroupIngress_default.json @@ -0,0 +1,2 @@ +{ "authorizesecuritygroupingressresponse" : {"jobid":17200} } + diff --git libcloud/test/compute/fixtures/cloudstack/createSecurityGroup_default.json libcloud/test/compute/fixtures/cloudstack/createSecurityGroup_default.json new file mode 100644 index 0000000..0d3cdaf --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/createSecurityGroup_default.json @@ -0,0 +1 @@ +{"createsecuritygroupresponse":{"securitygroup":{"account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","id":"895f9e41-4d89-468e-9b69-19a8f0d3a889","domain":"runseb@gmail.com","name":"MySG"}}} diff --git libcloud/test/compute/fixtures/cloudstack/deleteSSHKeyPair_default.json libcloud/test/compute/fixtures/cloudstack/deleteSSHKeyPair_default.json new file mode 100644 index 0000000..9e2c854 --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/deleteSSHKeyPair_default.json @@ -0,0 +1,2 @@ +{ "deletesshkeypairresponse" : { "success" : "true"} } + diff --git libcloud/test/compute/fixtures/cloudstack/deleteSecurityGroup_default.json libcloud/test/compute/fixtures/cloudstack/deleteSecurityGroup_default.json new file mode 100644 index 0000000..19ba723 --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/deleteSecurityGroup_default.json @@ -0,0 +1,2 @@ +{ "deletesecuritygroupresponse" : { "success" : "true"} } + diff --git libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_default.json libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_default.json new file mode 100644 index 0000000..d7728aa --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/listSSHKeyPairs_default.json @@ -0,0 +1 @@ +{"listsshkeypairsresponse":{"count":1,"sshkeypair":[{"name":"cs-keypair","fingerprint":"00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"}]}} diff --git libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_default.json libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_default.json new file mode 100644 index 0000000..fa9977a --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/listSecurityGroups_default.json @@ -0,0 +1 @@ +{"listsecuritygroupsresponse":{"count":1,"securitygroup":[{"egressrule":[],"account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","description":"Default Security Group","tags":[],"domain":"runseb@gmail.com","ingressrule":[{"startport":22,"cidr":"0.0.0.0/0","protocol":"tcp","endport":22,"ruleid":"489e83b2-5498-4c17-8a28-e6a96b35ac2d"}],"id":"ebfa2339-e9ae-4dcb-b73c-a76cd3fce39e","name":"default"}]}} diff --git libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17188.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17188.json new file mode 100644 index 0000000..43ca40d --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17188.json @@ -0,0 +1 @@ +{ "queryasyncjobresultresponse" : {"jobid":17166,"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":"Starting","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,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"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"}}} } diff --git libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17199.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17199.json new file mode 100644 index 0000000..485175a --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17199.json @@ -0,0 +1 @@ +{ "queryasyncjobresultresponse" : {"jobid":17166,"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":"Stopped","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,"cpuused":"0.13%","networkkbsread":2,"networkkbswrite":1,"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"}}} } diff --git libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17200.json libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17200.json new file mode 100644 index 0000000..d028ab4 --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/queryAsyncJobResult_17200.json @@ -0,0 +1 @@ +{"queryasyncjobresultresponse":{"jobid":17200,"jobstatus":1,"jobprocstatus":0,"jobresultcode":0,"jobresulttype":"object","jobresult":{"securitygroup":[{"egressrule":[],"account":"runseb@gmail.com","domainid":"ab53d864-6f78-4993-bb28-9b8667b535a1","name":"MySG","domain":"runseb@gmail.com","ingressrule":[{"startport":22,"cidr":"0.0.0.0/0","protocol":"tcp","endport":22,"ruleid":"7df1edc8-6e56-48d7-b816-39377506d787"}],"id":"fa334c44-21c6-4809-ad7d-287bbb23c29b"}]}}} diff --git libcloud/test/compute/fixtures/cloudstack/startVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/startVirtualMachine_default.json new file mode 100644 index 0000000..750e493 --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/startVirtualMachine_default.json @@ -0,0 +1 @@ +{ "startvirtualmachineresponse" : {"jobid":17188} } diff --git libcloud/test/compute/fixtures/cloudstack/stopVirtualMachine_default.json libcloud/test/compute/fixtures/cloudstack/stopVirtualMachine_default.json new file mode 100644 index 0000000..cb30e00 --- /dev/null +++ libcloud/test/compute/fixtures/cloudstack/stopVirtualMachine_default.json @@ -0,0 +1 @@ +{ "stopvirtualmachineresponse" : {"jobid":17199} } diff --git libcloud/test/compute/test_cloudstack.py libcloud/test/compute/test_cloudstack.py index b1e8ab1..14ce99f 100644 --- libcloud/test/compute/test_cloudstack.py +++ libcloud/test/compute/test_cloudstack.py @@ -1,3 +1,17 @@ +# 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 @@ -17,11 +31,13 @@ except AttributeError: from libcloud.compute.drivers.cloudstack import CloudStackNodeDriver from libcloud.compute.types import DeploymentError, LibcloudError +from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation from libcloud.test import MockHttpTestCase from libcloud.test.compute import TestCaseMixin from libcloud.test.file_fixtures import ComputeFileFixtures + class CloudStackNodeDriverTest(unittest.TestCase, TestCaseMixin): def setUp(self): CloudStackNodeDriver.connectionCls.conn_classes = \ @@ -104,9 +120,9 @@ class CloudStackNodeDriverTest(unittest.TestCase, TestCaseMixin): location = self.driver.list_locations()[0] self.assertRaises( - LibcloudError, - self.driver.create_volume, - 'vol-0', location, 11) + LibcloudError, + self.driver.create_volume, + 'vol-0', location, 11) def test_create_volume_with_custom_disk_size_offering(self): CloudStackMockHttp.fixture_tag = 'withcustomdisksize' @@ -128,6 +144,61 @@ class CloudStackNodeDriverTest(unittest.TestCase, TestCaseMixin): self.assertTrue(attachReturnVal) + def test_list_nodes(self): + node = self.driver.list_nodes()[0] + self.assertEquals('test', node.name) + + def test_list_locations(self): + location = self.driver.list_locations()[0] + self.assertEquals('Sydney', location.name) + + def test_start_node(self): + node = self.driver.list_nodes()[0] + res = node.ex_start() + self.assertEquals('Starting', res) + + def test_stop_node(self): + node = self.driver.list_nodes()[0] + res = node.ex_stop() + self.assertEquals('Stopped', res) + + def test_list_keypairs(self): + keypairs = self.driver.ex_list_keypairs() + fingerprint = '00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:' + \ + '00:00:00:00:00' + + self.assertEqual(keypairs[0]['name'], 'cs-keypair') + self.assertEqual(keypairs[0]['fingerprint'], fingerprint) + + def test_create_keypair(self): + with self.assertRaises(LibcloudError) as cm: + res = self.driver.ex_create_keypair('cs-keypair') + ex = cm.exception + + def test_delete_keypair(self): + res = self.driver.ex_delete_keypair('cs-keypair') + self.assertTrue(res) + + def test_list_security_groups(self): + groups = self.driver.ex_list_security_groups() + self.assertEqual(groups[0]['name'], 'default') + + def test_create_security_group(self): + group = self.driver.ex_create_security_group(name='MySG') + self.assertEqual(group['name'], 'MySG') + + def test_delete_security_group(self): + res = self.driver.ex_delete_security_group(name='MySG') + self.assertTrue(res) + + def test_authorize_security_group_ingress(self): + res = self.driver.ex_authorize_security_group_ingress('MySG', + 'TCP', + '22', + '22', + '0.0.0.0/0') + self.assertTrue(res) + class CloudStackMockHttp(MockHttpTestCase): fixtures = ComputeFileFixtures('cloudstack') -- 1.8.1.3