class MarvinPlugin(Plugin): """ Custom plugin for the cloudstackTestCases to be run using nose """ name = "marvin" def __init__(self): self.__identifier = None self.__testClient = None self.__logFolderPath = None self.__parsedConfig = None ''' Contains Config File ''' self.__configFile = None ''' Signifies the Zone against which all tests will be Run ''' self.__zoneForTests = None ''' Signifies the flag whether to deploy the New DC or Not ''' self.__deployDcFlag = None self.conf = None self.__resultStream = stdout self.__testRunner = None self.__testResult = SUCCESS self.__startTime = None self.__testName = None self.__tcRunLogger = MarvinLog('marvin').getLogger() self.__testModName = '' self.__hypervisorType = None Plugin.__init__(self) def configure(self, options, conf): """enable the marvin plugin when the --with-marvin directive is given to nose. The enableOpt value is set from the command line directive and self.enabled (True|False) determines whether marvin's tests will run. By default non-default plugins like marvin will be disabled """ self.enabled = True if hasattr(options, self.enableOpt): if not getattr(options, self.enableOpt): self.enabled = False return self.__configFile = options.configFile self.__deployDcFlag = options.deployDc self.__zoneForTests = options.zone self.__hypervisorType = options.hypervisor_type self.conf = conf if self.startMarvin() == FAILED: self.__tcRunLogger.error( 'Starting Marvin Failed, exiting. Please Check') exit(1) def options(self, parser, env): """ Register command line options """ parser.add_option("--marvin-config", action="store", default=env.get('MARVIN_CONFIG', './datacenter.cfg'), dest="configFile", help="Marvin's configuration file is required." "The config file containing the datacenter and " "other management server " "information is specified") parser.add_option("--deploy", action="store_true", default=False, dest="deployDc", help="Deploys the DC with Given Configuration." "Requires only when DC needs to be deployed") parser.add_option("--zone", action="store", default=None, dest="zone", help="Runs all tests against this specified zone") parser.add_option("--hypervisor", action="store", default=None, dest="hypervisor_type", help="Runs all tests against the specified " "zone and hypervisor Type") parser.add_option("--log-folder-path", action="store", default=None, dest="logFolder", help="Collects all logs under the user specified" "folder") Plugin.options(self, parser, env) def wantClass(self, cls): if cls.__name__ == 'cloudstackTestCase': return False if issubclass(cls, cloudstackTestCase): return True return None def __checkImport(self, filename): ''' @Name : __checkImport @Desc : Verifies if a test module is importable. Returns False or True based upon the result. ''' try: if os.path.isfile(filename): ret = os.path.splitext(filename) if ret[1] == ".py": os.system("python " + filename) return True return False except ImportError as e: self.__tcRunLogger.exception("File %s has import errors: %s" % (filename, e)) return False def wantFile(self, filename): ''' @Desc : Only python files will be used as test modules ''' return self.__checkImport(filename) def loadTestsFromTestCase(self, cls): if cls.__name__ != 'cloudstackTestCase': self.__identifier = cls.__name__ self._injectClients(cls) def beforeTest(self, test): self.__testModName = test.__str__() self.__testName = test.__str__().split()[0] if not self.__testName: self.__testName = "test" self.__testClient.identifier = '-'. \ join([self.__identifier, self.__testName]) if self.__tcRunLogger: self.__tcRunLogger.name = test.__str__() def startTest(self, test): """ Currently used to record start time for tests Dump Start Msg of TestCase to Log """ self.__tcRunLogger.info("=== Started Test %s ===" % str(self.__testName)) self.__startTime = time.time() def printMsg(self, status, tname, err): if status in [FAILED, EXCEPTION] and self.__tcRunLogger: self.__tcRunLogger.fatal("%s: %s: %s" % (status, tname, err)) write_str = "=== TestName: %s | Status : %s ===" % (tname, status) self.__resultStream.write(write_str) self.__tcRunLogger.info(write_str) def addSuccess(self, test, capt): ''' Adds the Success Messages to logs ''' self.printMsg(SUCCESS, self.__testName, "Test Case Passed") self.__testResult = SUCCESS def handleError(self, test, err): ''' Adds Exception throwing test cases and information to log. ''' self.printMsg(EXCEPTION, self.__testName, err) self.__testResult = EXCEPTION def prepareTestRunner(self, runner): if self.__testRunner: return self.__testRunner def handleFailure(self, test, err): ''' Adds Failing test cases and information to log. ''' self.printMsg(FAILED, self.__testName, err) self.__testResult = FAILED def startMarvin(self): ''' @Name : startMarvin @Desc : Initializes the Marvin creates the test Client creates the runlogger for logging Parses the config and creates a parsedconfig Creates a debugstream for tc debug log ''' try: obj_marvininit = MarvinInit(self.__configFile, self.__deployDcFlag, None, self.__zoneForTests, self.__hypervisorType) if obj_marvininit and obj_marvininit.init() == SUCCESS: self.__testClient = obj_marvininit.getTestClient() self.__parsedConfig = obj_marvininit.getParsedConfig() self.__resultStream = obj_marvininit.getResultFile() self.__testRunner = nose.core.TextTestRunner( stream=self.__resultStream, descriptions=True, verbosity=2, config=self.conf) return SUCCESS return FAILED except Exception as e: self.__tcRunLogger.exception( ("=== Start Marvin failed: %s ===" % e)) return FAILED def stopTest(self, test): """ Currently used to record end time for tests """ endTime = time.time() if self.__startTime: totTime = int(endTime - self.__startTime) self.__tcRunLogger.info( "TestCaseName: %s; Time Taken: %s Seconds; StartTime: %s; EndTime: %s; Result: %s" % (self.__testName, str(totTime), str(time.ctime(self.__startTime)), str( time.ctime(endTime)), self.__testResult)) def _injectClients(self, test): setattr(test, "debug", self.__tcRunLogger.debug) setattr(test, "info", self.__tcRunLogger.info) setattr(test, "warn", self.__tcRunLogger.warning) setattr(test, "error", self.__tcRunLogger.error) setattr(test, "testClient", self.__testClient) setattr(test, "config", self.__parsedConfig) if self.__testClient.identifier is None: self.__testClient.identifier = self.__identifier setattr(test, "clstestclient", self.__testClient) if hasattr(test, "user"): # when the class-level attr applied. all test runs as 'user' self.__testClient.getUserApiClient(test.UserName, test.DomainName, test.AcctType) def finalize(self, result): self.__tcRunLogger.info('=== finalize does nothing! ===')
class MarvinInit: def __init__(self, config_file, deploy_dc_flag=False, test_mod_name="deploydc", zone=None, hypervisor_type=None): self.__configFile = config_file self.__deployFlag = deploy_dc_flag self.__tcRunLogger = MarvinLog('marvin').getLogger() self.__tcRunLogger.info("=== Marvin Init Logging Successful ===") self.__testModName = test_mod_name self.__testClient = None self.__tcResultFile = None self.__testDataFilePath = None self.__zoneForTests = zone self.__parsedConfig = None self.__hypervisorType = hypervisor_type def __parseConfig(self): ''' @Name: __parseConfig @Desc : Parses the configuration file passed and assigns the parsed configuration @Output : SUCCESS or FAILED ''' try: if not os.path.isfile(self.__configFile): self.__tcRunLogger.error("=== Marvin Parse Config Init Failed ===") return FAILED self.__parsedConfig = getSetupConfig(self.__configFile) self.__tcRunLogger.info("=== Marvin Parse Config Successful ===") return SUCCESS except Exception as e: self.__tcRunLogger.exception("=== Marvin Parse Config Init Failed: %s ===" % e) return FAILED def getParsedConfig(self): return self.__parsedConfig def getLogFolderPath(self): return self.__logFolderPath def getTestClient(self): return self.__testClient def getLogger(self): return self.__tcRunLogger def getResultFile(self): ''' @Name : getDebugFile @Desc : Creates the result file at a given path. @Output : Returns the Result file to be used for writing test outputs ''' self.__tcResultFile = open("results.txt", "w") return self.__tcResultFile def __setHypervisorAndZoneInfo(self): ''' @Name : __setHypervisorAndZoneInfo @Desc: Set the HyperVisor and Zone details; default to XenServer ''' try: if not self.__hypervisorType: if self.__parsedConfig and self.__parsedConfig.zones is not None: for zone in self.__parsedConfig.zones: for pod in zone.pods: if pod is not None: for cluster in pod.clusters: if cluster is not None and cluster.hypervisor is not None: self.__hypervisorType = cluster.hypervisor break if not self.__zoneForTests: if self.__parsedConfig and self.__parsedConfig.zones is not None: for zone in self.__parsedConfig.zones: self.__zoneForTests = zone.name break if not self.__hypervisorType: self.__hypervisorType = XEN_SERVER return SUCCESS except Exception as e: self.__tcRunLogger.exception("=== Set Hypervizor and Zone info Failed: %s ===" % e) return FAILED def init(self): ''' @Name : init @Desc :Initializes the marvin by 1. Parsing the configuration and creating a parsed config structure 2. Creates a timestamped log folder and provides all logs to be dumped there 3. Creates the DataCenter based upon configuration provided @Output : SUCCESS or FAILED ''' try: self.__tcRunLogger.info("=== Marvin Init Started ===") if ((self.__parseConfig() != FAILED) and (self.__setHypervisorAndZoneInfo()) and (self.__setTestDataPath() != FAILED) and (self.__createTestClient() != FAILED) and (self.__deployDC() != FAILED)): self.__tcRunLogger.info("=== Marvin Init Successful ===") return SUCCESS self.__tcRunLogger.error("=== Marvin Init Failed ===") return FAILED except Exception as e: self.__tcRunLogger.exception("=== Marvin Init Failed with exception: %s ===" % e) return FAILED def __createTestClient(self): ''' @Name : __createTestClient @Desc : Creates the TestClient during init based upon the parameters provided @Output: Returns SUCCESS or FAILED ''' try: mgt_details = self.__parsedConfig.mgtSvr[0] dbsvr_details = self.__parsedConfig.dbSvr self.__testClient = CSTestClient( mgt_details, dbsvr_details, test_data_filepath=self.__testDataFilePath, zone=self.__zoneForTests, hypervisor_type=self.__hypervisorType) if self.__testClient: return self.__testClient.createTestClient() return FAILED except Exception as e: self.__tcRunLogger.exception("=== Marvin Create Test Client Failed: %s ===" % e) return FAILED def __setTestDataPath(self): ''' @Name : __setTestDataPath @Desc : Sets the TestData Path for tests to run @Output:Returns SUCCESS or FAILED ''' try: if ((self.__parsedConfig.TestData is not None) and (self.__parsedConfig.TestData.Path is not None)): self.__testDataFilePath = self.__parsedConfig.TestData.Path self.__tcRunLogger.info("=== Marvin Setting TestData Successful ===") return SUCCESS except Exception as e: self.__tcRunLogger.exception("=== Marvin Setting TestData Successful Failed: %s ===" % e) return FAILED def __deployDC(self): ''' @Name : __deployDC @Desc : Deploy the DataCenter and returns accordingly. @Output: SUCCESS or FAILED ''' try: ret = SUCCESS if self.__deployFlag: deploy_obj = DeployDataCenters(self.__testClient, self.__parsedConfig, self.__tcRunLogger) ret = deploy_obj.deploy() if ret != SUCCESS: self.__tcRunLogger.error("=== Deploy DC Failed ===") return ret except Exception as e: self.__tcRunLogger.exception("=== Deploy DC Failed with exception: %s ===" % e) return FAILED
class MarvinPlugin(Plugin): """ Custom plugin for the cloudstackTestCases to be run using nose """ name = "marvin" def __init__(self): self.__identifier = None self.__testClient = None self.__logFolderPath = None self.__parsedConfig = None ''' Contains Config File ''' self.__configFile = None ''' Signifies the Zone against which all tests will be Run ''' self.__zoneForTests = None ''' Signifies the flag whether to deploy the New DC or Not ''' self.__deployDcFlag = None self.conf = None self.__resultStream = stdout self.__testRunner = None self.__testResult = SUCCESS self.__startTime = None self.__testName = None self.__tcRunLogger = MarvinLog('marvin').getLogger() self.__testModName = '' self.__hypervisorType = None Plugin.__init__(self) def configure(self, options, conf): """enable the marvin plugin when the --with-marvin directive is given to nose. The enableOpt value is set from the command line directive and self.enabled (True|False) determines whether marvin's tests will run. By default non-default plugins like marvin will be disabled """ self.enabled = True if hasattr(options, self.enableOpt): if not getattr(options, self.enableOpt): self.enabled = False return self.__configFile = options.configFile self.__deployDcFlag = options.deployDc self.__zoneForTests = options.zone self.__hypervisorType = options.hypervisor_type self.conf = conf if self.startMarvin() == FAILED: self.__tcRunLogger.error('Starting Marvin Failed, exiting. Please Check') exit(1) def options(self, parser, env): """ Register command line options """ parser.add_option("--marvin-config", action="store", default=env.get('MARVIN_CONFIG', './datacenter.cfg'), dest="configFile", help="Marvin's configuration file is required." "The config file containing the datacenter and " "other management server " "information is specified") parser.add_option("--deploy", action="store_true", default=False, dest="deployDc", help="Deploys the DC with Given Configuration." "Requires only when DC needs to be deployed") parser.add_option("--zone", action="store", default=None, dest="zone", help="Runs all tests against this specified zone") parser.add_option("--hypervisor", action="store", default=None, dest="hypervisor_type", help="Runs all tests against the specified " "zone and hypervisor Type") parser.add_option("--log-folder-path", action="store", default=None, dest="logFolder", help="Collects all logs under the user specified" "folder" ) Plugin.options(self, parser, env) def wantClass(self, cls): if cls.__name__ == 'cloudstackTestCase': return False if issubclass(cls, cloudstackTestCase): return True return None def __checkImport(self, filename): ''' @Name : __checkImport @Desc : Verifies if a test module is importable. Returns False or True based upon the result. ''' try: if os.path.isfile(filename): ret = os.path.splitext(filename) if ret[1] == ".py": os.system("python " + filename) return True return False except ImportError as e: self.__tcRunLogger.exception("File %s has import errors: %s" % (filename, e)) return False def wantFile(self, filename): ''' @Desc : Only python files will be used as test modules ''' return self.__checkImport(filename) def loadTestsFromTestCase(self, cls): if cls.__name__ != 'cloudstackTestCase': self.__identifier = cls.__name__ self._injectClients(cls) def beforeTest(self, test): self.__testModName = test.__str__() self.__testName = test.__str__().split()[0] if not self.__testName: self.__testName = "test" self.__testClient.identifier = '-'. \ join([self.__identifier, self.__testName]) if self.__tcRunLogger: self.__tcRunLogger.name = test.__str__() def startTest(self, test): """ Currently used to record start time for tests Dump Start Msg of TestCase to Log """ self.__tcRunLogger.info("=== Started Test %s ===" % str(self.__testName)) self.__startTime = time.time() def printMsg(self, status, tname, err): if status in [FAILED, EXCEPTION] and self.__tcRunLogger: self.__tcRunLogger.fatal("%s: %s: %s" % (status, tname, err)) write_str = "=== TestName: %s | Status : %s ===" % (tname, status) self.__resultStream.write(write_str) self.__tcRunLogger.info(write_str) def addSuccess(self, test, capt): ''' Adds the Success Messages to logs ''' self.printMsg(SUCCESS, self.__testName, "Test Case Passed") self.__testResult = SUCCESS def handleError(self, test, err): ''' Adds Exception throwing test cases and information to log. ''' self.printMsg(EXCEPTION, self.__testName, err) self.__testResult = EXCEPTION def prepareTestRunner(self, runner): if self.__testRunner: return self.__testRunner def handleFailure(self, test, err): ''' Adds Failing test cases and information to log. ''' self.printMsg(FAILED, self.__testName, err) self.__testResult = FAILED def startMarvin(self): ''' @Name : startMarvin @Desc : Initializes the Marvin creates the test Client creates the runlogger for logging Parses the config and creates a parsedconfig Creates a debugstream for tc debug log ''' try: obj_marvininit = MarvinInit(self.__configFile, self.__deployDcFlag, None, self.__zoneForTests, self.__hypervisorType) if obj_marvininit and obj_marvininit.init() == SUCCESS: self.__testClient = obj_marvininit.getTestClient() self.__parsedConfig = obj_marvininit.getParsedConfig() self.__resultStream = obj_marvininit.getResultFile() self.__testRunner = nose.core.TextTestRunner( stream=self.__resultStream, descriptions=True, verbosity=2, config=self.conf ) return SUCCESS return FAILED except Exception as e: self.__tcRunLogger.exception(("=== Start Marvin failed: %s ===" % e)) return FAILED def stopTest(self, test): """ Currently used to record end time for tests """ endTime = time.time() if self.__startTime: totTime = int(endTime - self.__startTime) self.__tcRunLogger.info( "TestCaseName: %s; Time Taken: %s Seconds; StartTime: %s; EndTime: %s; Result: %s" % ( self.__testName, str(totTime), str(time.ctime(self.__startTime)), str(time.ctime(endTime)), self.__testResult ) ) def _injectClients(self, test): setattr(test, "debug", self.__tcRunLogger.debug) setattr(test, "info", self.__tcRunLogger.info) setattr(test, "warn", self.__tcRunLogger.warning) setattr(test, "error", self.__tcRunLogger.error) setattr(test, "testClient", self.__testClient) setattr(test, "config", self.__parsedConfig) if self.__testClient.identifier is None: self.__testClient.identifier = self.__identifier setattr(test, "clstestclient", self.__testClient) if hasattr(test, "user"): # when the class-level attr applied. all test runs as 'user' self.__testClient.getUserApiClient(test.UserName, test.DomainName, test.AcctType) def finalize(self, result): self.__tcRunLogger.info('=== finalize does nothing! ===')
class MarvinInit: def __init__(self, config_file, deploy_dc_flag=False, test_mod_name="deploydc", zone=None, hypervisor_type=None): self.__configFile = config_file self.__deployFlag = deploy_dc_flag self.__tcRunLogger = MarvinLog('marvin').getLogger() self.__tcRunLogger.info("=== Marvin Init Logging Successful ===") self.__testModName = test_mod_name self.__testClient = None self.__tcResultFile = None self.__testDataFilePath = None self.__zoneForTests = zone self.__parsedConfig = None self.__hypervisorType = hypervisor_type def __parseConfig(self): ''' @Name: __parseConfig @Desc : Parses the configuration file passed and assigns the parsed configuration @Output : SUCCESS or FAILED ''' try: if not os.path.isfile(self.__configFile): self.__tcRunLogger.error( "=== Marvin Parse Config Init Failed ===") return FAILED self.__parsedConfig = getSetupConfig(self.__configFile) self.__tcRunLogger.info("=== Marvin Parse Config Successful ===") return SUCCESS except Exception as e: self.__tcRunLogger.exception( "=== Marvin Parse Config Init Failed: %s ===" % e) return FAILED def getParsedConfig(self): return self.__parsedConfig def getLogFolderPath(self): return self.__logFolderPath def getTestClient(self): return self.__testClient def getLogger(self): return self.__tcRunLogger def getResultFile(self): ''' @Name : getDebugFile @Desc : Creates the result file at a given path. @Output : Returns the Result file to be used for writing test outputs ''' self.__tcResultFile = open("results.txt", "w") return self.__tcResultFile def __setHypervisorAndZoneInfo(self): ''' @Name : __setHypervisorAndZoneInfo @Desc: Set the HyperVisor and Zone details; default to XenServer ''' try: if not self.__hypervisorType: if self.__parsedConfig and self.__parsedConfig.zones is not None: for zone in self.__parsedConfig.zones: for pod in zone.pods: if pod is not None: for cluster in pod.clusters: if cluster is not None and cluster.hypervisor is not None: self.__hypervisorType = cluster.hypervisor break if not self.__zoneForTests: if self.__parsedConfig and self.__parsedConfig.zones is not None: for zone in self.__parsedConfig.zones: self.__zoneForTests = zone.name break if not self.__hypervisorType: self.__hypervisorType = XEN_SERVER return SUCCESS except Exception as e: self.__tcRunLogger.exception( "=== Set Hypervizor and Zone info Failed: %s ===" % e) return FAILED def init(self): ''' @Name : init @Desc :Initializes the marvin by 1. Parsing the configuration and creating a parsed config structure 2. Creates a timestamped log folder and provides all logs to be dumped there 3. Creates the DataCenter based upon configuration provided @Output : SUCCESS or FAILED ''' try: self.__tcRunLogger.info("=== Marvin Init Started ===") if ((self.__parseConfig() != FAILED) and (self.__setHypervisorAndZoneInfo()) and (self.__setTestDataPath() != FAILED) and (self.__createTestClient() != FAILED) and (self.__deployDC() != FAILED)): self.__tcRunLogger.info("=== Marvin Init Successful ===") return SUCCESS self.__tcRunLogger.error("=== Marvin Init Failed ===") return FAILED except Exception as e: self.__tcRunLogger.exception( "=== Marvin Init Failed with exception: %s ===" % e) return FAILED def __createTestClient(self): ''' @Name : __createTestClient @Desc : Creates the TestClient during init based upon the parameters provided @Output: Returns SUCCESS or FAILED ''' try: mgt_details = self.__parsedConfig.mgtSvr[0] dbsvr_details = self.__parsedConfig.dbSvr self.__testClient = CSTestClient( mgt_details, dbsvr_details, test_data_filepath=self.__testDataFilePath, zone=self.__zoneForTests, hypervisor_type=self.__hypervisorType) if self.__testClient: return self.__testClient.createTestClient() return FAILED except Exception as e: self.__tcRunLogger.exception( "=== Marvin Create Test Client Failed: %s ===" % e) return FAILED def __setTestDataPath(self): ''' @Name : __setTestDataPath @Desc : Sets the TestData Path for tests to run @Output:Returns SUCCESS or FAILED ''' try: if ((self.__parsedConfig.TestData is not None) and (self.__parsedConfig.TestData.Path is not None)): self.__testDataFilePath = self.__parsedConfig.TestData.Path self.__tcRunLogger.info( "=== Marvin Setting TestData Successful ===") return SUCCESS except Exception as e: self.__tcRunLogger.exception( "=== Marvin Setting TestData Successful Failed: %s ===" % e) return FAILED def __deployDC(self): ''' @Name : __deployDC @Desc : Deploy the DataCenter and returns accordingly. @Output: SUCCESS or FAILED ''' try: ret = SUCCESS if self.__deployFlag: deploy_obj = DeployDataCenters(self.__testClient, self.__parsedConfig, self.__tcRunLogger) ret = deploy_obj.deploy() if ret != SUCCESS: self.__tcRunLogger.error("=== Deploy DC Failed ===") return ret except Exception as e: self.__tcRunLogger.exception( "=== Deploy DC Failed with exception: %s ===" % e) return FAILED