forked from jasonhancock/cloudstack-python-client
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBaseClient.py
More file actions
62 lines (48 loc) · 1.76 KB
/
BaseClient.py
File metadata and controls
62 lines (48 loc) · 1.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import urllib2
import urllib
import json
import hmac
import base64
import hashlib
import re
class BaseClient(object):
def __init__(self, api, apikey, secret):
self.api = api
self.apikey = apikey
self.secret = secret
def request(self, command, args):
args['apikey'] = self.apikey
args['command'] = command
args['response'] = 'json'
params=[]
keys = sorted(args.keys())
for k in keys:
params.append(k + '=' + urllib.quote_plus(args[k]).replace("+", "%20"))
query = '&'.join(params)
signature = base64.b64encode(hmac.new(
self.secret,
msg=query.lower(),
digestmod=hashlib.sha1
).digest())
query += '&signature=' + urllib.quote_plus(signature)
response = urllib2.urlopen(self.api + '?' + query)
decoded = json.loads(response.read())
propertyResponse = command.lower() + 'response'
if not propertyResponse in decoded:
if 'errorresponse' in decoded:
raise RuntimeError("ERROR: " + decoded['errorresponse']['errortext'])
else:
raise RuntimeError("ERROR: Unable to parse the response")
response = decoded[propertyResponse]
result = re.compile(r"^list(\w+)s").match(command.lower())
if not result is None:
type = result.group(1)
if type in response:
return response[type]
else:
# sometimes, the 's' is kept, as in :
# { "listasyncjobsresponse" : { "asyncjobs" : [ ... ] } }
type += 's'
if type in response:
return response[type]
return response