Adding new marvincli changes(draft)

This commit is contained in:
Santhosh Edukulla 2014-09-07 20:44:43 +05:30
parent 412791e09f
commit 6c4978c40c
2 changed files with 185 additions and 118 deletions

View File

@ -20,6 +20,7 @@ import os
from optparse import OptionParser from optparse import OptionParser
import cmd import cmd
import random import random
from collections import OrderedDict
from marvin.marvinInit import MarvinInit from marvin.marvinInit import MarvinInit
from marvin.deployDataCenter import DeployDataCenters from marvin.deployDataCenter import DeployDataCenters
from marvin.cloudstackException import GetDetailExceptionInfo from marvin.cloudstackException import GetDetailExceptionInfo
@ -31,73 +32,6 @@ from marvin.codes import (SUCCESS,
from marvin.tcExecuteEngine import TestCaseExecuteEngine from marvin.tcExecuteEngine import TestCaseExecuteEngine
class MarvinCliHelp(object):
@classmethod
def do_printhelp(cls):
print "\n1. for building marvin from spec file and installing."
cls.help_build_and_install()
print "\n2. for syncing apis and installing marvin."
cls.help_sync_and_install()
print "\n3. for deploying a datacenter"
cls.help_deploydc()
print "\n4. for running test cases"
cls.help_runtest()
print "\n5. for deploying a datacenter (and) running tests"
cls.help_deploydc_and_runtest()
print "\n6. for generating apis from spec file"
cls.help_generateapis_from_apispecfile()
print "\n7. for generating apis from end point"
cls.help_generateapis_from_endpoint()
print "\n8. for printing marvincli version"
cls.help_printversion()
@classmethod
def print_msg(cls, msg):
print ShellColor.BOLD + ShellColor.RED + msg + ShellColor.END
@classmethod
def help_printversion(cls):
cls.print_msg("marvincli -v or --version")
@classmethod
def help_deploydc(cls):
cls.print_msg(
"marvincli [deploydc] \n\t[config-file=<marvin-config-file EX: advanced.cfg file>]")
@classmethod
def help_deploydc_and_runtest(cls, deploy=False):
msg = "marvincli [deploydc_and_runtest] \n\t[config-file=<path_to_marvin_cfg> \n\ttc-path=<test suite or test suite folder path>" \
"\n\tzone=<name of the zone> \n\thyp-type=<hypervisor_type> " \
"\n\trequired_hardware=<true\\false>]"
cls.print_msg(msg)
@classmethod
def help_generateapis_from_apispecfile(cls):
cls.print_msg(
"marvincli [generateapis_from_apispecfile] \n\t[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tapi-spec-file=<api spec file EX: /etc/cloud/cli/commands.xml>]")
@classmethod
def help_generateapis_from_endpoint(cls):
cls.print_msg(
"marvincli [generateapis_from_endpoint] \n\t[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tend-point=<CS Endpoint ip EX: localhost>]")
@classmethod
def help_runtest(cls):
cls.print_msg(
"marvincli [runtest] \n\t[config-file=<path_to_marvin_config> \n\ttc-path=test/integration/smoke \n\trequired_hardware=<true\\false> \n\tzone=<name of zone> \n\thyp-type=<xenserver\\kvm\\vmware> etc]")
@classmethod
def help_sync_and_install(cls):
cls.print_msg(
"marvincli [sync_and_install] \n\t[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tend-point=<CS installed host ip EX: localhost>]")
@classmethod
def help_build_and_install(cls):
cls.print_msg(
"marvincli [build_and_install] \n\t[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tapi-sync-file<api spec file generated by cs EX: /etc/cloud/cli/commands.xml>]")
class VerifyAndExit(object): class VerifyAndExit(object):
def __init__(self, msg): def __init__(self, msg):
@ -110,26 +44,113 @@ class VerifyAndExit(object):
if original_func(*args, **kwargs) == FAILED: if original_func(*args, **kwargs) == FAILED:
exit_check = True exit_check = True
except Exception as e: except Exception as e:
print "---", e print "===Exception.Please Check:===", e
exit_check = True exit_check = True
finally: finally:
if exit_check: if exit_check:
print "==== %s ====" % self.msg print "==== %s ====" % self.msg
MarvinCliHelp.do_printhelp() MarvinCliHelp.print_cmds_help()
sys.exit(1) sys.exit(1)
return new_function return new_function
class MarvinCliCommands(object): class MarvinCliCommands(object):
cmds_info = {'deploydc': {'options': ['config-file'], 'help': 'config-file=<marvin-config-file EX: advanced.cfg file>'}, cmds_info = OrderedDict({
'deploydc_and_runtest': {'options': ['config-file', 'tc-path', 'zone', 'hyp-type', 'required_hardware'], 'help': ''}, 'deploydc':
'generateapis_from_endpoint': {'options': '', 'help': '[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tend-point=<CS Endpoint ip EX: localhost>]'}, {
'generateapis_from_apispecfile': {'options': '', 'help': '[cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tapi-spec-file=<api spec file EX: /etc/cloud/cli/commands.xml>]'}, 'summary': 'for deploying a datacenter',
'runtest': {'options': '', 'help': '[config-file=<path_to_marvin_config> \n\ttc-path=test/integration/smoke \n\trequired_hardware=<true\\false> \n\tzone=<name of zone> \n\thyp-type=<xenserver\\kvm\\vmware> etc]'}, 'options': ['*config-file'],
'sync_and_install': {'options': ['sync_and_install'], 'help': '[marvincli sync_and_install cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tend-point=<CS installed host ip EX: localhost>]'}, 'help': 'marvincli deploydc config-file=<marvin-config-file EX: setup/dev/advanced.cfg file>',
'build_and_install': {'options': ['build_and_install'], 'help': '[marvincli build_and_install cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/> \n\tapi-sync-file<api spec file generated by cs EX: /etc/cloud/cli/commands.xml>]'}, 'desc': 'deploys a data center using the config file provided'
'version': {'options': '', 'help': ''} },
} 'deploydc_and_runtest':
{
'summary': 'for deploying a datacenter (and) running tests, either test suite (or) directory of test suites',
'options': ['*config-file', '*tc-path', 'zone', 'hyp-type', 'required_hardware'],
'help': 'marvincli deploydc_and_runtest config-file=<path_to_marvin_cfg EX: setup/dev/advanced.cfg>'
'tc-path=<test suite or test suite folder path EX: test/integration/smoke/>'
'zone=<name of the zone> hyp-type=<hypervisor_type EX: xen,kvm,vmware etc> required_hardware=<true\\false>',
'desc': 'deploys a data center using the config file provided, and runs test cases using the test suite or directory of test suites provided. '
'If zone to run against is not provided, then default zone mentioned in config file is provided '
'If hyp-type information is not provided, first hypervisor from config file is taken. '
'If required_hardware option is not provided, then it is set to false'
},
'generateapis_from_endpoint':
{
'summary': 'for generating apis from cs end point',
'options': ['*cs-folder-path', 'end-point'],
'help': 'marvincli generateapis_from_endpoint cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/>'
'end-point=<CS Endpoint ip EX: localhost>',
'desc': 'generates cloudstackAPI directory with CS apis information from cloudstack endpoint. '
'If end-point information is not provided, localhost is considered as default'
},
'generateapis_from_apispecfile':
{
'summary': 'for generating apis from api spec file',
'options': ['*cs-folder-path', 'api-spec-file'],
'help': 'marvincli generateapis_from_apispecfile cs-folder-path=<cloudstack code root dir EX: /root/cs-4.5/cloudstack/>'
'api-spec-file=<api spec file EX: /etc/cloud/cli/commands.xml>',
'desc': 'generates cloudstackAPI directory with CS apis information from cloudstack api spec file. '
'If spec file information is not provided, /etc/cloud/cli/commands.xml is considered as default'
},
'runtest':
{
'summary': 'for running test cases, either test suite (or) directory of test suites',
'options': ['*config-file', '*tc-path', 'required_hardware', 'zone', 'hyp-type'],
'help': 'marvincli runtest config-file=<path_to_marvin_config> tc-path=test/integration/smoke'
'required_hardware=<true\\false> zone=<name of zone> hyp-type=<xenserver\\kvm\\vmware> etc',
'desc': 'runs marvin integration tests against CS using config file, test suite path or directory of test suites are provided as input for running tests',
},
'sync_and_install':
{
'summary': 'for syncing apis and installing marvin using cs endpoint',
'options': ['*cs-folder-path', 'end-point'],
'help': 'marvincli sync_and_install cs-folder-path = <cloudstack code root dir EX: /root/cs-4.5/cloudstack/>'
'end-point = <CS installed host ip EX: localhost>',
'desc': 'generates cloudstackAPI directory with CS apis information from cloudstack end-point (and) installs new marvin.'
'If end-point information is not provided, localhost is considered as default'
},
'build_and_install':
{
'summary': 'for building and installing marvin using spec file',
'options': ['*cs-folder-path', 'api-sync-file'],
'help': 'marvincli build_and_install cs-folder-path = <cloudstack code root dir EX: /root/cs-4.5/cloudstack/>'
'api-sync-file = <api spec file generated by cs EX: /etc/cloud/cli/commands.xml>',
'desc': 'generates cloudstackAPI directory with CS apis information from cloudstack api-spec-file (and) installs new marvin.'
'If api spec file information is not provided, /etc/cloud/cli/commands.xml is considered as default'
},
'version':
{
'summary': 'for printing marvincli version',
'options': ['-v (or) --version'],
'help': 'marvincli -v (or) marvincli --version',
'desc': 'prints the version of marvincli'
}
})
class MarvinCliHelp(object):
@classmethod
def print_cmds_help(cls):
msg = ''
for cmd_name, cmd_txt in MarvinCliCommands.cmds_info.items():
msg = msg + \
'\n----------------------------------------------------\n'
cmd_info = ShellColor.BOLD + ShellColor.RED + \
'cmd_name:%s' % str(cmd_name) + ShellColor.END
for key, value in cmd_txt.iteritems():
cmd_info = cmd_info + '\n' + \
str(key) + ' : ' + str(value).strip('\n')
msg = msg + cmd_info
# return ShellColor.BOLD + ShellColor.RED + msg + ShellColor.END
return msg
@classmethod
def print_msg(cls, msg):
if msg:
return ShellColor.BOLD + ShellColor.RED + msg + ShellColor.END
class ShellColor(object): class ShellColor(object):
@ -163,7 +184,8 @@ class MarvinCli(cmd.Cmd, object):
self.__csFolder = "." self.__csFolder = "."
cmd.Cmd.__init__(self) cmd.Cmd.__init__(self)
@VerifyAndExit("Invalid input options, please check") @VerifyAndExit(
"cmd failed, may be invalid input options, please check help")
def parse_input_deploy(self, inputs=None): def parse_input_deploy(self, inputs=None):
''' '''
Parses,reads the options and verifies for the config file Parses,reads the options and verifies for the config file
@ -181,7 +203,8 @@ class MarvinCli(cmd.Cmd, object):
return SUCCESS return SUCCESS
return FAILED return FAILED
@VerifyAndExit("Invalid input options, please check") @VerifyAndExit(
"cmd failed, may be invalid input options, please check help")
def parse_input_runtcs(self, inputs): def parse_input_runtcs(self, inputs):
''' '''
Parses,reads the options and verifies for the config file Parses,reads the options and verifies for the config file
@ -193,7 +216,6 @@ class MarvinCli(cmd.Cmd, object):
(key, value) = item.split('=') (key, value) = item.split('=')
out_dict[key] = value out_dict[key] = value
self.__configFile = out_dict.get('config-file', None) self.__configFile = out_dict.get('config-file', None)
self.__deployFlag = out_dict.get('deploy', False)
self.__zone = out_dict.get("zone", None) self.__zone = out_dict.get("zone", None)
self.__hypervisorType = out_dict.get("hyp-type", None) self.__hypervisorType = out_dict.get("hyp-type", None)
self.__tcPath = out_dict.get("tc-path",) self.__tcPath = out_dict.get("tc-path",)
@ -225,13 +247,13 @@ class MarvinCli(cmd.Cmd, object):
return FAILED return FAILED
except Exception as e: except Exception as e:
print "====Exception Occurred under start_marvin: %s ====" % \ print "====Exception Occurred under start_marvin: %s ====" % \
GetDetailExceptionInfo(e) GetDetailExceptionInfo(e)
return FAILED return FAILED
def run_test_suites(self): def run_test_suites(self):
print "\n==== Started Running Test Cases ====" print "\n==== Started Running Test Cases ===="
xunit_out_path = "/tmp/marvin_xunit_out" + \ xunit_out_path = "/tmp/marvin_xunit_out" + \
str(random.randrange(1, 10000)) + ".xml" str(random.randrange(1, 10000)) + ".xml"
marvin_tc_run_cmd = "nosetests-2.7 -s --with-marvin --marvin-config=%s --with-xunit --xunit-file=%s %s -a tags=advanced, required_hardware=%s --zone=%s --hypervisor=%s" marvin_tc_run_cmd = "nosetests-2.7 -s --with-marvin --marvin-config=%s --with-xunit --xunit-file=%s %s -a tags=advanced, required_hardware=%s --zone=%s --hypervisor=%s"
if os.path.isfile(self.__tcPath): if os.path.isfile(self.__tcPath):
marvin_tc_run_cmd = marvin_tc_run_cmd % (self.__configFile, marvin_tc_run_cmd = marvin_tc_run_cmd % (self.__configFile,
@ -252,16 +274,32 @@ class MarvinCli(cmd.Cmd, object):
''' '''
print "\n==== Running Test Cases Successful ====" print "\n==== Running Test Cases Successful ===="
def do_deploy(self, args): @VerifyAndExit(
self.__deployFlag = True "cmd failed, may be invalid input options, please check help")
self.parse_input_deploy(inputs=args) def do_deploydc(self, args):
self.start_marvin() try:
self.__deployFlag = True
self.parse_input_deploy(inputs=args)
self.start_marvin()
return SUCCESS
except Exception as e:
print "==== deploy cmd failed :%s ==== " % str(e)
return FAILED
@VerifyAndExit(
"cmd failed, may be invalid input options, please check help")
def do_deploydc_and_runtest(self, args): def do_deploydc_and_runtest(self, args):
self.do_deploy(inputs=args) try:
self.parse_input_runtcs() self.do_deploy(inputs=args)
self.run_test_suites() self.parse_input_runtcs()
self.run_test_suites()
return SUCCESS
except Exception as e:
print "==== deploydc cmd failed:%s ==== " % str(e)
return FAILED
@VerifyAndExit(
"cmd failed, may be invalid input options, please check help")
def do_generateapis_from_apispecfile(self, args): def do_generateapis_from_apispecfile(self, args):
api_spec_file = "/etc/cloud/cli/commands.xml" api_spec_file = "/etc/cloud/cli/commands.xml"
cs_api_folder = "." cs_api_folder = "."
@ -281,11 +319,11 @@ class MarvinCli(cmd.Cmd, object):
if api_spec_file: if api_spec_file:
try: try:
cg.generateCodeFromXML(api_spec_file) cg.generateCodeFromXML(api_spec_file)
return return SUCCESS
except Exception as e: except Exception as e:
print "==== Generating apis from api spec file failed: %s ====" % str(e.message()) print "==== Generating apis from api spec file failed: %s ====" % str(e.message())
sys.exit(1) return FAILED
sys.exit(1) return FAILED
def create_marvin_api_folder(self, cs_folder_path='.'): def create_marvin_api_folder(self, cs_folder_path='.'):
cs_api_folder = cs_folder_path + "/tools/marvin/marvin/cloudstackAPI" cs_api_folder = cs_folder_path + "/tools/marvin/marvin/cloudstackAPI"
@ -295,6 +333,8 @@ class MarvinCli(cmd.Cmd, object):
os.makedirs(cs_api_folder) os.makedirs(cs_api_folder)
return cs_api_folder return cs_api_folder
@VerifyAndExit(
"cmd failed, may be invalid input options, please check help")
def do_generateapis_from_endpoint(self, args): def do_generateapis_from_endpoint(self, args):
endpoint_url = 'http://%s:8096/client/api?command=listApis&\ endpoint_url = 'http://%s:8096/client/api?command=listApis&\
response=json' response=json'
@ -312,36 +352,54 @@ response=json'
try: try:
endpoint_url = endpoint_url % str(cs_end_point) endpoint_url = endpoint_url % str(cs_end_point)
cg.generateCodeFromJSON(endpoint_url) cg.generateCodeFromJSON(endpoint_url)
return return SUCCESS
except Exception as e: except Exception as e:
print "==== Generating apis from end point failed: %s ====" % str(e.message()) print "==== Generating apis from end point failed: %s ====" % str(e.message())
sys.exit(1) return FAILED
sys.exit(1) return FAILED
@VerifyAndExit(
"cmd failed, may be invalid input options, please check help")
def do_runtest(self, args): def do_runtest(self, args):
self.parse_input_runtcs(args) try:
self.start_marvin() self.parse_input_runtcs(args)
self.run_test_suites() self.start_marvin()
self.run_test_suites()
return SUCCESS
except Exception as e:
print "==== run test failed: %s ====" % str(e.message())
return FAILED
def install_marvin(self): def install_marvin(self):
if self.__csFolder: if self.__csFolder:
marvin_setup_file_path = self.__csFolder + "/tools/marvin/setup.py" marvin_setup_file_path = self.__csFolder + "/tools/marvin/setup.py"
# step2: Build and install the Marvin
try: try:
os.system("python %s install" % str(marvin_setup_file_path)) os.system("python %s install" % str(marvin_setup_file_path))
print "==== Marvin Installed Successfully ===="
except Exception as e: except Exception as e:
print "==== Marvin Installation Failed ====" print "==== Marvin Installation Failed ===="
print "==== Marvin Installed Successfully ===="
@VerifyAndExit(
"cmd failed, may be invalid input options, please check help")
def do_build_and_install(self, args): def do_build_and_install(self, args):
# step1: Generate the apis from spec file first try:
self.do_generateapis_from_apispecfile(args) self.do_generateapis_from_apispecfile(args)
self.install_marvin() self.install_marvin()
return SUCCESS
except Exception as e:
print "==== build from end point and install marvin failed: %s ====" % str(e)
return FAILED
@VerifyAndExit(
"cmd failed, may be invalid input options, please check help")
def do_sync_and_install(self, args): def do_sync_and_install(self, args):
# step1: Generate the apis from spec file first try:
self.do_generateapis_from_endpoint(args) self.do_generateapis_from_endpoint(args)
self.install_marvin() self.install_marvin()
return SUCCESS
except Exception as e:
print "==== sync from spec file and install marvin failed: %s ====" % str(e)
return FAILED
class MarvinCliParser(OptionParser): class MarvinCliParser(OptionParser):
@ -349,9 +407,14 @@ class MarvinCliParser(OptionParser):
def format_help(self, formatter=None): def format_help(self, formatter=None):
if formatter is None: if formatter is None:
formatter = self.formatter formatter = self.formatter
print MarvinCliHelp.print_msg("Usage: marvincli [cmd] [options].See, the below cmds for more information \n\n") result = []
print MarvinCliHelp.do_printhelp() if self.usage:
return "\n===========================================================================\n" result.append(MarvinCliHelp.print_msg("\nUsage: marvincli [cmd] [options]. See, the below cmds for more information."
"(*) signifies mandatory fields \n\n"))
self.description = MarvinCliHelp.print_cmds_help()
if self.description:
result.append(self.format_description(formatter) + "\n")
return "".join(result)
def main(): def main():
@ -364,12 +427,14 @@ def main():
MarvinCliHelp.help_printversion() MarvinCliHelp.help_printversion()
sys.exit(0) sys.exit(0)
if len(sys.argv) > 1: if len(sys.argv) > 1:
if sys.argv[1].lower() in ["deploydc", "deploydc_and_runtest", "generateapis_from_endpoint", if sys.argv[1].lower() not in MarvinCliCommands.cmds_info.keys():
"generateapis_from_apispecfile", "runtest", "sync_and_install", "build_and_install"]:
MarvinCli().onecmd(' '.join(args))
else:
print "\n==== Invalid Command ====" print "\n==== Invalid Command ===="
sys.exit(1) sys.exit(1)
args = ' '.join(args)
if '-h' in args or '--help' in args:
print MarvinCliCommands.cmds_info[sys.argv[0]]
else:
MarvinCli().onecmd(args)
sys.exit(0) sys.exit(0)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -111,10 +111,12 @@ class MarvinInit:
if not self.__hypervisorType: if not self.__hypervisorType:
if self.__parsedConfig and self.__parsedConfig.zones is not None: if self.__parsedConfig and self.__parsedConfig.zones is not None:
for zone in self.__parsedConfig.zones: for zone in self.__parsedConfig.zones:
for pod in zone.pods and pod is not None: for pod in zone.pods:
for cluster in pod.clusters and cluster is not None: if pod is not None:
self.__hypervisorType = cluster.hypervisor for cluster in pod.clusters:
break if cluster is not None and cluster.hypervisor is not None:
self.__hypervisorType = cluster.hypervisor
break
if not self.__zoneForTests: if not self.__zoneForTests:
if self.__parsedConfig and self.__parsedConfig.zones is not None: if self.__parsedConfig and self.__parsedConfig.zones is not None:
for zone in self.__parsedConfig.zones: for zone in self.__parsedConfig.zones: