You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by gi...@apache.org on 2013/12/07 09:09:37 UTC

git commit: updated refs/heads/4.2 to 1190abd

Updated Branches:
  refs/heads/4.2 9dfba1900 -> 1190abd4c


Enhanced few features under Marvin

Added few enhancements to marvin.
Added new module for Logging Facility to marvin.
Added new Init facility to marvin.
Currently, there are multiple ways we are doing logging
Removed few unwanted logging cases.
Removed few command line switch options for logging.
The new way of logging now provides consolidated logging
under one single folder timestamped under the configured
folder path.
Removed parsing configuration from deploydata center
Added parsing,start logging and deploy as part of init
Added new error handling facility to catch unknown exception from
test cases. Currently, lot of scripts are throwing unknown
exceptions, add a handler to plugin to dump them to a file

ToDO:
Will do clean up in phase2 for this patch.
Separate deployDatacenter from creating test client.
Clean up configGenerator

Conflicts:
	tools/marvin/marvin/deployDataCenter.py
	tools/marvin/marvin/marvinPlugin.py


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/1190abd4
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/1190abd4
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/1190abd4

Branch: refs/heads/4.2
Commit: 1190abd4ca0e575c32da5366d557858c6bd73fcf
Parents: 9dfba19
Author: Santhosh Edukulla <Sa...@citrix.com>
Authored: Fri Dec 6 12:01:53 2013 +0530
Committer: Girish Shilamkar <gs...@ddn.com>
Committed: Sat Dec 7 13:38:45 2013 +0530

----------------------------------------------------------------------
 setup/dev/advanced.cfg                      |  10 +-
 tools/marvin/marvin/cloudstackConnection.py |  53 +++----
 tools/marvin/marvin/codes.py                |   5 +
 tools/marvin/marvin/configGenerator.py      |  48 -------
 tools/marvin/marvin/deployDataCenter.py     |  57 ++------
 tools/marvin/marvin/marvinInit.py           | 159 +++++++++++++++++++++
 tools/marvin/marvin/marvinLog.py            |  72 ++++++++++
 tools/marvin/marvin/marvinPlugin.py         | 174 ++++++++++++++---------
 8 files changed, 374 insertions(+), 204 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1190abd4/setup/dev/advanced.cfg
----------------------------------------------------------------------
diff --git a/setup/dev/advanced.cfg b/setup/dev/advanced.cfg
index dfaba00..aee5985 100644
--- a/setup/dev/advanced.cfg
+++ b/setup/dev/advanced.cfg
@@ -137,16 +137,10 @@
         "port": 3306,
         "user": "cloud"
     },
