mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Fixed command line tool
This commit is contained in:
parent
ad3c18a46c
commit
fe2fc63692
@ -1,63 +0,0 @@
|
|||||||
'''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
|
|
||||||
@ -58,26 +58,32 @@ def load_dynamic_methods():
|
|||||||
name = getText(cmd.getElementsByTagName('name')[0].childNodes).strip()
|
name = getText(cmd.getElementsByTagName('name')[0].childNodes).strip()
|
||||||
assert name
|
assert name
|
||||||
|
|
||||||
description = cmd.getElementsByTagName('name')[0].getAttribute("description")
|
description = getText(cmd.getElementsByTagName('description')[0].childNodes).strip()
|
||||||
if description: description = '"""%s"""' % description
|
if description:
|
||||||
|
description = '"""%s"""' % description
|
||||||
else: description = ''
|
else: description = ''
|
||||||
arguments = []
|
arguments = []
|
||||||
options = []
|
options = []
|
||||||
descriptions = []
|
descriptions = []
|
||||||
|
|
||||||
for param in cmd.getElementsByTagName('arg'):
|
for param in cmd.getElementsByTagName("request")[0].getElementsByTagName("arg"):
|
||||||
argname = getText(param.childNodes).strip()
|
argname = getText(param.getElementsByTagName('name')[0].childNodes).strip()
|
||||||
assert argname
|
assert argname
|
||||||
|
|
||||||
required = param.getAttribute("required").strip()
|
required = getText(param.getElementsByTagName('required')[0].childNodes).strip()
|
||||||
if required == 'true': required = True
|
if required == 'true': required = True
|
||||||
elif required == 'false': required = False
|
elif required == 'false': required = False
|
||||||
else: raise AssertionError, "Not reached"
|
else: raise AssertionError, "Not reached"
|
||||||
if required: arguments.append(argname)
|
if required: arguments.append(argname)
|
||||||
options.append(argname)
|
options.append(argname)
|
||||||
|
|
||||||
description = param.getAttribute("description").strip()
|
#import ipdb; ipdb.set_trace()
|
||||||
if description: descriptions.append( (argname,description) )
|
requestDescription = param.getElementsByTagName('description')
|
||||||
|
if requestDescription:
|
||||||
|
descriptionParam = getText(requestDescription[0].childNodes)
|
||||||
|
else:
|
||||||
|
descriptionParam = ''
|
||||||
|
if descriptionParam: descriptions.append( (argname,descriptionParam) )
|
||||||
|
|
||||||
funcparams = ["self"] + [ "%s=None"%o for o in options ]
|
funcparams = ["self"] + [ "%s=None"%o for o in options ]
|
||||||
funcparams = ", ".join(funcparams)
|
funcparams = ", ".join(funcparams)
|
||||||
@ -95,7 +101,7 @@ def load_dynamic_methods():
|
|||||||
output = self._make_request("%s",parms)
|
output = self._make_request("%s",parms)
|
||||||
return output
|
return output
|
||||||
"""%(name,funcparams,description,arguments,name)
|
"""%(name,funcparams,description,arguments,name)
|
||||||
|
|
||||||
namespace = {}
|
namespace = {}
|
||||||
exec code.strip() in namespace
|
exec code.strip() in namespace
|
||||||
|
|
||||||
@ -106,7 +112,8 @@ def load_dynamic_methods():
|
|||||||
yield (name,func)
|
yield (name,func)
|
||||||
|
|
||||||
|
|
||||||
for name,meth in load_dynamic_methods(): setattr(CloudAPI,name,meth)
|
for name,meth in load_dynamic_methods():
|
||||||
|
setattr(CloudAPI, name, meth)
|
||||||
|
|
||||||
implementor = CloudAPI
|
implementor = CloudAPI
|
||||||
|
|
||||||
|
|||||||
@ -11,25 +11,27 @@ import cloudtool.utils as utils
|
|||||||
|
|
||||||
def main(argv=None):
|
def main(argv=None):
|
||||||
|
|
||||||
|
#import ipdb; ipdb.set_trace()
|
||||||
if argv == None:
|
if argv == None:
|
||||||
argv = sys.argv
|
argv = sys.argv
|
||||||
|
|
||||||
prelim_args = [ x for x in argv[1:] if not x.startswith('-') ]
|
prelim_args = [ x for x in argv[0:] if not x.startswith('-') ]
|
||||||
parser = utils.get_parser()
|
parser = utils.get_parser()
|
||||||
|
|
||||||
api = __import__("cloudapis")
|
api = __import__("cloudapis")
|
||||||
apis = getattr(api, "implementor")
|
apis = getattr(api, "implementor")
|
||||||
if len(prelim_args) == 0:
|
if len(prelim_args) == 1:
|
||||||
parser.error("you need to specify an API as the first argument\n\nSupported APIs:\n" + "\n".join(utils.get_api_list(apis)))
|
|
||||||
elif len(prelim_args) == 1:
|
|
||||||
commandlist = utils.get_command_list(apis)
|
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))
|
parser.error("you need to specify a command name as the first 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])
|
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]))
|
if not command: parser.error("command %r not supported by the %s API"%(prelim_args[1],prelim_args[0]))
|
||||||
|
|
||||||
|
argv = argv[1:]
|
||||||
|
if len(argv) == 1:
|
||||||
|
argv.append("--help")
|
||||||
|
|
||||||
parser = utils.get_parser(apis.__init__,command)
|
parser = utils.get_parser(apis.__init__,command)
|
||||||
argv = argv[1:]
|
|
||||||
opts,args,api_optionsdict,cmd_optionsdict = parser.parse_args(argv)
|
opts,args,api_optionsdict,cmd_optionsdict = parser.parse_args(argv)
|
||||||
|
|
||||||
|
|
||||||
@ -38,7 +40,7 @@ def main(argv=None):
|
|||||||
except utils.OptParseError,e:
|
except utils.OptParseError,e:
|
||||||
parser.error(str(e))
|
parser.error(str(e))
|
||||||
|
|
||||||
command = utils.lookup_command_in_api(api,args[1])
|
command = utils.lookup_command_in_api(api,args[0])
|
||||||
|
|
||||||
# we now discard the first two arguments as those necessarily are the api and command names
|
# we now discard the first two arguments as those necessarily are the api and command names
|
||||||
args = args[2:]
|
args = args[2:]
|
||||||
|
|||||||
@ -112,51 +112,18 @@ def get_parser(api_callable=None,cmd_callable=None): # this should probably be t
|
|||||||
group = parser.add_option_group("General options")
|
group = parser.add_option_group("General options")
|
||||||
group.add_option('-v', '--verbose', dest="verbose", help="Print extra output")
|
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 = []
|
parser.api_dests = []
|
||||||
if api_callable and api_options:
|
if api_callable and api_options:
|
||||||
group = parser.add_option_group("Options for the %s API"%api_name)
|
group = parser.add_option_group("Options for the %s API"%api_name)
|
||||||
for a in api_options:
|
for a in api_options:
|
||||||
shortopt = long_to_short[a[0][0]]
|
group.add_option(a[0][0],**a[1])
|
||||||
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.api_dests.append(a[1]["dest"])
|
||||||
|
|
||||||
parser.cmd_dests = []
|
parser.cmd_dests = []
|
||||||
if cmd_callable and cmd_options:
|
if cmd_callable and cmd_options:
|
||||||
group = parser.add_option_group("Options for the %s command"%cmd_name)
|
group = parser.add_option_group("Options for the %s command"%cmd_name)
|
||||||
for a in cmd_options:
|
for a in cmd_options:
|
||||||
shortopt = long_to_short[a[0][0]]
|
group.add_option(a[0][0],**a[1])
|
||||||
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"])
|
parser.cmd_dests.append(a[1]["dest"])
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
@ -178,7 +145,7 @@ def get_command_list(api):
|
|||||||
for cmd_name in dir(api):
|
for cmd_name in dir(api):
|
||||||
cmd = getattr(api,cmd_name)
|
cmd = getattr(api,cmd_name)
|
||||||
if callable(cmd) and not cmd_name.startswith("_"):
|
if callable(cmd) and not cmd_name.startswith("_"):
|
||||||
if cmd.__doc__: docstring = cmd.__doc__
|
if cmd.__doc__:docstring = cmd.__doc__
|
||||||
else: docstring = ''
|
else:docstring = ''
|
||||||
cmds.append( " %s %s"%(cmd_name.replace('_','-'),docstring) )
|
cmds.append( " %s" % (cmd_name.replace('_','-')) )
|
||||||
return cmds
|
return cmds
|
||||||
|
|||||||
@ -1,166 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -421,7 +421,7 @@ def generate_xml_api_description(task):
|
|||||||
cp += jars
|
cp += jars
|
||||||
cp = pathsep.join(cp)
|
cp = pathsep.join(cp)
|
||||||
arguments = ["-f",",".join(properties),"-d",builddir]
|
arguments = ["-f",",".join(properties),"-d",builddir]
|
||||||
ret = Utils.exec_command(["java","-cp",cp,"com.cloud.utils.commandlinetool.BuildCommandLineInputFile"]+arguments,log=True)
|
ret = Utils.exec_command(["java","-cp",cp,"com.cloud.api.doc.ApiXmlDocWriter"]+arguments,log=True)
|
||||||
return ret
|
return ret
|
||||||
props = " client/tomcatconf/commands.properties"
|
props = " client/tomcatconf/commands.properties"
|
||||||
jarnames = ['utils','server','core', 'api']
|
jarnames = ['utils','server','core', 'api']
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user