mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
116 lines
2.9 KiB
Python
116 lines
2.9 KiB
Python
'''Implements the Cloud.com API'''
|
|
|
|
|
|
from cloudtool.utils import describe
|
|
import urllib
|
|
import urllib2
|
|
import os
|
|
import xml.dom.minidom
|
|
|
|
class CloudAPI:
|
|
|
|
@describe("server", "Management Server host name or address")
|
|
@describe("responseformat", "Response format: xml or json")
|
|
def __init__(self,
|
|
server="127.0.0.1:8096",
|
|
responseformat="xml",
|
|
):
|
|
self.__dict__.update(locals())
|
|
|
|
def _make_request(self,command,parameters=None):
|
|
'''Command is a string, parameters is a dictionary'''
|
|
if ":" in self.server:
|
|
host,port = self.server.split(":")
|
|
port = int(port)
|
|
else:
|
|
host = self.server
|
|
port = 8096
|
|
|
|
url = "http://" + self.server + "/?"
|
|
|
|
if not parameters: parameters = {}
|
|
parameters["command"] = command
|
|
parameters["response"] = self.responseformat
|
|
querystring = urllib.urlencode(parameters)
|
|
url += querystring
|
|
|
|
f = urllib2.urlopen(url)
|
|
|
|
data = f.read()
|
|
|
|
return data
|
|
|
|
|
|
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 = cmd.getElementsByTagName('name')[0].getAttribute("description")
|
|
if description: description = '"""%s"""' % description
|
|
else: description = ''
|
|
arguments = []
|
|
options = []
|
|
descriptions = []
|
|
|
|
for param in cmd.getElementsByTagName('arg'):
|
|
argname = getText(param.childNodes).strip()
|
|
assert argname
|
|
|
|
required = param.getAttribute("required").strip()
|
|
if required == 'true': required = True
|
|
elif required == 'false': required = False
|
|
else: raise AssertionError, "Not reached"
|
|
if required: arguments.append(argname)
|
|
options.append(argname)
|
|
|
|
description = param.getAttribute("description").strip()
|
|
if description: descriptions.append( (argname,description) )
|
|
|
|
funcparams = ["self"] + [ "%s=None"%o for o in options ]
|
|
funcparams = ", ".join(funcparams)
|
|
|
|
code = """
|
|
def %s(%s):
|
|
%s
|
|
parms = locals()
|
|
del parms["self"]
|
|
for arg in %r:
|
|
if locals()[arg] is None:
|
|
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)
|
|
return output
|
|
"""%(name,funcparams,description,arguments,name)
|
|
|
|
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(): setattr(CloudAPI,name,meth)
|
|
|
|
implementor = CloudAPI
|
|
|
|
del name,meth,describe,load_dynamic_methods
|
|
|
|
|