Implement a log level option to enable ONOS logs for every test case.
This is done automatically through overriding of setUp in CordLogger which every test class should inherit.
Otherwise, one can manually enable logSet for all controllers through the CordLogger logSet api.

Change-Id: I43bd5a97e0ab9cbec7d7c51daf2d5ea0d6961505
diff --git a/src/test/cbench/__init__.py b/src/test/cbench/__init__.py
index 374665c..db4ad9c 100644
--- a/src/test/cbench/__init__.py
+++ b/src/test/cbench/__init__.py
@@ -22,3 +22,5 @@
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
 __path__.append(subscriber_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/cluster/clusterTest.py b/src/test/cluster/clusterTest.py
index 5099900..a694bad 100644
--- a/src/test/cluster/clusterTest.py
+++ b/src/test/cluster/clusterTest.py
@@ -108,12 +108,8 @@
         self.cliExit()
         return result
 
-    def log_set(self, level = "INFO", app = "org.onosproject", controller = None):
-        self.cliEnter(controller = controller)
-        try:
-            self.cli.logSet(level = level, app = app)
-        except: pass
-        self.cliExit()
+    def log_set(self, level = None, app = 'org.onosproject', controllers = None):
+        CordLogger.logSet(level = level, app = app, controllers = controllers, forced = True)
 
     def get_leaders(self, controller = None):
         result_map = {}
@@ -382,15 +378,12 @@
             log.info('ITERATION: %d. Restarting Controller %s' %(num + 1, controller_name))
             try:
                 #enable debug log for the other controllers before restarting this controller
-                for ctlr in controllers:
-                    if ctlr == controller:
-                        continue
-                    log.info('Enabling DEBUG log for controller: %s' %ctlr)
-                    self.log_set(level="DEBUG", controller = ctlr)
-                    self.log_set(level="DEBUG", app = "io.atomix", controller = ctlr)
+                adjacent_controllers = list( set(controllers) - set([controller]) )
+                self.log_set(controllers = adjacent_controllers)
+                self.log_set(app = 'io.atomix', controllers = adjacent_controllers)
                 cord_test_onos_restart(node = controller_name, timeout = 0)
-                self.log_set(level="DEBUG", controller = controller)
-                self.log_set(level="DEBUG", app = "io.atomix", controller = controller)
+                self.log_set(controllers = controller)
+                self.log_set(app = 'io.atomix', controllers = controller)
                 time.sleep(60)
             except:
                 time.sleep(5)
diff --git a/src/test/cordSubscriber/__init__.py b/src/test/cordSubscriber/__init__.py
index 374665c..db4ad9c 100644
--- a/src/test/cordSubscriber/__init__.py
+++ b/src/test/cordSubscriber/__init__.py
@@ -22,3 +22,5 @@
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
 __path__.append(subscriber_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/cordvtn/__init__.py b/src/test/cordvtn/__init__.py
index d2ccc00..fd839d6 100644
--- a/src/test/cordvtn/__init__.py
+++ b/src/test/cordvtn/__init__.py
@@ -20,3 +20,5 @@
 fsm_dir = os.path.join(working_dir, '../fsm')
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/dhcp/__init__.py b/src/test/dhcp/__init__.py
index b7bb2a9..58368ab 100644
--- a/src/test/dhcp/__init__.py
+++ b/src/test/dhcp/__init__.py
@@ -22,4 +22,5 @@
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
 __path__.append(subscriber_dir)
-
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/dhcprelay/__init__.py b/src/test/dhcprelay/__init__.py
index 0a5ce19..58368ab 100644
--- a/src/test/dhcprelay/__init__.py
+++ b/src/test/dhcprelay/__init__.py
@@ -22,3 +22,5 @@
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
 __path__.append(subscriber_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/fabric/__init__.py b/src/test/fabric/__init__.py
index b3dcc62..dce9397 100644
--- a/src/test/fabric/__init__.py
+++ b/src/test/fabric/__init__.py
@@ -20,3 +20,5 @@
 fsm_dir = os.path.join(working_dir, '../fsm')
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/flows/__init__.py b/src/test/flows/__init__.py
index b3dcc62..dce9397 100644
--- a/src/test/flows/__init__.py
+++ b/src/test/flows/__init__.py
@@ -20,3 +20,5 @@
 fsm_dir = os.path.join(working_dir, '../fsm')
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/igmp/__init__.py b/src/test/igmp/__init__.py
index 374665c..db4ad9c 100644
--- a/src/test/igmp/__init__.py
+++ b/src/test/igmp/__init__.py
@@ -22,3 +22,5 @@
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
 __path__.append(subscriber_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/md5/__init__.py b/src/test/md5/__init__.py
index b3dcc62..dce9397 100644
--- a/src/test/md5/__init__.py
+++ b/src/test/md5/__init__.py
@@ -20,3 +20,5 @@
 fsm_dir = os.path.join(working_dir, '../fsm')
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/netCondition/__init__.py b/src/test/netCondition/__init__.py
index 4344312..db4ad9c 100644
--- a/src/test/netCondition/__init__.py
+++ b/src/test/netCondition/__init__.py
@@ -22,4 +22,5 @@
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
 __path__.append(subscriber_dir)
-
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/pap/__init__.py b/src/test/pap/__init__.py
index b3dcc62..dce9397 100644
--- a/src/test/pap/__init__.py
+++ b/src/test/pap/__init__.py
@@ -20,3 +20,5 @@
 fsm_dir = os.path.join(working_dir, '../fsm')
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/setup/cord-test.py b/src/test/setup/cord-test.py
index 7b52058..4ef4408 100755
--- a/src/test/setup/cord-test.py
+++ b/src/test/setup/cord-test.py
@@ -319,6 +319,7 @@
 onos_app_file = os.path.abspath('{0}/../apps/ciena-cordigmp-'.format(cord_tester_base) + onos_app_version + '.oar')
 cord_test_server_address = '{}:{}'.format(CORD_TEST_HOST, CORD_TEST_PORT)
 identity_file_default = '/etc/maas/ansible/id_rsa'
+onos_log_level = 'INFO'
 
 ##sets up the ssh key file for the test container
 def set_ssh_key_file(identity_file):
@@ -339,6 +340,7 @@
     test_server_params = args.server.split(':')
     test_host = test_server_params[0]
     test_port = CORD_TEST_PORT
+    log_level = args.log_level.upper()
     if len(test_server_params) > 1:
         test_port = int(test_server_params[1])
     try:
@@ -477,6 +479,7 @@
                      'CORD_TEST_HOST' : test_host,
                      'CORD_TEST_PORT' : test_port,
                      'ONOS_RESTART' : 0 if args.olt and args.test_controller else 1,
+                     'LOG_LEVEL': log_level,
                      'MANIFEST': int(use_manifest),
                      'HEAD_NODE': head_node if head_node else CORD_TEST_HOST,
                      'MAAS_API_KEY': maas_api_key
@@ -572,7 +575,7 @@
     nose_cnt = {'image': CordTester.IMAGE, 'tag': 'candidate'}
     update_map = { 'quagga' : False, 'radius' : False, 'test': False }
     update_map[args.update.lower()] = True
-
+    log_level = args.log_level.upper()
     if args.update.lower() == 'all':
        for c in update_map.keys():
            update_map[c] = True
@@ -708,6 +711,7 @@
                          'CORD_TEST_HOST' : ip,
                          'CORD_TEST_PORT' : port,
                          'ONOS_RESTART' : 0 if args.olt and args.test_controller else 1,
+                         'LOG_LEVEL': log_level,
                          'MANIFEST': int(use_manifest),
                          'HEAD_NODE': head_node if head_node else CORD_TEST_HOST,
                          'MAAS_API_KEY': maas_api_key
@@ -963,6 +967,10 @@
     parser_run.add_argument('-j', '--onos-instances', default=1, type=int,
                             help='Specify number to test onos instances to form cluster')
     parser_run.add_argument('-v', '--shared-volume', action='store_true', help='Start ONOS cluster instances with shared volume')
+    parser_run.add_argument('-log', '--log-level', default=onos_log_level,
+                            choices=['DEBUG','TRACE','ERROR','WARN','INFO'],
+                            type=str,
+                            help='Specify the log level for the test cases')
     parser_run.set_defaults(func=runTest)
 
 
@@ -980,6 +988,9 @@
                         '    --update=all to rebuild all cord tester images.')
     parser_setup.add_argument('-d', '--dont-provision', action='store_true', help='Dont start test container.')
     parser_setup.add_argument('-l', '--olt', action='store_true', help='Use OLT config')
+    parser_setup.add_argument('-log', '--log-level', default=onos_log_level, type=str,
+                              choices=['DEBUG','TRACE','ERROR','WARN','INFO'],
+                              help='Specify the log level for the test cases')
     parser_setup.add_argument('-s', '--start-switch', action='store_true', help='Start OVS when running under OLT config')
     parser_setup.add_argument('-c', '--onos-cord', default='', type=str,
                               help='Specify cord location for ONOS cord when running on podd')
diff --git a/src/test/subscriber/__init__.py b/src/test/subscriber/__init__.py
index b3dcc62..dce9397 100644
--- a/src/test/subscriber/__init__.py
+++ b/src/test/subscriber/__init__.py
@@ -20,3 +20,5 @@
 fsm_dir = os.path.join(working_dir, '../fsm')
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
diff --git a/src/test/tls/__init__.py b/src/test/tls/__init__.py
index b3dcc62..3d1f997 100644
--- a/src/test/tls/__init__.py
+++ b/src/test/tls/__init__.py
@@ -1,12 +1,12 @@
-# 
+#
 # Copyright 2016-present Ciena Corporation
 #
 # Licensed 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.
@@ -20,3 +20,7 @@
 fsm_dir = os.path.join(working_dir, '../fsm')
 __path__.append(utils_dir)
 __path__.append(fsm_dir)
+cli_dir = os.path.join(working_dir, '../cli')
+__path__.append(cli_dir)
+
+
diff --git a/src/test/utils/CordLogger.py b/src/test/utils/CordLogger.py
index 5f38c8c..081e33c 100644
--- a/src/test/utils/CordLogger.py
+++ b/src/test/utils/CordLogger.py
@@ -1,11 +1,48 @@
 from OnosLog import OnosLog
 from scapy.all import log
+from onosclidriver import OnosCliDriver
 import unittest
+import os
+import time
 
 class CordLogger(unittest.TestCase):
 
+    controllers = os.getenv('ONOS_CONTROLLER_IP', '').split(',')
+    cliSessions = {}
+    onosLogLevel = 'INFO'
+    curLogLevel = onosLogLevel
+    testLogLevel = os.getenv('LOG_LEVEL', onosLogLevel)
+
+    @classmethod
+    def cliSessionEnter(cls):
+        try:
+            for controller in cls.controllers:
+                if not controller:
+                    continue
+                retries = 0
+                while retries < 3:
+                    cli = OnosCliDriver(controller = controller, connect = True)
+                    if cli.handle:
+                        cls.cliSessions[controller] = cli
+                        break
+                    else:
+                        retries += 1
+                        time.sleep(2)
+        except:
+            pass
+
+    @classmethod
+    def cliSessionExit(cls):
+        try:
+            for controller, cli in cls.cliSessions.items():
+                if cli:
+                    cli.disconnect()
+        except:
+            pass
+
     def setUp(self):
         '''Read the log buffer'''
+        self.logSet()
         try:
             onosLog = OnosLog()
             st, output = onosLog.get_log()
@@ -13,6 +50,8 @@
 
     def tearDown(self):
         '''Dump the log buffer for ERRORS/warnings'''
+        #reset the log level back to default log level after a test
+        self.logSet(level = self.onosLogLevel)
         try:
             onosLog = OnosLog()
             st, output = onosLog.get_log( ('ERROR','WARN') )
@@ -22,3 +61,26 @@
             else:
                 log.info('\nTest %s has no errors and warnings in the logs' %self._testMethodName)
         except: pass
+
+    @classmethod
+    def logSet(cls, level = None, app = 'org.onosproject', controllers = None, forced = False):
+        #explicit override of level is allowed to reset log levels
+        if level is None:
+            level = cls.testLogLevel
+        #if we are already at current/ONOS log level, there is nothing to do
+        if forced is False and level == cls.curLogLevel:
+            return
+        if controllers is None:
+            controllers = cls.controllers
+        else:
+            if type(controllers) in [str, unicode]:
+                controllers = [ controllers ]
+        cls.cliSessionEnter()
+        try:
+            for controller in controllers:
+                if cls.cliSessions.has_key(controller):
+                    cls.cliSessions[controller].logSet(level = level, app = app)
+            cls.curLogLevel = level
+        except:
+            pass
+        cls.cliSessionExit()
diff --git a/src/test/utils/__init__.py b/src/test/utils/__init__.py
index 714a2b8..c34e915 100644
--- a/src/test/utils/__init__.py
+++ b/src/test/utils/__init__.py
@@ -1,12 +1,12 @@
-# 
+#
 # Copyright 2016-present Ciena Corporation
 #
 # Licensed 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.
@@ -17,4 +17,6 @@
 ##add the python path to lookup the utils
 working_dir = os.path.dirname(os.path.realpath(sys.argv[-1]))
 utils_dir = os.path.join(working_dir, '../fsm')
+cli_dir = os.path.join(working_dir, '../cli')
 __path__.append(utils_dir)
+__path__.append(cli_dir)