Modify CloudStack Connection class so it looks more like other connection classes and user can more easily specify which attributes to send as part of the query string and as part of the request body.
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/b23d9085 Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/b23d9085 Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/b23d9085 Branch: refs/heads/trunk Commit: b23d9085e701c37ce2451978b1a7963c68c031e8 Parents: dd4df81 Author: Tomaz Muraus <[email protected]> Authored: Wed Nov 20 14:20:15 2013 +0100 Committer: Tomaz Muraus <[email protected]> Committed: Wed Nov 20 15:13:32 2013 +0100 ---------------------------------------------------------------------- libcloud/common/cloudstack.py | 82 ++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/b23d9085/libcloud/common/cloudstack.py ---------------------------------------------------------------------- diff --git a/libcloud/common/cloudstack.py b/libcloud/common/cloudstack.py index a34f3df..5f139e2 100644 --- a/libcloud/common/cloudstack.py +++ b/libcloud/common/cloudstack.py @@ -15,6 +15,7 @@ import base64 import hashlib +import copy import hmac from libcloud.utils.py3 import urlencode @@ -39,6 +40,17 @@ class CloudStackConnection(ConnectionUserAndKey, PollingConnection): ASYNC_SUCCESS = 1 ASYNC_FAILURE = 2 + def encode_data(self, data): + """ + Must of the data is sent as part of query params (eeww), + but in newer versions, userdata argument can be sent as a + urlencoded data in the request body. + """ + if data: + data = urlencode(data) + + return data + def _make_signature(self, params): signature = [(k.lower(), v) for k, v in list(params.items())] signature.sort(key=lambda x: x[0]) @@ -59,25 +71,37 @@ class CloudStackConnection(ConnectionUserAndKey, PollingConnection): return params, headers - def _async_request(self, command, **kwargs): - context = {'command': command} - context.update(kwargs) - result = super(CloudStackConnection, self).async_request(action=None, - params=None, - data=None, - headers=None, - method=None, + def _async_request(self, command, action=None, params=None, data=None, + headers=None, method='GET', context=None): + if params: + context = copy.deepcopy(params) + else: + context = {} + + # Command is specified as part of GET call + context['command'] = command + result = super(CloudStackConnection, self).async_request(action=action, + params=params, + data=data, + headers= + headers, + method=method, context= context) return result['jobresult'] def get_request_kwargs(self, action, params=None, data='', headers=None, method='GET', context=None): - return context + command = context['command'] + request_kwargs = {'command': command, 'action': action, + 'params': params, 'data': data, + 'headers': headers, 'method': method} + return request_kwargs def get_poll_request_kwargs(self, response, context, request_kwargs): job_id = response['jobid'] - kwargs = {'command': 'queryAsyncJobResult', 'jobid': job_id} + params = {'jobid': job_id} + kwargs = {'command': 'queryAsyncJobResult', 'params': params} return kwargs def has_completed(self, response): @@ -89,13 +113,24 @@ class CloudStackConnection(ConnectionUserAndKey, PollingConnection): return status == self.ASYNC_SUCCESS - def _sync_request(self, command, **kwargs): - """This method handles synchronous calls which are generally fast - information retrieval requests and thus return 'quickly'.""" + def _sync_request(self, command, action=None, params=None, data=None, + headers=None, method='GET'): + """ + This method handles synchronous calls which are generally fast + information retrieval requests and thus return 'quickly'. + """ + # command is always sent as part of "command" query parameter + if params: + params = copy.deepcopy(params) + else: + params = {} + + params['command'] = command + result = self.request(action=self.driver.path, params=params, + data=data, headers=headers, method=method) - kwargs['command'] = command - result = self.request(self.driver.path, params=kwargs) command = command.lower() + 'response' + if command not in result.object: raise MalformedResponseError( "Unknown response format", @@ -116,8 +151,15 @@ class CloudStackDriverMixIn(object): super(CloudStackDriverMixIn, self).__init__(key, secret, secure, host, port) - def _sync_request(self, command, **kwargs): - return self.connection._sync_request(command, **kwargs) - - def _async_request(self, command, **kwargs): - return self.connection._async_request(command, **kwargs) + def _sync_request(self, command, action=None, params=None, data=None, + headers=None, method='GET'): + return self.connection._sync_request(command=command, action=action, + params=params, data=data, + headers=headers, method=method) + + def _async_request(self, command, action=None, params=None, data=None, + headers=None, method='GET', context=None): + return self.connection._async_request(command=command, action=action, + params=params, data=data, + headers=headers, method=method, + context=context)