-    "logger": [
+    "logger": 
         {
-            "name": "TestClient",
-            "file": "/tmp/testclient.log"
+            "LogFolderPath": "/tmp/"
         },
-        {
-            "name": "TestCase",
-            "file": "/tmp/testcase.log"
-        }
-    ],
     "globalConfig": [
         {
             "name": "network.gc.wait",

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1190abd4/tools/marvin/marvin/cloudstackConnection.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py
index 23f81fb..48a2d21 100644
--- a/tools/marvin/marvin/cloudstackConnection.py
+++ b/tools/marvin/marvin/cloudstackConnection.py
@@ -20,24 +20,24 @@ import urllib
 import base64
 import hmac
 import hashlib
-import logging
 import time
 import cloudstackException
 from cloudstackAPI import *
 import jsonHelper
-from requests import ConnectionError
-from requests import HTTPError
-from requests import Timeout
-from requests import RequestException
+from requests import (
+    ConnectionError,
+    HTTPError,
+    Timeout,
+    RequestException
+    )
 
 
 class cloudConnection(object):
 
     """ Connections to make API calls to the cloudstack management server
     """
-    def __init__(self, mgmtDet, asyncTimeout=3600, logging=None,
+    def __init__(self, mgmtDet, asyncTimeout=3600, logger=None,
                  path='client/api'):
-        self.loglevel()  # Turn off requests logs
         self.apiKey = mgmtDet.apiKey
         self.securityKey = mgmtDet.securityKey
         self.mgtSvr = mgmtDet.mgtSvrIp
@@ -46,7 +46,7 @@ class cloudConnection(object):
         self.passwd = mgmtDet.passwd
         self.certCAPath = mgmtDet.certCAPath
         self.certPath = mgmtDet.certPath
-        self.logging = logging
+        self.logger = logger
         self.path = path
         self.retries = 5
         self.mgtDetails = mgmtDet
@@ -67,13 +67,6 @@ class cloudConnection(object):
                                self.logging,
                                self.path)
 
-    def loglevel(self, lvl=logging.WARNING):
-        """
-        Turns off the INFO/DEBUG logs from `requests`
-        """
-        requests_log = logging.getLogger("requests")
-        requests_log.setLevel(lvl)
-
     def poll(self, jobid, response):
         """
         polls the completion of a given jobid
@@ -95,9 +88,9 @@ class cloudConnection(object):
                 return asyncResonse
 
             time.sleep(5)
-            if self.logging is not None:
-                self.logging.debug("job: %s still processing,"
-                                   " will timeout in %ds" % (jobid, timeout))
+            if self.logger is not None:
+                self.logger.debug("job: %s still processing,"
+                                  "will timeout in %ds" % (jobid, timeout))
             timeout = timeout - 5
 
         raise cloudstackException.cloudstackAPIException(
@@ -122,7 +115,7 @@ class cloudConnection(object):
         )
         signature = base64.encodestring(hmac.new(
             self.securityKey, hashStr, hashlib.sha1).digest()).strip()
-        self.logging.debug("Computed Signature by Marvin: %s" % signature)
+        self.logger.debug("Computed Signature by Marvin: %s" % signature)
         return signature
 
     def request(self, command, auth=True, payload={}, method='GET'):
@@ -186,7 +179,7 @@ class cloudConnection(object):
                     then try with default certs, \
                     we dont need to mention here the cert path
                     '''
-                    self.logging.debug("Creating CS connection over https \
+                    self.logger.debug("Creating CS connection over https \
                                         didnt worked with user provided certs \
                                             , so trying with no certs %s" % e)
                     if method == 'POST':
@@ -198,20 +191,20 @@ class cloudConnection(object):
                                                 params=payload,
                                                 verify=https_flag)
         except ConnectionError, c:
-            self.logging.debug("Connection refused. Reason: %s : %s"
-                               % (self.baseurl, c))
+            self.logger.debug("Connection refused. Reason: %s : %s" %
+                              (self.baseurl, c))
             raise c
         except HTTPError, h:
-            self.logging.debug("Http Error.Server returned error code: %s" % h)
+            self.logger.debug("Http Error.Server returned error code: %s" % h)
             raise h
         except Timeout, t:
-            self.logging.debug("Connection timed out with %s" % t)
+            self.logger.debug("Connection timed out with %s" % t)
             raise t
         except RequestException, r:
-            self.logging.debug("RequestException from server %s" % r)
+            self.logger.debug("RequestException from server %s" % r)
             raise r
         except Exception, e:
-            self.logging.debug("Error returned by server %s" % r)
+            self.logger.debug("Error returned by server %s" % r)
             raise e
         else:
             return response
@@ -265,16 +258,16 @@ class cloudConnection(object):
         @return:
         """
         cmdname, isAsync, payload = self.sanitizeCommand(cmd)
-        self.logging.debug("sending %s request: %s %s" % (method, cmdname,
-                                                          str(payload)))
+        self.logger.debug("sending %s request: %s %s" % (method, cmdname,
+                                                         str(payload)))
         response = self.request(cmdname,
                                 self.auth,
                                 payload=payload,
                                 method=method)
         if response is None:
             return None
-        self.logging.debug("Request: %s Response: %s" %
-                           (response.url, response.text))
+        self.logger.debug("Request: %s Response: %s" % (response.url,
+                                                        response.text))
         try:
             response = jsonHelper.getResultObj(response.json(), response_type)
         except TypeError:

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1190abd4/tools/marvin/marvin/codes.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/codes.py b/tools/marvin/marvin/codes.py
index f409c7c..8f0f88d 100644
--- a/tools/marvin/marvin/codes.py
+++ b/tools/marvin/marvin/codes.py
@@ -42,3 +42,8 @@ PASS = 1
 MATCH_NOT_FOUND = "ELEMENT NOT FOUND IN THE INPUT"
 SUCCESS = "SUCCESS"
 EXCEPTION_OCCURRED = "Exception Occurred"
+NO = "no"
+YES = "yes"
+FAILED = "FAILED"
+UNKNOWN_ERROR = "Unknown Error"
+EXCEPTION = "Exception"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1190abd4/tools/marvin/marvin/configGenerator.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/configGenerator.py b/tools/marvin/marvin/configGenerator.py
index 631e40f..3f98aca 100644
--- a/tools/marvin/marvin/configGenerator.py
+++ b/tools/marvin/marvin/configGenerator.py
@@ -534,18 +534,6 @@ def descSetupInBasicMode():
         cfg.value = v
         zs.globalConfig.append(cfg)
 
-    ''''add loggers'''
-    testClientLogger = logger()
-    testClientLogger.name = "TestClient"
-    testClientLogger.file = "/tmp/testclient.log"
-
-    testCaseLogger = logger()
-    testCaseLogger.name = "TestCase"
-    testCaseLogger.file = "/tmp/testcase.log"
-
-    zs.logger.append(testClientLogger)
-    zs.logger.append(testCaseLogger)
-
     return zs
 
 
@@ -669,18 +657,6 @@ def descSetupInEipMode():
         cfg.value = v
         zs.globalConfig.append(cfg)
 
-    ''''add loggers'''
-    testClientLogger = logger()
-    testClientLogger.name = "TestClient"
-    testClientLogger.file = "/tmp/testclient.log"
-
-    testCaseLogger = logger()
-    testCaseLogger.name = "TestCase"
-    testCaseLogger.file = "/tmp/testcase.log"
-
-    zs.logger.append(testClientLogger)
-    zs.logger.append(testCaseLogger)
-
     return zs
 
 
@@ -801,18 +777,6 @@ def descSetupInAdvancedMode():
         cfg.value = v
         zs.globalConfig.append(cfg)
 
-    ''''add loggers'''
-    testClientLogger = logger()
-    testClientLogger.name = "TestClient"
-    testClientLogger.file = "/tmp/testclient.log"
-
-    testCaseLogger = logger()
-    testCaseLogger.name = "TestCase"
-    testCaseLogger.file = "/tmp/testcase.log"
-
-    zs.logger.append(testClientLogger)
-    zs.logger.append(testCaseLogger)
-
     return zs
 
 '''sample code to generate setup configuration file'''
@@ -926,18 +890,6 @@ def descSetupInAdvancedsgMode():
         cfg.value = v
         zs.globalConfig.append(cfg)
 
-    ''''add loggers'''
-    testClientLogger = logger()
-    testClientLogger.name = "TestClient"
-    testClientLogger.file = "/tmp/testclient.log"
-
-    testCaseLogger = logger()
-    testCaseLogger.name = "TestCase"
-    testCaseLogger.file = "/tmp/testcase.log"
-
-    zs.logger.append(testClientLogger)
-    zs.logger.append(testCaseLogger)
-
     return zs
 
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1190abd4/tools/marvin/marvin/deployDataCenter.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py
index 33bc438..9343171 100644
--- a/tools/marvin/marvin/deployDataCenter.py
+++ b/tools/marvin/marvin/deployDataCenter.py
@@ -28,16 +28,9 @@ from optparse import OptionParser
 
 class deployDataCenters(object):
 
-    def __init__(self, cfgFile):
-        if not path.exists(cfgFile) \
-           and not path.exists(path.abspath(cfgFile)):
-            raise IOError("config file %s not found. please \
-                           specify a valid config file" % cfgFile)
-        self.configFile = cfgFile
-        '''
-        parsed configuration information
-        '''
-        self.config = None
+    def __init__(self, cfg, logger=None):
+        self.config = cfg
+        self.tcRunLogger = logger
 
     def addHosts(self, hosts, zoneId, podId, clusterId, hypervisor):
         if hosts is None:
@@ -507,50 +500,17 @@ class deployDataCenters(object):
         self.config.mgtSvr[0].securityKey = securityKey
         return apiKey, securityKey
 
-    def getCfg(self):
-        if self.config is not None:
-            return self.config
-        return None
-
     def loadCfg(self):
-        try:
-            self.config = configGenerator.getSetupConfig(self.configFile)
-        except:
-            raise cloudstackException.InvalidParameterException("Failed to load config %s" % self.configFile)
-
         ''' Retrieving Management Server Connection Details '''
         mgtDetails = self.config.mgtSvr[0]
         ''' Retrieving Database Connection Details'''
         dbSvrDetails = self.config.dbSvr
-        loggers = self.config.logger
-        testClientLogFile = None
-        self.testCaseLogFile = None
-        self.testResultLogFile = None
-        if loggers is not None and len(loggers) > 0:
-            for log in loggers:
-                if log.name == "TestClient":
-                    testClientLogFile = log.file
-                elif log.name == "TestCase":
-                    self.testCaseLogFile = log.file
-                elif log.name == "TestResult":
-                    self.testResultLogFile = log.file
-
-        testClientLogger = None
-        if testClientLogFile is not None:
-            testClientLogger = logging.getLogger("testclient.testengine.run")
-            fh = logging.FileHandler(testClientLogFile)
-            fh.setFormatter(logging.
-            Formatter("%(asctime)s - %(levelname)s - %(name)s\
-           - %(message)s"))
-            testClientLogger.addHandler(fh)
-            testClientLogger.setLevel(logging.INFO)
-        self.testClientLogger = testClientLogger
 
         self.testClient = \
             cloudstackTestClient.\
             cloudstackTestClient(mgtDetails,
                                  dbSvrDetails,
-                                 logging=self.testClientLogger)
+                                 logging=self.tcRunLogger)
 
         if mgtDetails.apiKey is None:
             mgtDetails.apiKey, mgtDetails.securityKey = self.registerApiKey()
@@ -559,8 +519,7 @@ class deployDataCenters(object):
                 cloudstackTestClient.cloudstackTestClient(
                     mgtDetails,
                     dbSvrDetails,
-                    logging=
-                    self.testClientLogger)
+                    logging=self.tcRunLogger)
 
         self.apiClient = self.testClient.getApiClient()
         """set hypervisor"""
