| import sys |
| import unittest |
| |
| try: |
| import simplejson as json |
| except ImportError: |
| import json |
| |
| from libcloud.py3 import httplib |
| from libcloud.py3 import urlparse |
| from libcloud.py3 import b |
| |
| try: |
| parse_qsl = urlparse.parse_qsl |
| except AttributeError: |
| import cgi |
| parse_qsl = cgi.parse_qsl |
| |
| from libcloud.common.cloudstack import CloudStackConnection, CloudStackResponse |
| from libcloud.common.types import MalformedResponseError |
| |
| from test import MockHttpTestCase |
| |
| async_delay = 0 |
| |
| class CloudStackMockDriver(object): |
| host = 'nonexistant.' |
| path = '/path' |
| async_poll_frequency = 0 |
| |
| name = 'fake' |
| |
| async_delay = 0 |
| |
| class CloudStackCommonTest(unittest.TestCase): |
| def setUp(self): |
| CloudStackConnection.conn_classes = (None, CloudStackMockHttp) |
| self.connection = CloudStackConnection('apikey', 'secret', |
| host=CloudStackMockDriver.host) |
| self.connection.poll_interval = 0.0 |
| self.driver = self.connection.driver = CloudStackMockDriver() |
| |
| def test_sync_request_bad_response(self): |
| self.driver.path = '/bad/response' |
| try: |
| self.connection._sync_request('fake') |
| except Exception: |
| e = sys.exc_info()[1] |
| self.assertTrue(isinstance(e, MalformedResponseError)) |
| return |
| self.assertTrue(False) |
| |
| def test_sync_request(self): |
| self.driver.path = '/sync' |
| self.connection._sync_request('fake') |
| |
| def test_async_request_successful(self): |
| self.driver.path = '/async/success' |
| result = self.connection._async_request('fake') |
| self.assertEqual(result, {'fake': 'result'}) |
| |
| def test_async_request_unsuccessful(self): |
| self.driver.path = '/async/fail' |
| try: |
| self.connection._async_request('fake') |
| except: |
| return |
| self.assertFalse(True) |
| |
| def test_async_request_delayed(self): |
| global async_delay |
| self.driver.path = '/async/delayed' |
| async_delay = 2 |
| self.connection._async_request('fake') |
| self.assertEqual(async_delay, 0) |
| |
| def test_signature_algorithm(self): |
| cases = [ |
| ( |
| { |
| 'command': 'listVirtualMachines' |
| }, 'z/a9Y7J52u48VpqIgiwaGUMCso0=' |
| ), ( |
| { |
| 'command': 'deployVirtualMachine', |
| 'name': 'fred', |
| 'displayname': 'George', |
| 'serviceofferingid': 5, |
| 'templateid': 17, |
| 'zoneid': 23, |
| 'networkids': 42 |
| }, 'gHTo7mYmadZ+zluKHzlEKb1i/QU=' |
| ), ( |
| { |
| 'command': 'deployVirtualMachine', |
| 'name': 'fred', |
| 'displayname': 'George+Ringo', |
| 'serviceofferingid': 5, |
| 'templateid': 17, |
| 'zoneid': 23, |
| 'networkids': 42 |
| }, 'tAgfrreI1ZvWlWLClD3gu4+aKv4=' |
| ) |
| ] |
| |
| connection = CloudStackConnection('fnord', 'abracadabra') |
| for case in cases: |
| params = connection.add_default_params(case[0]) |
| self.assertEqual(connection._make_signature(params), b(case[1])) |
| |
| class CloudStackMockHttp(MockHttpTestCase): |
| def _response(self, status, result, response): |
| return (status, json.dumps(result), result, response) |
| |
| def _check_request(self, url): |
| url = urlparse.urlparse(url) |
| query = dict(parse_qsl(url.query)) |
| |
| self.assertTrue('apiKey' in query) |
| self.assertTrue('command' in query) |
| self.assertTrue('response' in query) |
| self.assertTrue('signature' in query) |
| |
| self.assertTrue(query['response'] == 'json') |
| |
| return query |
| |
| def _bad_response(self, method, url, body, headers): |
| self._check_request(url) |
| result = {'success': True} |
| return self._response(httplib.OK, result, httplib.responses[httplib.OK]) |
| |
| def _sync(self, method, url, body, headers): |
| query = self._check_request(url) |
| result = {query['command'].lower() + 'response': {}} |
| return self._response(httplib.OK, result, httplib.responses[httplib.OK]) |
| |
| def _async_success(self, method, url, body, headers): |
| query = self._check_request(url) |
| if query['command'].lower() == 'queryasyncjobresult': |
| self.assertEqual(query['jobid'], '42') |
| result = { |
| query['command'].lower() + 'response': { |
| 'jobstatus': 1, |
| 'jobresult': {'fake': 'result'} |
| } |
| } |
| else: |
| result = {query['command'].lower() + 'response': {'jobid': '42'}} |
| return self._response(httplib.OK, result, httplib.responses[httplib.OK]) |
| |
| def _async_fail(self, method, url, body, headers): |
| query = self._check_request(url) |
| if query['command'].lower() == 'queryasyncjobresult': |
| self.assertEqual(query['jobid'], '42') |
| result = { |
| query['command'].lower() + 'response': { |
| 'jobstatus': 2, |
| 'jobresult': {'fake': 'failresult'} |
| } |
| } |
| else: |
| result = {query['command'].lower() + 'response': {'jobid': '42'}} |
| return self._response(httplib.OK, result, httplib.responses[httplib.OK]) |
| |
| def _async_delayed(self, method, url, body, headers): |
| global async_delay |
| |
| query = self._check_request(url) |
| if query['command'].lower() == 'queryasyncjobresult': |
| self.assertEqual(query['jobid'], '42') |
| if async_delay == 0: |
| result = { |
| query['command'].lower() + 'response': { |
| 'jobstatus': 1, |
| 'jobresult': {'fake': 'result'} |
| } |
| } |
| else: |
| result = { |
| query['command'].lower() + 'response': { |
| 'jobstatus': 0, |
| } |
| } |
| async_delay -= 1 |
| else: |
| result = {query['command'].lower() + 'response': {'jobid': '42'}} |
| return self._response(httplib.OK, result, httplib.responses[httplib.OK]) |
| |
| if __name__ == '__main__': |
| sys.exit(unittest.main()) |