mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			290 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # Copyright 2012 Citrix Systems, Inc. Licensed under the
 | |
| # Apache License, Version 2.0 (the "License"); you may not use this
 | |
| # file except in compliance with the License.  Citrix Systems, Inc.
 | |
| # reserves all rights not expressly granted by 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 KIND, either express or implied.
 | |
| # See the License for the specific language governing permissions and
 | |
| # limitations under the License.
 | |
| # 
 | |
| # Automatically generated by addcopyright.py at 04/03/2012
 | |
| import xml.dom.minidom
 | |
| from optparse import OptionParser
 | |
| import os
 | |
| import sys
 | |
| class cmdParameterProperty(object):
 | |
|     def __init__(self):
 | |
|         self.name = None
 | |
|         self.required = False
 | |
|         self.desc = ""
 | |
|         self.type = "planObject"
 | |
|         self.subProperties = []
 | |
|         
 | |
| class cloudStackCmd:
 | |
|     def __init__(self):
 | |
|         self.name = ""
 | |
|         self.desc = ""
 | |
|         self.async = "false"
 | |
|         self.request = []
 | |
|         self.response = []
 | |
| 
 | |
| class codeGenerator:
 | |
|     space = "    "
 | |
| 
 | |
|     cmdsName = []
 | |
|     
 | |
|     def __init__(self, outputFolder, apiSpecFile):
 | |
|         self.cmd = None
 | |
|         self.code = ""
 | |
|         self.required = []
 | |
|         self.subclass = []
 | |
|         self.outputFolder = outputFolder
 | |
|         self.apiSpecFile = apiSpecFile
 | |
|         
 | |
|     def addAttribute(self, attr, pro):
 | |
|         value = pro.value
 | |
|         if pro.required:
 | |
|             self.required.append(attr)
 | |
|         desc = pro.desc
 | |
|         if desc is not None:
 | |
|             self.code += self.space
 | |
|             self.code += "''' " + pro.desc + " '''"
 | |
|             self.code += "\n"
 | |
|         
 | |
|         self.code += self.space
 | |
|         self.code += attr + " = " + str(value)
 | |
|         self.code += "\n"
 | |
|     
 | |
|     def generateSubClass(self, name, properties):
 | |
|         '''generate code for sub list'''
 | |
|         subclass = 'class %s:\n'%name
 | |
|         subclass += self.space + "def __init__(self):\n"
 | |
|         for pro in properties:
 | |
|             if pro.desc is not None:
 | |
|                 subclass += self.space + self.space + '""""%s"""\n'%pro.desc
 | |
|             if len (pro.subProperties) > 0:
 | |
|                 subclass += self.space + self.space + 'self.%s = []\n'%pro.name
 | |
|                 self.generateSubClass(pro.name, pro.subProperties)
 | |
|             else:
 | |
|                 subclass += self.space + self.space + 'self.%s = None\n'%pro.name
 | |
|         
 | |
|         self.subclass.append(subclass)
 | |
|     def generate(self, cmd):
 | |
|        
 | |
|         self.cmd = cmd
 | |
|         self.cmdsName.append(self.cmd.name)
 | |
|         self.code += "\n"
 | |
|         self.code += '"""%s"""\n'%self.cmd.desc  
 | |
|         self.code += 'from baseCmd import *\n'
 | |
|         self.code += 'from baseResponse import *\n'
 | |
|         self.code += "class %sCmd (baseCmd):\n"%self.cmd.name
 | |
|         self.code += self.space + "def __init__(self):\n"
 | |
|         
 | |
|         self.code += self.space + self.space + 'self.isAsync = "%s"\n' %self.cmd.async
 | |
|         
 | |
|         for req in self.cmd.request:
 | |
|             if req.desc is not None:
 | |
|                 self.code += self.space + self.space + '"""%s"""\n'%req.desc
 | |
|             if req.required == "true":
 | |
|                 self.code += self.space + self.space + '"""Required"""\n'
 | |
|             
 | |
|             value = "None"
 | |
|             if req.type == "list" or req.type == "map":
 | |
|                 value = "[]"
 | |
|             
 | |
|             self.code += self.space + self.space  + 'self.%s = %s\n'%(req.name,value)
 | |
|             if req.required == "true":
 | |
|                 self.required.append(req.name)
 | |
|         
 | |
|         self.code += self.space + self.space + "self.required = ["
 | |
|         for require in self.required:
 | |