@@ -606,7 +565,11 @@ if __name__ == "__main__":
                       ./datacenterCfg")
 
     (options, args) = parser.parse_args()
-    deploy = deployDataCenters(options.input)
+    from marvin.marvinLog import MarvinLog
+    cfg = configGenerator.getSetupConfig(options.input)
+    log_obj = MarvinLog("CSLog")
+    tcRunLogger = log_obj.setLogHandler("/tmp/debug.log")
+    deploy = deployDataCenters(cfg, tcRunLogger)
     deploy.deploy()
 
     """

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1190abd4/tools/marvin/marvin/marvinInit.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/marvinInit.py b/tools/marvin/marvin/marvinInit.py
new file mode 100644
index 0000000..d822a2b
--- /dev/null
+++ b/tools/marvin/marvin/marvinInit.py
@@ -0,0 +1,159 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with 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.
+'''
+@Desc: Initializes the marvin and does required prerequisites
+for starting it.
+1. Parses the configuration file passed to marvin and creates a
+   parsed config
+   2. Initializes the logging required for marvin.All logs are
+   now made available under a single timestamped folder.
+   3. Deploys the Data Center based upon input
+
+'''
+
+from marvin import configGenerator
+from marvin import cloudstackException
+from marvin.marvinLog import MarvinLog
+from marvin.deployDataCenter import deployDataCenters
+from marvin.codes import(
+    YES,
+    NO,
+    SUCCESS,
+    FAILED
+    )
+import sys
+import time
+import os
+import logging
+
+
+class MarvinInit:
+    def __init__(self, config_file, load_flag):
+        self.__configFile = config_file
+        self.__loadFlag = load_flag
+        self.__parsedConfig = None
+        self.__logFolderPath = None
+        self.__tcRunLogger = None
+        self.__testClient = None
+        self.__tcRunDebugFile = None
+
+    def __parseConfig(self):
+        '''
+        @Desc : Parses the configuration file passed and assigns
+        the parsed configuration
+        '''
+        try:
+            self.__parsedConfig = configGenerator.\
+                getSetupConfig(self.__configFile)
+            return SUCCESS
+        except Exception, e:
+            print "\n Exception Occurred Under __parseConfig : %s" % str(e)
+            return None
+
+    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 getDebugFile(self):
+        return self.__tcRunDebugFile
+
+    def init(self):
+        '''
+        @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
+        '''
+        try:
+            if ((self.__parseConfig() is not None) and
+               (self.__initLogging() is not None) and
+               (self.__deployDC() is not None)):
+                return SUCCESS
+            else:
+                return FAILED
+        except Exception, e:
+            print "\n Exception Occurred Under init %s" % str(e)
+            return FAILED
+
+    def __initLogging(self):
+        try:
+            '''
+            @Desc : 1. Initializes the logging for marvin and so provides
+                    various log features for automation run.
+                    2. Initializes all logs to be available under
+                    given Folder Path,where all test run logs
+                    are available for a given run.
+                    3. All logging like exception log,results, run info etc
+                     for a given test run are available under a given
+                     timestamped folder
+            '''
+            log_config = self.__parsedConfig.logger
+            temp_path = "".join(str(time.time()).split("."))
+            if log_config is not None:
+                if log_config.LogFolderPath is not None:
+                    self.logFolderPath = log_config.LogFolderPath + temp_path
+                else:
+                    self.logFolderPath = temp_path
+            else:
+                self.logFolderPath = temp_path
+            os.makedirs(self.logFolderPath)
+            '''
+            Log File Paths
+            '''
+            tc_failed_exceptionlog = self.logFolderPath + "/failed_" \
+                                                          "plus_" \
+                                                          "exceptions.txt"
+            tc_run_log = self.logFolderPath + "/runinfo.txt"
+            self.__tcRunDebugFile = open(self.logFolderPath +
+                                         "/tcresults.txt", "w")
+
+            log_obj = MarvinLog("CSLog")
+            self.__tcRunLogger = log_obj.setLogHandler(tc_run_log)
+            log_obj.setLogHandler(tc_failed_exceptionlog,
+                                  log_level=logging.FATAL)
+            return SUCCESS
+        except Exception, e:
+            print "\n Exception Occurred Under __initLogging :%s" % str(e)
+            return None
+
+    def __deployDC(self):
+        try:
+            '''
+            Deploy the DataCenter and retrieves test client.
+            '''
+            deploy_obj = deployDataCenters(self.__parsedConfig,
+                                           self.__tcRunLogger)
+            if self.__loadFlag:
+                deploy_obj.loadCfg()
+            else:
+                deploy_obj.deploy()
+
+            self.__testClient = deploy_obj.testClient
+            return SUCCESS
+        except Exception, e:
+            print "\n Exception Occurred Under __deployDC : %s" % str(e)
+            return None

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1190abd4/tools/marvin/marvin/marvinLog.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/marvinLog.py b/tools/marvin/marvin/marvinLog.py
new file mode 100644
index 0000000..ca4d600
--- /dev/null
+++ b/tools/marvin/marvin/marvinLog.py
@@ -0,0 +1,72 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with 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.
+'''
+@Desc: Module for providing logging facilities to marvin
+'''
+import logging
+import sys
+from marvin.codes import (NO,
+                          YES
+                          )
+
+
+class MarvinLog:
+    '''
+    @Desc  : provides interface for logging to marvin
+    @Input : logger_name : name for logger
+    '''
+    logFormat = "%(asctime)s - %(levelname)s - %(name)s - %(message)s"
+    _instance = None
+
+    def __new__(cls, logger_name):
+        if not cls._instance:
+            cls._instance = super(MarvinLog, cls).__new__(cls, logger_name)
+            return cls._instance
+
+    def __init__(self, logger_name):
+        self.loggerName = logger_name
+        self.logger = None
+        self.__setLogger()
+
+    def __setLogger(self):
+        self.logger = logging.getLogger(self.loggerName)
+        self.logger.setLevel(logging.DEBUG)
+
+    def setLogHandler(self, log_file_path, log_format=None,
+                      log_level=logging.DEBUG):
+        '''
+        @Desc:
+        @Input: log_file_path: Log File Path as where to store the logs
+               log_format : Format of log messages to be dumped
+               log_level : Determines the level of logging for this logger
+        '''
+        try:
+            if log_file_path is not None:
+                stream = logging.FileHandler(log_file_path)
+            else:
+                stream = logging.StreamHandler(stream=sys.stdout)
+
+            if log_format is None:
+                stream.setFormatter(log_format)
+            else:
+                stream.setFormatter(cls.logFormat)
+            stream.setLevel(log_level)
+            self.logger.addHandler(stream)
+        except Exception, e:
+            print "\n Exception Occurred Under setLogHandler %s" % str(e)
+        finally:
+            return self.logger

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1190abd4/tools/marvin/marvin/marvinPlugin.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/marvinPlugin.py b/tools/marvin/marvin/marvinPlugin.py
index 48d5154..852b84a 100644
--- a/tools/marvin/marvin/marvinPlugin.py
+++ b/tools/marvin/marvin/marvinPlugin.py
@@ -20,9 +20,16 @@ import sys
 import logging
 import nose.core
 from marvin.cloudstackTestCase import cloudstackTestCase
-from marvin import deployDataCenter
+from marvin.marvinInit import MarvinInit
 from nose.plugins.base import Plugin
+from marvin.codes import (SUCCESS,
+                          FAILED,
+                          EXCEPTION,
+                          UNKNOWN_ERROR
+                          )
+import traceback
 import time
+import os
 
 
 class MarvinPlugin(Plugin):
@@ -32,7 +39,21 @@ class MarvinPlugin(Plugin):
 
     name = "marvin"
 
-    def configure(self, options, config):
+    def __init__(self):
+        self.identifier = None
+        self.testClient = None
+        self.parsedConfig = None
+        self.configFile = None
+        self.loadFlag = None
+        self.conf = None
+        self.debugStream = sys.stdout
+        self.testRunner = None
+        self.startTime = None
+        self.testName = None
+        self.tcRunLogger = 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.
@@ -44,33 +65,13 @@ class MarvinPlugin(Plugin):
                 return
             else:
                 self.enabled = True
-        self.logformat = logging.Formatter("%(asctime)s - %(levelname)s - " +
-                                           "%(name)s - %(message)s")
-
-        if options.debug_log:
-            self.logger = logging.getLogger("NoseTestExecuteEngine")
-            self.debug_stream = logging.FileHandler(options.debug_log)
-            self.debug_stream.setFormatter(self.logformat)
-            self.logger.addHandler(self.debug_stream)
-            self.logger.setLevel(logging.DEBUG)
-
-        if options.result_log:
-            ch = logging.StreamHandler()
-            ch.setLevel(logging.ERROR)
-            ch.setFormatter(self.logformat)
-            self.logger.addHandler(ch)
-            self.result_stream = open(options.result_log, "w")
-        else:
-            self.result_stream = sys.stdout
-
-        deploy = deployDataCenter.deployDataCenters(options.config_file)
-        deploy.loadCfg() if options.load else deploy.deploy()
-        self.setClient(deploy.testClient)
-        self.setConfig(deploy.getCfg())
-
-        self.testrunner = nose.core.TextTestRunner(stream=self.result_stream,
-                                                   descriptions=True,
-                                                   verbosity=2, config=config)
+        self.configFile = options.config_file
+        self.loadFlag = options.load
+        self.conf = conf
+        '''
+        Initializes the marvin with required settings
+        '''
+        self.startMarvin()
 
     def options(self, parser, env):
         """
