mirror of https://github.com/apache/cloudstack.git
Add cloud-tool into FOSS
This commit is contained in:
parent
d7bf859d92
commit
066d94f6f9
|
|
@ -210,8 +210,8 @@ authorizeNetworkGroupIngress=com.cloud.api.commands.AuthorizeNetworkGroupIngress
|
|||
revokeNetworkGroupIngress=com.cloud.api.commands.RevokeNetworkGroupIngressCmd;11
|
||||
listNetworkGroups=com.cloud.api.commands.ListNetworkGroupsCmd;11
|
||||
|
||||
registerPreallocatedLun=com.cloud.server.api.commands.RegisterPreallocatedLunCmd;1
|
||||
deletePreallocatedLun=com.cloud.server.api.commands.DeletePreallocatedLunCmd;1
|
||||
registerPreallocatedLun=com.cloud.api.commands.RegisterPreallocatedLunCmd;1
|
||||
deletePreallocatedLun=com.cloud.api.commands.DeletePreallocatedLunCmd;1
|
||||
listPreallocatedLuns=com.cloud.api.commands.ListPreallocatedLunsCmd;1
|
||||
|
||||
#### vm group commands
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
|
||||
|
||||
import cloudtool
|
||||
|
||||
ret = cloudtool.main()
|
||||
if ret: sys.exit(ret)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
'''
|
||||
Created on Aug 2, 2010
|
||||
|
||||
@author: rudd-o
|
||||
'''
|
||||
|
||||
import os,pkgutil
|
||||
|
||||
def get_all_apis():
|
||||
apis = []
|
||||
for x in pkgutil.walk_packages([os.path.dirname(__file__)]):
|
||||
loader = x[0].find_module(x[1])
|
||||
try: module = loader.load_module("cloudapis." + x[1])
|
||||
except ImportError: continue
|
||||
apis.append(module)
|
||||
return apis
|
||||
|
||||
def lookup_api(api_name):
|
||||
api = None
|
||||
matchingapi = [ x for x in get_all_apis() if api_name.replace("-","_") == x.__name__.split(".")[-1] ]
|
||||
if not matchingapi: api = None
|
||||
else: api = matchingapi[0]
|
||||
if api: api = getattr(api,"implementor")
|
||||
return api
|
||||
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
'''Implements the Amazon API'''
|
||||
|
||||
|
||||
import boto.ec2
|
||||
import os
|
||||
from cloudtool.utils import describe,OptionConflictError,OptionValueError
|
||||
raise ImportError
|
||||
|
||||
class AmazonAPI:
|
||||
|
||||
@describe("access_key", "Amazon access key")
|
||||
@describe("secret_key", "Amazon secret key")
|
||||
@describe("region", "Amazon region")
|
||||
@describe("endpoint", "Amazon endpoint")
|
||||
def __init__(self,
|
||||
access_key=os.environ.get("AWS_ACCESS_KEY_ID",None),
|
||||
secret_key=os.environ.get("AWS_SECRET_ACCESS_KEY",None),
|
||||
region=None,
|
||||
endpoint=None):
|
||||
if not access_key: raise OptionValueError,"you need to specify an access key"
|
||||
if not secret_key: raise OptionValueError,"you need to specify a secret key"
|
||||
if region and endpoint:
|
||||
raise OptionConflictError,("mutually exclusive with --endpoint",'--region')
|
||||
self.__dict__.update(locals())
|
||||
|
||||
def _get_regions(self):
|
||||
return boto.ec2.regions(aws_access_key_id=self.access_key,aws_secret_access_key=self.secret_key)
|
||||
|
||||
def _get_region(self,name):
|
||||
try: return [ x for x in self._get_regions() if x.name == name ][0]
|
||||
except IndexError: raise KeyError,name
|
||||
|
||||
def _connect(self):
|
||||
if self.region:
|
||||
region = self._get_region(self.region)
|
||||
self.connection = region.connect(
|
||||
aws_access_key_id=self.access_key,
|
||||
aws_secret_access_key=self.secret_key
|
||||
)
|
||||
else:
|
||||
self.connection = boto.ec2.connection.EC2Connection(
|
||||
host=self.endpoint,
|
||||
aws_access_key_id=self.access_key,
|
||||
aws_secret_access_key=self.secret_key
|
||||
)
|
||||
def list_regions(self):
|
||||
"""Lists all regions"""
|
||||
regions = self._get_regions()
|
||||
for r in regions: print r
|
||||
|
||||
def get_all_images(self):
|
||||
"""Lists all images"""
|
||||
self._connect()
|
||||
images = self.connection.get_all_images()
|
||||
for i in images: print i
|
||||
|
||||
def get_region(self):
|
||||
"""Gets the region you're connecting to"""
|
||||
self._connect()
|
||||
print self.connection.region
|
||||
|
||||
|
||||
implementor = AmazonAPI
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
'''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
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
'''
|
||||
Created on Aug 2, 2010
|
||||
|
||||
@author: rudd-o
|
||||
'''
|
||||
|
||||
import sys
|
||||
import cloudapis as apis
|
||||
import cloudtool.utils as utils
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
|
||||
if argv == None:
|
||||
argv = sys.argv
|
||||
|
||||
prelim_args = [ x for x in argv[1:] if not x.startswith('-') ]
|
||||
parser = utils.get_parser()
|
||||
|
||||
api = __import__("cloudapis")
|
||||
apis = getattr(api, "implementor")
|
||||
if len(prelim_args) == 0:
|
||||
parser.error("you need to specify an API as the first argument\n\nSupported APIs:\n" + "\n".join(utils.get_api_list()))
|
||||
elif len(prelim_args) == 1:
|
||||
commandlist = utils.get_command_list(apis)
|
||||
parser.error("you need to specify a command name as the second argument\n\nCommands supported by the %s API:\n"%prelim_args[0] + "\n".join(commandlist))
|
||||
|
||||
command = utils.lookup_command_in_api(apis,prelim_args[1])
|
||||
if not command: parser.error("command %r not supported by the %s API"%(prelim_args[1],prelim_args[0]))
|
||||
|
||||
parser = utils.get_parser(apis.__init__,command)
|
||||
argv = argv[1:]
|
||||
opts,args,api_optionsdict,cmd_optionsdict = parser.parse_args(argv)
|
||||
|
||||
|
||||
try:
|
||||
api = apis(**api_optionsdict)
|
||||
except utils.OptParseError,e:
|
||||
parser.error(str(e))
|
||||
|
||||
command = utils.lookup_command_in_api(api,args[1])
|
||||
|
||||
# we now discard the first two arguments as those necessarily are the api and command names
|
||||
args = args[2:]
|
||||
|
||||
try: return command(*args,**cmd_optionsdict)
|
||||
except TypeError,e: parser.error(str(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(argv)
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
'''
|
||||
Created on Aug 2, 2010
|
||||
|
||||
@author: rudd-o
|
||||
'''
|
||||
|
||||
|
||||
import sys
|
||||
import os
|
||||
import inspect
|
||||
from optparse import OptionParser, OptParseError, BadOptionError, OptionError, OptionConflictError, OptionValueError
|
||||
import cloudapis as apis
|
||||
|
||||
|
||||
def describe(name,desc):
|
||||
def inner(decoratee):
|
||||
if not hasattr(decoratee,"descriptions"): decoratee.descriptions = {}
|
||||
decoratee.descriptions[name] = desc
|
||||
return decoratee
|
||||
return inner
|
||||
|
||||
|
||||
def error(msg):
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.write("\n")
|
||||
|
||||
|
||||
class MyOptionParser(OptionParser):
|
||||
def error(self, msg):
|
||||
error("%s: %s\n" % (self.get_prog_name(),msg))
|
||||
self.print_usage(sys.stderr)
|
||||
self.exit(os.EX_USAGE)
|
||||
|
||||
def parse_args(self,*args,**kwargs):
|
||||
options,arguments = OptionParser.parse_args(self,*args,**kwargs)
|
||||
|
||||
def prune_options(options,alist):
|
||||
"""Given 'options' -- a list of arguments to OptionParser.add_option,
|
||||
and a set of optparse Values, return a dictionary of only those values
|
||||
that apply exclusively to 'options'"""
|
||||
return dict( [ (k,getattr(options,k)) for k in dir(options) if k in alist ] )
|
||||
|
||||
api_options = prune_options(options,self.api_dests)
|
||||
cmd_options = prune_options(options,self.cmd_dests)
|
||||
|
||||
return options,arguments,api_options,cmd_options
|
||||
|
||||
|
||||
def get_parser(api_callable=None,cmd_callable=None): # this should probably be the __init__ method of myoptionparser
|
||||
|
||||
def getdefaulttag(default):
|
||||
if default is not None: return " [Default: %default]"
|
||||
return ''
|
||||
|
||||
def get_arguments_and_options(callable):
|
||||
"""Infers and returns arguments and options based on a callable's signature.
|
||||
Cooperates with decorator @describe"""
|
||||
try:
|
||||
funcargs = inspect.getargspec(callable).args
|
||||
defaults = inspect.getargspec(callable).defaults
|
||||
except:
|
||||
funcargs = inspect.getargspec(callable)[0]
|
||||
defaults = inspect.getargspec(callable)[3]
|
||||
if not defaults: defaults = []
|
||||
args = funcargs[1:len(funcargs)-len(defaults)] # this assumes self, so assumes methods
|
||||
opts = funcargs[len(funcargs)-len(defaults):]
|
||||
try: descriptions = callable.descriptions
|
||||
except AttributeError: descriptions = {}
|
||||
arguments = [ (argname, descriptions.get(argname,'') ) for argname in args ]
|
||||
options = [ [
|
||||
("--%s"%argname.replace("_","-"),),
|
||||
{
|
||||
"dest":argname,
|
||||
"help":descriptions.get(argname,'') + getdefaulttag(default),
|
||||
"default":default,
|
||||
}
|
||||
] for argname,default in zip(opts,defaults) ]
|
||||
return arguments,options
|
||||
|
||||
basic_usage = "usage: %prog [options...] "
|
||||
|
||||
api_name = "<api>"
|
||||
cmd_name = "<command>"
|
||||
description = "%prog is a command-line tool to access several cloud APIs."
|
||||
arguments = ''
|
||||
argexp = ""
|
||||
|
||||
if api_callable:
|
||||
api_name = api_callable.__module__.split(".")[-1].replace("_","-")
|
||||
api_arguments,api_options = get_arguments_and_options(api_callable)
|
||||
assert len(api_arguments) is 0 # no mandatory arguments for class initializers
|
||||
|
||||
if cmd_callable:
|
||||
cmd_name = cmd_callable.func_name.replace("_","-")
|
||||
cmd_arguments,cmd_options = get_arguments_and_options(cmd_callable)
|
||||
if cmd_arguments:
|
||||
arguments = " " + " ".join( [ s[0].upper() for s in cmd_arguments ] )
|
||||
argexp = "\n\nArguments:\n" + "\n".join ( " %s\n %s"%(s.upper(),u) for s,u in cmd_arguments )
|
||||
description = cmd_callable.__doc__
|
||||
|
||||
api_command = "%s %s"%(api_name,cmd_name)
|
||||
|
||||
if description: description = "\n\n" + description
|
||||
else: description = ''
|
||||
|
||||
usage = basic_usage + api_command + arguments + description + argexp
|
||||
|
||||
parser = MyOptionParser(usage=usage, add_help_option=False)
|
||||
|
||||
parser.add_option('--help', action="help")
|
||||
|
||||
group = parser.add_option_group("General options")
|
||||
group.add_option('-v', '--verbose', dest="verbose", help="Print extra output")
|
||||
|
||||
# now we need to derive the short options. we initialize the known fixed longopts and shortopts
|
||||
longopts = [ '--verbose' ]
|
||||
|
||||
# we add the known long options, sorted and grouped to guarantee a stable short opt set regardless of order
|
||||
if api_callable and api_options:
|
||||
longopts += sorted([ x[0][0] for x in api_options ])
|
||||
if cmd_callable and cmd_options:
|
||||
longopts += sorted([ x[0][0] for x in cmd_options ])
|
||||
|
||||
# we use this function to derive a suitable short option and remember the already-used short options
|
||||
def derive_shortopt(longopt,usedopts):
|
||||
"""longopt begins with a dash"""
|
||||
shortopt = None
|
||||
for x in xrange(2,10000):
|
||||
try: shortopt = "-" + longopt[x]
|
||||
except IndexError:
|
||||
shortopt = None
|
||||
break
|
||||
if shortopt in usedopts: continue
|
||||
usedopts.append(shortopt)
|
||||
break
|
||||
return shortopt
|
||||
|
||||
# now we loop through the long options and assign a suitable short option, saving the short option for later use
|
||||
long_to_short = {}
|
||||
alreadyusedshorts = []
|
||||
for longopt in longopts:
|
||||
long_to_short[longopt] = derive_shortopt(longopt,alreadyusedshorts)
|
||||
|
||||
parser.api_dests = []
|
||||
if api_callable and api_options:
|
||||
group = parser.add_option_group("Options for the %s API"%api_name)
|
||||
for a in api_options:
|
||||
shortopt = long_to_short[a[0][0]]
|
||||
if shortopt: group.add_option(shortopt,a[0][0],**a[1])
|
||||
else: group.add_option(a[0][0],**a[1])
|
||||
parser.api_dests.append(a[1]["dest"])
|
||||
|
||||
parser.cmd_dests = []
|
||||
if cmd_callable and cmd_options:
|
||||
group = parser.add_option_group("Options for the %s command"%cmd_name)
|
||||
for a in cmd_options:
|
||||
shortopt = long_to_short[a[0][0]]
|
||||
if shortopt: group.add_option(shortopt,a[0][0],**a[1])
|
||||
else: group.add_option(a[0][0],**a[1])
|
||||
parser.cmd_dests.append(a[1]["dest"])
|
||||
|
||||
return parser
|
||||
|
||||
def lookup_command_in_api(api,command_name):
|
||||
command = getattr(api,command_name.replace("-","_"),None)
|
||||
return command
|
||||
|
||||
def get_api_list():
|
||||
apilist = []
|
||||
for api in apis.get_all_apis():
|
||||
api_module = api
|
||||
api_name = api.__name__.split(".")[-1]
|
||||
if not api_name.startswith("_") and hasattr(api_module,'__doc__'):
|
||||
apilist.append( " %20s %s"%(api_name.replace("_",'-'),api_module.__doc__) )
|
||||
return apilist
|
||||
|
||||
def get_command_list(api):
|
||||
cmds = []
|
||||
for cmd_name in dir(api):
|
||||
cmd = getattr(api,cmd_name)
|
||||
if callable(cmd) and not cmd_name.startswith("_"):
|
||||
if cmd.__doc__: docstring = cmd.__doc__
|
||||
else: docstring = ''
|
||||
cmds.append( " %s %s"%(cmd_name.replace('_','-'),docstring) )
|
||||
return cmds
|
||||
14
cloud.spec
14
cloud.spec
|
|
@ -274,6 +274,13 @@ Group: System Environment/Libraries
|
|||
The Cloud.com console proxy is the service in charge of granting console
|
||||
access into virtual machines managed by the Cloud.com CloudStack.
|
||||
|
||||
%package cli
|
||||
Summary: Cloud.com command line tools
|
||||
Requires: python
|
||||
Group: System Environment/Libraries
|
||||
%description cli
|
||||
The Cloud.com command line tools contain a few Python modules that can call cloudStack APIs.
|
||||
|
||||
|
||||
%if %{_premium}
|
||||
|
||||
|
|
@ -619,6 +626,13 @@ fi
|
|||
%attr(0755,root,root) %{_bindir}/%{name}-setup-console-proxy
|
||||
%dir %attr(770,root,root) %{_localstatedir}/log/%{name}/console-proxy
|
||||
|
||||
%files cli
|
||||
%{_bindir}/%{name}-tool
|
||||
%{_sysconfdir}/%{name}/cli/commands.xml
|
||||
%dir %{_prefix}/lib*/python*/site-packages/%{name}tool
|
||||
%{_prefix}/lib*/python*/site-packages/%{name}tool/*
|
||||
%{_prefix}/lib*/python*/site-packages/%{name}apis.py
|
||||
|
||||
%if %{_premium}
|
||||
|
||||
%files test
|
||||
|
|
|
|||
|
|
@ -0,0 +1,166 @@
|
|||
/**
|
||||
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the GNU General Public License v3 or later.
|
||||
*
|
||||
* It is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.cloud.utils.commandlinetool;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
|
||||
public class BuildCommandLineInputFile {
|
||||
private static Properties api_commands = new Properties();
|
||||
private static String dirName="";
|
||||
|
||||
public static void main (String[] args) {
|
||||
Properties preProcessedCommands = new Properties();
|
||||
Class clas = null;
|
||||
Enumeration e = null;
|
||||
String[] fileNames = null;
|
||||
|
||||
//load properties
|
||||
List<String> argsList = Arrays.asList(args);
|
||||
Iterator<String> iter = argsList.iterator();
|
||||
while (iter.hasNext()) {
|
||||
String arg = iter.next();
|
||||
// populate the file names
|
||||
if (arg.equals("-f")) {
|
||||
fileNames = iter.next().split(",");
|
||||
}
|
||||
if (arg.equals("-d")) {
|
||||
dirName = iter.next();
|
||||
}
|
||||
}
|
||||
|
||||
if ((fileNames == null) || (fileNames.length == 0)){
|
||||
System.out.println("Please specify input file(s) separated by coma using -f option");
|
||||
System.exit(2);
|
||||
}
|
||||
|
||||
for (String fileName : fileNames) {
|
||||
try {
|
||||
FileInputStream in = new FileInputStream(fileName);
|
||||
preProcessedCommands.load(in);
|
||||
}catch (FileNotFoundException ex) {
|
||||
System.out.println("Can't find file " + fileName);
|
||||
System.exit(2);
|
||||
} catch (IOException ex1) {
|
||||
System.out.println("Error reading from file " + ex1);
|
||||
System.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Object key : preProcessedCommands.keySet()) {
|
||||
String preProcessedCommand = preProcessedCommands.getProperty((String)key);
|
||||
String[] commandParts = preProcessedCommand.split(";");
|
||||
api_commands.put(key, commandParts[0]);
|
||||
}
|
||||
|
||||
|
||||
e = api_commands.propertyNames();
|
||||
|
||||
try {
|
||||
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
|
||||
Document doc = docBuilder.newDocument();
|
||||
Element root = doc.createElement("commands");
|
||||
doc.appendChild(root);
|
||||
|
||||
while (e.hasMoreElements()) {
|
||||
String key = (String) e.nextElement();
|
||||
try {
|
||||
clas = Class.forName(api_commands.getProperty(key));
|
||||
Element child1 = doc.createElement("command");
|
||||
root.appendChild(child1);
|
||||
Element child2 = doc.createElement("name");
|
||||
child1.appendChild(child2);
|
||||
Text text = doc.createTextNode(key);
|
||||
child2.appendChild(text);
|
||||
|
||||
Field m[] = clas.getDeclaredFields();
|
||||
for (int i = 0; i < m.length; i++) {
|
||||
if (m[i].getName().endsWith("s_properties")) {
|
||||
m[i].setAccessible(true);
|
||||
List<Pair<Enum, Boolean>> properties = (List<Pair<Enum, Boolean>>) m[i].get(null);
|
||||
for (Pair property : properties){
|
||||
if (!property.first().toString().equals("ACCOUNT_OBJ") && !property.first().toString().equals("USER_ID")){
|
||||
Element child3 = doc.createElement("arg");
|
||||
child1.appendChild(child3);
|
||||
Class clas2 = property.first().getClass();
|
||||
Method m2 = clas2.getMethod("getName");
|
||||
text = doc.createTextNode(m2.invoke(property.first()).toString());
|
||||
child3.appendChild(text);
|
||||
child3.setAttribute("required", property.second().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException ex2) {
|
||||
System.out.println("Can't find class " + api_commands.getProperty(key));
|
||||
System.exit(2);
|
||||
}
|
||||
}
|
||||
TransformerFactory transfac = TransformerFactory.newInstance();
|
||||
Transformer trans = transfac.newTransformer();
|
||||
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
|
||||
trans.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
StreamResult result = new StreamResult(sw);
|
||||
DOMSource source = new DOMSource(doc);
|
||||
trans.transform(source, result);
|
||||
String xmlString = sw.toString();
|
||||
|
||||
//write xml to file
|
||||
File f=new File(dirName + "/commands.xml");
|
||||
Writer output = new BufferedWriter(new FileWriter(f));
|
||||
output.write(xmlString);
|
||||
output.close();
|
||||
} catch (Exception ex) {
|
||||
System.out.println(ex);
|
||||
System.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -412,6 +412,31 @@ for vendor in _glob(_join("vendor","*")) + _glob(_join("cloudstack-proprietary",
|
|||
|
||||
# ====================== End vendor-specific plugins ====================
|
||||
|
||||
def generate_xml_api_description(task):
|
||||
relationship = Utils.relpath(sourcedir,os.getcwd())
|
||||
cp = [ _join(relationship,x) for x in task.generator.env.CLASSPATH.split(pathsep) ]
|
||||
buildproducts = [ x.bldpath(task.env) for x in task.inputs ]
|
||||
jars = [ x for x in buildproducts if x.endswith("jar") ]
|
||||
properties = [ x for x in buildproducts if x.endswith("properties") ]
|
||||
cp += jars
|
||||
cp = pathsep.join(cp)
|
||||
arguments = ["-f",",".join(properties),"-d",builddir]
|
||||
ret = Utils.exec_command(["java","-cp",cp,"com.cloud.utils.commandlinetool.BuildCommandLineInputFile"]+arguments,log=True)
|
||||
return ret
|
||||
props = " client/tomcatconf/commands.properties"
|
||||
jarnames = ['utils','server','core', 'api']
|
||||
tgen = bld(
|
||||
rule = generate_xml_api_description,
|
||||
source = " ".join( [ 'target/jar/cloud-%s.jar'%x for x in jarnames ] ) + props,
|
||||
target = 'commands.xml',
|
||||
name = 'xmlapi',
|
||||
after = 'runant',
|
||||
install_path="${CLIDIR}"
|
||||
)
|
||||
#bld.process_after(tgen)
|
||||
|
||||
bld.install_files("${PYTHONDIR}/cloudtool", 'cloud-cli/cloudtool/*')
|
||||
bld.install_as("${PYTHONDIR}/cloudapis.py", 'cloud-cli/cloudapis/cloud.py')
|
||||
|
||||
# ====================== Magic! =========================================
|
||||
|
||||
|
|
|
|||
|
|
@ -273,6 +273,8 @@ conf.env.CPLIBDIR = Utils.subst_vars(_join("${LIBDIR}","${CPPATH}"),conf.env)
|
|||
conf.env.CPSYSCONFDIR = Utils.subst_vars(_join("${SYSCONFDIR}","${CPPATH}"),conf.env)
|
||||
conf.env.CPLOGDIR = Utils.subst_vars(_join("${LOCALSTATEDIR}","log","${CPPATH}"),conf.env)
|
||||
|
||||
conf.env.CLIPATH = _join(conf.env.PACKAGE,"cli")
|
||||
|
||||
conf.env.IPALLOCATORLIBDIR = Utils.subst_vars(_join("${LIBDIR}","${IPALLOCATORPATH}"),conf.env)
|
||||
conf.env.IPALLOCATORSYSCONFDIR = Utils.subst_vars(_join("${SYSCONFDIR}","${IPALLOCATORPATH}"),conf.env)
|
||||
conf.env.IPALLOCATORLOGDIR = Utils.subst_vars(_join("${LOCALSTATEDIR}","log","${IPALLOCATORPATH}"),conf.env)
|
||||
|
|
@ -286,6 +288,8 @@ conf.env.IPALOCATORLOG = _join(conf.env.IPALLOCATORLOGDIR,"ipallocator.log")
|
|||
|
||||
conf.env.SETUPDATADIR = Utils.subst_vars(_join("${DATADIR}","${SETUPPATH}"),conf.env)
|
||||
|
||||
conf.env.CLIDIR = Utils.subst_vars(_join("${SYSCONFDIR}","${CLIPATH}"),conf.env)
|
||||
|
||||
conf.env.SERVERSYSCONFDIR = Utils.subst_vars(_join("${SYSCONFDIR}","${SERVERPATH}"),conf.env)
|
||||
|
||||
if conf.env.DISTRO in ["Windows"]:
|
||||
|
|
|
|||
Loading…
Reference in New Issue