|             self.code += '"' + require + '",'
 | |
|         self.code += "]\n"
 | |
|         self.required = []
 | |
|         
 | |
|         
 | |
|         """generate response code"""
 | |
|         subItems = {}
 | |
|         self.code += "\n"
 | |
|         self.code += 'class %sResponse (baseResponse):\n'%self.cmd.name
 | |
|         self.code += self.space + "def __init__(self):\n"
 | |
|         if len(self.cmd.response) == 0:
 | |
|             self.code += self.space + self.space + "pass"
 | |
|         else:
 | |
|             for res in self.cmd.response:
 | |
|                 if res.desc is not None:
 | |
|                     self.code += self.space + self.space + '"""%s"""\n'%res.desc
 | |
|             
 | |
|                 if len(res.subProperties) > 0:
 | |
|                     self.code += self.space + self.space + 'self.%s = []\n'%res.name
 | |
|                     self.generateSubClass(res.name, res.subProperties)
 | |
|                 else:
 | |
|                     self.code += self.space + self.space + 'self.%s = None\n'%res.name
 | |
|         self.code += '\n'
 | |
|         
 | |
|         for subclass in self.subclass:
 | |
|             self.code += subclass + "\n"
 | |
|         
 | |
|         fp = open(self.outputFolder + "/cloudstackAPI/%s.py"%self.cmd.name, "w")
 | |
|         fp.write(self.code)
 | |
|         fp.close()
 | |
|         self.code = ""
 | |
|         self.subclass = []
 | |
|        
 | |
|         
 | |
|     def finalize(self):
 | |
|         '''generate an api call'''
 | |
|         
 | |
|         header = '"""Test Client for CloudStack API"""\n'
 | |
|         imports = "import copy\n"
 | |
|         initCmdsList = '__all__ = ['
 | |
|         body = ''
 | |
|         body += "class CloudStackAPIClient:\n"
 | |
|         body += self.space + 'def __init__(self, connection):\n'
 | |
|         body += self.space + self.space + 'self.connection = connection\n'
 | |
|         body += "\n"
 | |
|         
 | |
|         body += self.space + 'def __copy__(self):\n'
 | |
|         body += self.space + self.space + 'return CloudStackAPIClient(copy.copy(self.connection))\n'
 | |
|         body += "\n"
 | |
|         
 | |
|         for cmdName in self.cmdsName:
 | |
|             body += self.space + 'def %s(self,command):\n'%cmdName
 | |
|             body += self.space + self.space + 'response = %sResponse()\n'%cmdName
 | |
|             body += self.space + self.space + 'response = self.connection.make_request(command, response)\n'
 | |
|             body += self.space + self.space + 'return response\n'
 | |
|             body += '\n'
 | |
|         
 | |
|             imports += 'from %s import %sResponse\n'%(cmdName, cmdName)
 | |
|             initCmdsList += '"%s",'%cmdName
 | |
|         
 | |
|         fp = open(self.outputFolder + '/cloudstackAPI/cloudstackAPIClient.py', 'w')
 | |
|         for item in [header, imports, body]:
 | |
|             fp.write(item)
 | |
|         fp.close()
 | |
|         
 | |
|         '''generate __init__.py'''
 | |
|         initCmdsList += '"cloudstackAPIClient"]'
 | |
|         fp = open(self.outputFolder + '/cloudstackAPI/__init__.py', 'w')
 | |
|         fp.write(initCmdsList)
 | |
|         fp.close()
 | |
|         
 | |
|         fp = open(self.outputFolder + '/cloudstackAPI/baseCmd.py', 'w')
 | |
|         basecmd = '"""Base Command"""\n'
 | |
|         basecmd += 'class baseCmd:\n'
 | |
|         basecmd += self.space + 'pass\n'
 | |
|         fp.write(basecmd)
 | |
|         fp.close()
 | |
|         
 | |
|         fp = open(self.outputFolder + '/cloudstackAPI/baseResponse.py', 'w')
 | |
|         basecmd = '"""Base class for response"""\n'
 | |
|         basecmd += 'class baseResponse:\n'
 | |
|         basecmd += self.space + 'pass\n'
 | |
|         fp.write(basecmd)
 | |
|         fp.close()
 | |
|         
 | |
|     
 | |
|     def constructResponse(self, response):
 | |
|         paramProperty = cmdParameterProperty()
 | |
|         paramProperty.name = getText(response.getElementsByTagName('name'))
 | |