@@ -82,29 +83,11 @@ class MarvinPlugin(Plugin):
                           help="Marvin's configuration file where the " +
                                "datacenter information is specified " +
                                "[MARVIN_CONFIG]")
-        parser.add_option("--result-log", action="store",
-                          default=env.get('RESULT_LOG', None),
-                          dest="result_log",
-                          help="The path to the results file where test " +
-                               "summary will be written to [RESULT_LOG]")
-        parser.add_option("--client-log", action="store",
-                          default=env.get('DEBUG_LOG', 'debug.log'),
-                          dest="debug_log",
-                          help="The path to the testcase debug logs " +
-                          "[DEBUG_LOG]")
         parser.add_option("--load", action="store_true", default=False,
                           dest="load",
                           help="Only load the deployment configuration given")
-
         Plugin.options(self, parser, env)
 
-    def __init__(self):
-        self.identifier = None
-        Plugin.__init__(self)
-
-    def prepareTestRunner(self, runner):
-        return self.testrunner
-
     def wantClass(self, cls):
         if cls.__name__ == 'cloudstackTestCase':
             return False
@@ -117,18 +100,13 @@ class MarvinPlugin(Plugin):
             self.identifier = cls.__name__
             self._injectClients(cls)
 
-    def setClient(self, client):
-        if client is not None:
-            self.testclient = client
-
-    def setConfig(self, config):
-        if config is not None:
-            self.config = config
-
     def beforeTest(self, test):
         self.testName = test.__str__().split()[0]
