mirror of https://github.com/apache/cloudstack.git
marvin_refactor: provide entity in the api command objects
Also include the entity generation in to the codegenerator so single module can generate both api command objects and the derived entities. Signed-off-by: Prasanna Santhanam <tsp@apache.org>
This commit is contained in:
parent
a789d43ded
commit
8b62f1bb15
|
|
@ -23,6 +23,7 @@ import urllib2
|
|||
from optparse import OptionParser
|
||||
from textwrap import dedent
|
||||
from os import path
|
||||
from cs_entity_generator import write_entity_classes, get_actionable_entities
|
||||
|
||||
|
||||
|
||||
|
|
@ -30,6 +31,7 @@ class cmdParameterProperty(object):
|
|||
def __init__(self):
|
||||
self.name = None
|
||||
self.required = False
|
||||
self.entity = ""
|
||||
self.desc = ""
|
||||
self.type = "planObject"
|
||||
self.subProperties = []
|
||||
|
|
@ -40,6 +42,7 @@ class cloudStackCmd(object):
|
|||
self.name = ""
|
||||
self.desc = ""
|
||||
self.async = "false"
|
||||
self.entity = ""
|
||||
self.request = []
|
||||
self.response = []
|
||||
|
||||
|
|
@ -129,6 +132,7 @@ class codeGenerator(object):
|
|||
self.code += self.space + "def __init__(self):\n"
|
||||
self.code += self.space + self.space
|
||||
self.code += 'self.isAsync = "%s"\n' % str(self.cmd.async).lower()
|
||||
self.code += self.space*2 + 'self.entity = "%s"\n' % self.cmd.entity
|
||||
|
||||
for req in self.cmd.request:
|
||||
if req.desc is not None:
|
||||
|
|
@ -282,6 +286,11 @@ class codeGenerator(object):
|
|||
csCmd = cloudStackCmd()
|
||||
csCmd.name = getText(cmd.getElementsByTagName('name'))
|
||||
assert csCmd.name
|
||||
if csCmd.name in ['login', 'logout']:
|
||||
continue
|
||||
|
||||
csCmd.entity = getText(cmd.getElementsByTagName('entity'))
|
||||
assert csCmd.entity
|
||||
|
||||
desc = getText(cmd.getElementsByTagName('description'))
|
||||
if desc:
|
||||
|
|
@ -300,6 +309,8 @@ class codeGenerator(object):
|
|||
getText(param.getElementsByTagName('name'))
|
||||
assert paramProperty.name
|
||||
|
||||
|
||||
|
||||
required = param.getElementsByTagName('required')
|
||||
if required:
|
||||
paramProperty.required = getText(required)
|
||||
|
|
@ -371,6 +382,12 @@ class codeGenerator(object):
|
|||
if 'name' in cmd:
|
||||
csCmd.name = cmd['name']
|
||||
assert csCmd.name
|
||||
if csCmd.name in ['login', 'logout']:
|
||||
continue
|
||||
|
||||
if cmd.has_key('entity'):
|
||||
csCmd.entity = cmd['entity']
|
||||
assert csCmd.entity
|
||||
|
||||
if 'description' in cmd:
|
||||
csCmd.desc = cmd['description']
|
||||
|
|
@ -465,3 +482,7 @@ if __name__ == "__main__":
|
|||
endpointUrl = 'http://%s:8096/client/api?command=listApis&\
|
||||
response=json' % options.endpoint
|
||||
cg.generateCodeFromJSON(endpointUrl)
|
||||
|
||||
if options.entity:
|
||||
entities = get_actionable_entities(path=apiModule)
|
||||
write_entity_classes(entities, "base2")
|
||||
|
|
|
|||
|
|
@ -15,12 +15,9 @@
|
|||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from marvin.cloudstackAPI import *
|
||||
import os
|
||||
import inflect
|
||||
|
||||
# Grammar for CloudStack APIs
|
||||
grammar = ['create', 'list', 'delete', 'update',
|
||||
grammar = ['create', 'list', 'delete', 'update', 'ldap', 'login', 'logout',
|
||||
'enable', 'activate', 'disable', 'add', 'remove',
|
||||
'attach', 'detach', 'associate', 'generate', 'assign',
|
||||
'authorize', 'change', 'register', 'configure',
|
||||
|
|
@ -29,7 +26,7 @@ grammar = ['create', 'list', 'delete', 'update',
|
|||
'copy', 'extract', 'migrate', 'restore', 'suspend',
|
||||
'get', 'query', 'prepare', 'deploy', 'upload', 'lock',
|
||||
'disassociate', 'scale', 'dedicate', 'archive', 'find',
|
||||
'recover', 'release', 'resize', 'revert']
|
||||
'recover', 'release', 'resize', 'revert', 'replace']
|
||||
|
||||
LICENSE = """# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
|
|
@ -49,15 +46,21 @@ LICENSE = """# Licensed to the Apache Software Foundation (ASF) under one
|
|||
# under the License.
|
||||
"""
|
||||
|
||||
def get_api_cmds():
|
||||
"""@return: instances of all the API commands exposed by CloudStack
|
||||
def get_api_cmds(path=None):
|
||||
""" Returns the API cmdlet instances
|
||||
@param path: path where the api modules are found. defaults to pythonpath
|
||||
@return: instances of all the API commands exposed by CloudStack
|
||||
"""
|
||||
api_classes = __import__('marvin.cloudstackAPI')
|
||||
if path:
|
||||
api_classes = __import__('cloudstackAPI', fromlist=['*'], level=2)
|
||||
else:
|
||||
api_classes = __import__('marvin.cloudstackAPI')
|
||||
|
||||
cmdlist = map(
|
||||
lambda f: getattr(api_classes.cloudstackAPI, f),
|
||||
lambda f: getattr(api_classes, f),
|
||||
filter(
|
||||
lambda t: t.startswith('__') == False,
|
||||
dir(api_classes.cloudstackAPI)
|
||||
dir(api_classes)
|
||||
)
|
||||
)
|
||||
cmdlist = filter(
|
||||
|
|
@ -88,8 +91,12 @@ def transform_api(api):
|
|||
"""
|
||||
if api == 'ldapConfig':
|
||||
return 'configure', 'Ldap'
|
||||
if api == 'ldapRemove':
|
||||
elif api == 'ldapRemove':
|
||||
return 'remove', 'Ldap'
|
||||
elif api == 'login':
|
||||
return 'login', 'CloudStack'
|
||||
elif api == 'logout':
|
||||
return 'logout', 'CloudStack'
|
||||
return api, None
|
||||
|
||||
def post_transform_adjust(entity):
|
||||
|
|
@ -112,12 +119,12 @@ def prepositon_transformer(preposition=None):
|
|||
@param entity: The entity eg: resetPasswordForVirtualMachine, preposition=For
|
||||
@return: transformed entity, Y is the entity and doX is the verb, eg: VirtualMachine, resetPassword
|
||||
"""
|
||||
def transform_api(api):
|
||||
def transform_api_with_preposition(api):
|
||||
if api.find(preposition) > 0:
|
||||
if api[api.find(preposition) + len(preposition)].isupper():
|
||||
return api[:api.find(preposition)], api[api.find(preposition) + len(preposition):]
|
||||
return api, None
|
||||
return transform_api
|
||||
return transform_api_with_preposition
|
||||
|
||||
|
||||
def skip_list():
|
||||
|
|
@ -143,33 +150,36 @@ def get_verb_and_entity(cmd):
|
|||
@return: verb, Entity tuple
|
||||
"""
|
||||
api = cmd.__class__.__name__
|
||||
api = api.replace('Cmd', '')
|
||||
#apply known list of transformations
|
||||
for transformer in get_transformers():
|
||||
api = api.replace('Cmd', '')
|
||||
if transformer(api)[0] != api:
|
||||
print "%s, %s -> %s" % (transformer.__name__, api, transformer(api))
|
||||
verb, entity = transformer(api)[0], \
|
||||
singularize(transformer(api)[1]) if singularize(transformer(api)[1]) else transformer(api)[1]
|
||||
return verb, post_transform_adjust(entity)
|
||||
|
||||
matching_verbs = filter(lambda v: api.startswith(v), grammar)
|
||||
if len(matching_verbs) > 0:
|
||||
verb = matching_verbs[0]
|
||||
entity = api.replace(verb, '').replace('Cmd', '')
|
||||
entity = singularize(entity) if singularize(entity) else entity
|
||||
for transformer in get_transformers():
|
||||
if transformer(api)[1]:
|
||||
# print "%s, %s -> %s" % (transformer.__name__, api, transformer(api))
|
||||
verb = transformer(api)[0]
|
||||
entity = singularize(cmd.entity) if singularize(cmd.entity) else cmd.entity
|
||||
break
|
||||
else:
|
||||
verb = matching_verbs[0]
|
||||
entity = singularize(cmd.entity) if singularize(cmd.entity) else cmd.entity
|
||||
print "%s => (verb, entity) = (%s, %s)" % (api, verb, post_transform_adjust(entity))
|
||||
return verb, post_transform_adjust(entity)
|
||||
else:
|
||||
print "No matching verb, entity breakdown for api %s" % api
|
||||
|
||||
|
||||
def get_actionable_entities():
|
||||
def get_actionable_entities(path=None):
|
||||
"""
|
||||
Inspect all entities and return a map of the Entity against the actions
|
||||
along with the required arguments to satisfy the action
|
||||
@param path: path where the api modules are found. defaults to pythonpath
|
||||
@return: Dictionary of Entity { "verb" : [required] }
|
||||
"""
|
||||
cmdlets = sorted(filter(lambda api: api.__class__.__name__ not in skip_list(), get_api_cmds()),
|
||||
cmdlets = sorted(filter(lambda api: api.__class__.__name__ not in skip_list(), get_api_cmds(path)),
|
||||
key=lambda k: get_verb_and_entity(k)[1])
|
||||
|
||||
|
||||
entities = {}
|
||||
for cmd in cmdlets:
|
||||
requireds = getattr(cmd, 'required')
|
||||
|
|
@ -184,6 +194,9 @@ def get_actionable_entities():
|
|||
entities[entity][verb]['args'] = requireds
|
||||
entities[entity][verb]['apimodule'] = cmd.__class__.__module__.split('.')[-1]
|
||||
entities[entity][verb]['apicmd'] = api
|
||||
print "Transformed %s APIs to %s entities successfully" % (len(cmdlets), len(entities)) \
|
||||
if len(cmdlets) > 0 \
|
||||
else "No transformations occurred"
|
||||
return entities
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue