From fe2fc63692fd0878d9880147e3219ceddbcec34a Mon Sep 17 00:00:00 2001 From: alena Date: Thu, 28 Oct 2010 23:10:12 -0700 Subject: [PATCH] Fixed command line tool --- cloud-cli/cloudapis/amazon.py | 63 ------- cloud-cli/cloudapis/cloud.py | 25 ++- cloud-cli/cloudtool/__init__.py | 18 +- cloud-cli/cloudtool/utils.py | 43 +---- .../BuildCommandLineInputFile.java | 166 ------------------ wscript_build | 2 +- 6 files changed, 32 insertions(+), 285 deletions(-) delete mode 100644 cloud-cli/cloudapis/amazon.py delete mode 100644 utils/src/com/cloud/utils/commandlinetool/BuildCommandLineInputFile.java diff --git a/cloud-cli/cloudapis/amazon.py b/cloud-cli/cloudapis/amazon.py deleted file mode 100644 index c6911d6ed2d..00000000000 --- a/cloud-cli/cloudapis/amazon.py +++ /dev/null @@ -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 \ No newline at end of file diff --git a/cloud-cli/cloudapis/cloud.py b/cloud-cli/cloudapis/cloud.py index 07276b4446e..be703dd16e9 100644 --- a/cloud-cli/cloudapis/cloud.py +++ b/cloud-cli/cloudapis/cloud.py @@ -58,26 +58,32 @@ def load_dynamic_methods(): name = getText(cmd.getElementsByTagName('name')[0].childNodes).strip() assert name - description = cmd.getElementsByTagName('name')[0].getAttribute("description") - if description: description = '"""%s"""' % description + description = getText(cmd.getElementsByTagName('description')[0].childNodes).strip() + if description: + description = '"""%s"""' % description else: description = '' arguments = [] options = [] descriptions = [] - for param in cmd.getElementsByTagName('arg'): - argname = getText(param.childNodes).strip() + for param in cmd.getElementsByTagName("request")[0].getElementsByTagName("arg"): + argname = getText(param.getElementsByTagName('name')[0].childNodes).strip() assert argname - required = param.getAttribute("required").strip() + 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) - description = param.getAttribute("description").strip() - if description: descriptions.append( (argname,description) ) + #import ipdb; ipdb.set_trace() + 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 = ", ".join(funcparams) @@ -95,7 +101,7 @@ def load_dynamic_methods(): output = self._make_request("%s",parms) return output """%(name,funcparams,description,arguments,name) - + namespace = {} exec code.strip() in namespace @@ -106,7 +112,8 @@ def load_dynamic_methods(): 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 diff --git a/cloud-cli/cloudtool/__init__.py b/cloud-cli/cloudtool/__init__.py index a1062ff529c..d1b41c8cc2c 100644 --- a/cloud-cli/cloudtool/__init__.py +++ b/cloud-cli/cloudtool/__init__.py @@ -11,25 +11,27 @@ import cloudtool.utils as utils def main(argv=None): + #import ipdb; ipdb.set_trace() if argv == None: 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() - + 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(apis))) - elif len(prelim_args) == 1: + if 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)) + 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]) 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) - argv = argv[1:] opts,args,api_optionsdict,cmd_optionsdict = parser.parse_args(argv) @@ -38,7 +40,7 @@ def main(argv=None): except utils.OptParseError,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 args = args[2:] diff --git a/cloud-cli/cloudtool/utils.py b/cloud-cli/cloudtool/utils.py index 6c7456feb42..5762be64735 100644 --- a/cloud-cli/cloudtool/utils.py +++ b/cloud-cli/cloudtool/utils.py @@ -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.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]) + 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]) + group.add_option(a[0][0],**a[1]) parser.cmd_dests.append(a[1]["dest"]) return parser @@ -178,7 +145,7 @@ def get_command_list(api): 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) ) + if cmd.__doc__:docstring = cmd.__doc__ + else:docstring = '' + cmds.append( " %s" % (cmd_name.replace('_','-')) ) return cmds diff --git a/utils/src/com/cloud/utils/commandlinetool/BuildCommandLineInputFile.java b/utils/src/com/cloud/utils/commandlinetool/BuildCommandLineInputFile.java deleted file mode 100644 index f2a77615b9f..00000000000 --- a/utils/src/com/cloud/utils/commandlinetool/BuildCommandLineInputFile.java +++ /dev/null @@ -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 . - * - */ - -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 argsList = Arrays.asList(args); - Iterator 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> properties = (List>) 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); - } - } - -} \ No newline at end of file diff --git a/wscript_build b/wscript_build index 6cb90d4afcd..3dbf48123fb 100644 --- a/wscript_build +++ b/wscript_build @@ -421,7 +421,7 @@ def generate_xml_api_description(task): 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) + ret = Utils.exec_command(["java","-cp",cp,"com.cloud.api.doc.ApiXmlDocWriter"]+arguments,log=True) return ret props = " client/tomcatconf/commands.properties" jarnames = ['utils','server','core', 'api']