-        self.testclient.identifier = '-'.join([self.identifier, self.testName])
-        self.logger.name = test.__str__()
+        self.testClient.identifier = '-'.join([self.identifier, self.testName])
+        self.tcRunLogger.name = test.__str__()
+
+    def prepareTestRunner(self, runner):
+        return self.testRunner
 
     def startTest(self, test):
         """
@@ -136,6 +114,58 @@ class MarvinPlugin(Plugin):
         """
         self.startTime = time.time()
 
+    def getErrorInfo(self, err):
+        '''
+        Extracts and returns the sanitized error message
+        '''
+        if err is not None:
+            return str(traceback.format_exc())
+        else:
+            return UNKNOWN_ERROR
+
+    def handleError(self, test, err):
+        '''
+        Adds Exception throwing test cases and information to log.
+        '''
+        err_msg = self.getErrorInfo(err)
+        self.tcRunLogger.fatal("%s: %s: %s" %
+                               (EXCEPTION, self.testName, err_msg))
+
+    def handleFailure(self, test, err):
+        '''
+        Adds Failing test cases and information to log.
+        '''
+        err_msg = self.getErrorInfo(err)
+        self.tcRunLogger.fatal("%s: %s: %s" %
+                               (FAILED, self.testName, err_msg))
+
+    def startMarvin(self):
+        '''
+        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.loadFlag)
+            if obj_marvininit.init() == SUCCESS:
+                self.testClient = obj_marvininit.getTestClient()
+                self.tcRunLogger = obj_marvininit.getLogger()
+                self.parsedConfig = obj_marvininit.getParsedConfig()
+                self.debugStream = obj_marvininit.getDebugFile()
+                self.testRunner = nose.core.TextTestRunner(stream=
+                                                           self.debugStream,
+                                                           descriptions=True,
+                                                           verbosity=2,
+                                                           config=self.conf)
+                return SUCCESS
+            else:
+                return FAILED
+        except Exception, e:
+            print "Exception Occurred under startMarvin: %s" % str(e)
+            return FAILED
+
     def stopTest(self, test):
         """
         Currently used to record end time for tests
@@ -143,22 +173,24 @@ class MarvinPlugin(Plugin):
         endTime = time.time()
         if self.startTime is not None:
             totTime = int(endTime - self.startTime)
-            self.logger.debug(
-                "TestCaseName: %s; Time Taken: %s Seconds; \
-                StartTime: %s; EndTime: %s"
-                % (self.testName, str(totTime),
-                   str(time.ctime(self.startTime)), str(time.ctime(endTime))))
+            self.tcRunLogger.debug("TestCaseName: %s; Time Taken: "
+                                   "%s Seconds; "
+                                   "StartTime: %s; EndTime: %s"
+                                   % (self.testName, str(totTime),
+                                      str(time.ctime(self.startTime)),
+                                      str(time.ctime(endTime))))
 
     def _injectClients(self, test):
-        setattr(test, "debug", self.logger.debug)
-        setattr(test, "info", self.logger.info)
-        setattr(test, "warn", self.logger.warning)
-        setattr(test, "testClient", self.testclient)
-        setattr(test, "config", self.config)
-        if self.testclient.identifier is None:
-            self.testclient.identifier = self.identifier
-        setattr(test, "clstestclient", self.testclient)
+        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.createUserApiClient(test.UserName, test.DomainName,
+            self.testClient.createUserApiClient(test.UserName, test.DomainName,
                                                 test.AcctType)