|         paramProperty.desc = getText(response.getElementsByTagName('description'))
 | |
|         if paramProperty.name.find('(*)') != -1:
 | |
|             '''This is a list'''
 | |
|             paramProperty.name = paramProperty.name.split('(*)')[0]
 | |
|             for subresponse in response.getElementsByTagName('arguments')[0].getElementsByTagName('arg'):
 | |
|                 subProperty = self.constructResponse(subresponse)
 | |
|                 paramProperty.subProperties.append(subProperty)
 | |
|         return paramProperty
 | |
| 
 | |
|     def loadCmdFromXML(self):
 | |
|         dom = xml.dom.minidom.parse(self.apiSpecFile)
 | |
|         cmds = []
 | |
|         for cmd in dom.getElementsByTagName("command"):
 | |
|             csCmd = cloudStackCmd()
 | |
|             csCmd.name = getText(cmd.getElementsByTagName('name'))
 | |
|             assert csCmd.name
 | |
|         
 | |
|             desc = getText(cmd.getElementsByTagName('description'))
 | |
|             if desc: 
 | |
|                 csCmd.desc = desc
 | |
|     
 | |
|             async = getText(cmd.getElementsByTagName('isAsync'))
 | |
|             if async:
 | |
|                 csCmd.async = async
 | |
|         
 | |
|             for param in cmd.getElementsByTagName("request")[0].getElementsByTagName("arg"):
 | |
|                 paramProperty = cmdParameterProperty()
 | |
|             
 | |
|                 paramProperty.name = getText(param.getElementsByTagName('name'))
 | |
|                 assert paramProperty.name
 | |
|             
 | |
|                 required = param.getElementsByTagName('required')
 | |
|                 if required:
 | |
|                     paramProperty.required = getText(required)
 | |
|             
 | |
|                 requestDescription = param.getElementsByTagName('description')
 | |
|                 if requestDescription:            
 | |
|                     paramProperty.desc = getText(requestDescription)
 | |
|             
 | |
|                 type = param.getElementsByTagName("type")
 | |
|                 if type:
 | |
|                     paramProperty.type = getText(type)
 | |
|                 
 | |
|                 csCmd.request.append(paramProperty)
 | |
|         
 | |
|             responseEle = cmd.getElementsByTagName("response")[0]
 | |
|             for response in responseEle.getElementsByTagName("arg"):
 | |
|                 if response.parentNode != responseEle:
 | |
|                     continue
 | |
|             
 | |
|                 paramProperty = self.constructResponse(response)
 | |
|                 csCmd.response.append(paramProperty)
 | |
|             
 | |
|             cmds.append(csCmd)
 | |
|         return cmds
 | |
|     
 | |
|     def generateCode(self):
 | |
|         cmds = self.loadCmdFromXML()
 | |
|         for cmd in cmds:
 | |
|             self.generate(cmd)
 | |
|         self.finalize()
 | |
| 
 | |
| def getText(elements):
 | |
|     return elements[0].childNodes[0].nodeValue.strip()
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     parser = OptionParser()
 | |
|   
 | |
|     parser.add_option("-o", "--output", dest="output", help="the root path where code genereted, default is .")
 | |
|     parser.add_option("-s", "--specfile", dest="spec", help="the path and name of the api spec xml file, default is /etc/cloud/cli/commands.xml")
 | |
|     
 | |
|     (options, args) = parser.parse_args()
 | |
|     
 | |
|     apiSpecFile = "/etc/cloud/cli/commands.xml"
 | |
|     if options.spec is not None:
 | |
|         apiSpecFile = options.spec
 | |
|     
 | |
|     if not os.path.exists(apiSpecFile):
 | |
|         print "the spec file %s does not exists"%apiSpecFile
 | |
|         print parser.print_help()
 | |
|         exit(1)
 | |
|     
 | |
| 
 | |
|     folder = "."
 | |
|     if options.output is not None:
 | |
|         folder = options.output
 | |
|     apiModule=folder + "/cloudstackAPI"
 | |
|     if not os.path.exists(apiModule):
 | |
|         try:
 | |
|             os.mkdir(apiModule)
 | |
|         except:
 | |
|             print "Failed to create folder %s, due to %s"%(apiModule,sys.exc_info())
 | |
|             print parser.print_help()
 | |
|             exit(2)
 | |
|     
 | |
|     cg = codeGenerator(folder, apiSpecFile)
 | |
|     cg.generateCode()
 | |
|     
 |