diff --git a/cloud-cli/cloudapis/cloud.py b/cloud-cli/cloudapis/cloud.py index 34b3413ce5e..1ee9806c978 100644 --- a/cloud-cli/cloudapis/cloud.py +++ b/cloud-cli/cloudapis/cloud.py @@ -5,9 +5,9 @@ # 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 @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. - + '''Implements the CloudStack API''' @@ -32,7 +32,7 @@ import hashlib import httplib class CloudAPI: - + @describe("server", "Management Server host name or address") @describe("apikey", "Management Server apiKey") @describe("securitykey", "Management Server securityKey") @@ -46,14 +46,14 @@ class CloudAPI: securityKey=None ): self.__dict__.update(locals()) - + def _make_request_with_keys(self,command,requests={}): requests["command"] = command requests["apiKey"] = self.apiKey requests["response"] = "xml" requests = zip(requests.keys(), requests.values()) requests.sort(key=lambda x: str.lower(x[0])) - + requestUrl = "&".join(["=".join([request[0], urllib.quote_plus(str(request[1]))]) for request in requests]) hashStr = "&".join(["=".join([str.lower(request[0]), urllib.quote_plus(str.lower(str(request[1])))]) for request in requests]) @@ -70,7 +70,7 @@ class CloudAPI: requests["response"] = self.responseformat requests = zip(requests.keys(), requests.values()) requests.sort(key=lambda x: str.lower(x[0])) - + requestUrl = "&".join(["=".join([request[0], urllib.quote_plus(str(request[1]))]) for request in requests]) hashStr = "&".join(["=".join([str.lower(request[0]), urllib.quote_plus(str.lower(str(request[1])))]) for request in requests]) @@ -80,7 +80,7 @@ class CloudAPI: self.connection.request("GET", "/client/api?%s"%requestUrl) return self.connection.getresponse().read() - + def _make_request(self,command,parameters=None): '''Command is a string, parameters is a dictionary''' @@ -90,9 +90,9 @@ class CloudAPI: else: host = self.server port = 8096 - - url = "http://" + self.server + "/?" - + + url = "http://" + self.server + "/client/api?" + if not parameters: parameters = {} if self.apiKey is not None and self.securityKey is not None: return self._make_request_with_auth(command, parameters) @@ -102,7 +102,7 @@ class CloudAPI: querystring = urllib.urlencode(parameters) url += querystring - + f = urllib2.urlopen(url) data = f.read() if self.stripxml == "true": @@ -119,51 +119,51 @@ class CloudAPI: def load_dynamic_methods(): '''creates smart function objects for every method in the commands.xml file''' - + def getText(nodelist): rc = [] for node in nodelist: if node.nodeType == node.TEXT_NODE: rc.append(node.data) return ''.join(rc) - + # FIXME figure out installation and packaging xmlfile = os.path.join("/etc/cloud/cli/","commands.xml") dom = xml.dom.minidom.parse(xmlfile) - + for cmd in dom.getElementsByTagName("command"): name = getText(cmd.getElementsByTagName('name')[0].childNodes).strip() assert name - + description = getText(cmd.getElementsByTagName('description')[0].childNodes).strip() - if description: + if description: description = '"""%s"""' % description else: description = '' arguments = [] options = [] descriptions = [] - + for param in cmd.getElementsByTagName("request")[0].getElementsByTagName("arg"): argname = getText(param.getElementsByTagName('name')[0].childNodes).strip() assert argname - + required = getText(param.getElementsByTagName('required')[0].childNodes).strip() if required == 'true': required = True elif required == 'false': required = False else: raise AssertionError, "Not reached" if required: arguments.append(argname) options.append(argname) - + #import ipdb; ipdb.set_trace() requestDescription = param.getElementsByTagName('description') - if requestDescription: + if requestDescription: descriptionParam = getText(requestDescription[0].childNodes) - else: + else: descriptionParam = '' if descriptionParam: descriptions.append( (argname,descriptionParam) ) - + funcparams = ["self"] + [ "%s=None"%o for o in options ] funcparams = ", ".join(funcparams) - + code = """ def %s(%s): %s @@ -171,7 +171,7 @@ def load_dynamic_methods(): del parms["self"] for arg in %r: if locals()[arg] is None: - raise TypeError, "%%s is a required option"%%arg + raise TypeError, "%%s is a required option"%%arg for k,v in parms.items(): if v is None: del parms[k] output = self._make_request("%s",parms) @@ -180,15 +180,15 @@ def load_dynamic_methods(): namespace = {} exec code.strip() in namespace - + func = namespace[name] for argname,description in descriptions: func = describe(argname,description)(func) - + yield (name,func) -for name,meth in load_dynamic_methods(): +for name,meth in load_dynamic_methods(): setattr(CloudAPI, name, meth) implementor = CloudAPI