stress_test/controller.py
File `controller.py` has 866 lines of code (exceeds 250 allowed). Consider refactoring.# Copyright (c) 2016 Intracom S.A. Telecom Solutions. All rights reserved.## This program and the accompanying materials are made available under the# terms of the Eclipse Public License v1.0 which accompanies this distribution,# and is available at http://www.eclipse.org/legal/epl-v10.html import loggingimport osimport sysimport stress_test.controller_exceptionsimport timeimport tracebackimport util.file_opsimport util.netutilimport util.processimport queue class Controller: """ All controller-related functionality is here """ def __init__(self, ctrl_base_dir, test_config): """ Creates a Controller object. Options from JSON input file :param test_config: JSON input configuration :param ctrl_base_dir: controller base directory :type test_config: JSON configuration dictionary :type ctrl_base_dir: str """ self.name = test_config['controller_name'] self.base_dir = ctrl_base_dir self.traceback_enabled = False self.ip = test_config['controller_node_ip'] self.ssh_port = test_config['controller_node_ssh_port'] self.ssh_user = test_config['controller_node_username'] self.ssh_pass = test_config['controller_node_password'] self.of_port = test_config['controller_port'] self.logs_dir = self.base_dir + test_config['controller_logs_dir'] self.get_hnd = (self.base_dir + test_config['controller_get_handler']) self.build_hnd = (self.base_dir + test_config['controller_build_handler']) self.start_hnd = (self.base_dir + test_config['controller_start_handler']) self.stop_hnd = (self.base_dir + test_config['controller_stop_handler']) self.status_hnd = (self.base_dir + test_config['controller_status_handler']) self.clean_hnd = (self.base_dir + test_config['controller_clean_handler']) self.java_opts = ' '.join(test_config['java_opts']) self.pid = -1 self._ssh_conn = None util.file_ops.check_filelist([self.build_hnd, self.clean_hnd]) @staticmethod def new(ctrl_base_dir, test_config): """ Factory method. Creates a subclass class depending on the controller name :returns: a subclass or None :rtype: object :raises NotImplementedError: in case an invalid controller_name is \ given in the configuration json file """ name = test_config['controller_name'] if (name == 'ODL'): return ODL(ctrl_base_dir, test_config) elif name == 'ONOS': raise NotImplementedError('ONOS is not supported yet') else: raise NotImplementedError('Not supported yet') Similar blocks of code found in 4 locations. Consider refactoring. def _error_handling(self, error_message, error_num=1): """ Handles custom errors of controller :param error_message: message of the handled error :param error_num: error number of the handled error, used to define \ subcases of raised errors. :type error_message: str :type error_num: int :raises controller_exceptions.CtrlError: to terminate execution of test after error handling """ exc_type, exc_obj, exc_tb = sys.exc_info() logging.error('{0} :::::::::: Exception :::::::::::'. format(exc_obj)) logging.error(error_message) logging.error('Error number:{0}'.format(error_num)) logging.error('{0} - {1} Exception: {2}, {3}'. format(exc_obj, self.name, exc_type, exc_tb.tb_lineno)) if self.traceback_enabled: traceback.print_exc() # Propagate error outside the class to stop test execution raise(stress_test.controller_exceptions.CtrlError) Similar blocks of code found in 3 locations. Consider refactoring. def init_ssh(self): """ Initializes a new SSH client object, with the controller node and \ assigns it to the protected attribute _ssh_conn. If a connection \ already exists it returns a new SSH client object to the \ controller node. :raises controller_exceptions.CtrlNodeConnectionError: if ssh \ connection establishment fails """ logging.info( '[open_ssh_connection] Initiating SSH session with {0} node.'. format(self.name, self.ip)) try: try: if self._ssh_conn is None: self._ssh_conn = util.netutil.ssh_connect_or_return( self.ip, int(self.ssh_port), self.ssh_user, self.ssh_pass, 10) else: # Return a new client ssh object for the controller node return util.netutil.ssh_connect_or_return( self.ip, int(self.ssh_port), self.ssh_user, self.ssh_pass, 10) except: raise(stress_test.controller_exceptions. CtrlNodeConnectionError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method cleanup. (6)
Function `cleanup` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring. def cleanup(self): """ Wrapper to the controller cleanup handler :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.CtrlCleanupError: if controller cleanup \ handler fails """ logging.info('[Controller] Cleaning up') try:Similar blocks of code found in 2 locations. Consider refactoring. try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.clean_hnd]): raise(IOError( '{0} clean handler does not exist'. format('[controller.cleanup]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.clean_hnd) exit_status, cmd_output = util.netutil.ssh_run_command( self._ssh_conn, self.clean_hnd, '[controller.clean_handler]') if exit_status == 0: logging.info('[controller.clean_handler] controller ' 'successfully cleaned.') else: raise(stress_test.controller_exceptions.CtrlCleanupError( '[controller.clean_handler] controller cleanup ' 'handler exited with non zero exit status. \n ' 'Handler output: {0}'.format(cmd_output), exit_status)) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) except: raise(stress_test.controller_exceptions.CtrlCleanupError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method check_status. (7)
Function `check_status` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring. def check_status(self): """ Wrapper to the controller status handler :returns: the status of the controller (running = 1, not running = 0) :rtype: int :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.CtrlStatusUnknownError: if the handler \ fails to return controller status or fails to execute """ logging.info('[Controller] Checking the status') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.status_hnd]): raise(IOError( '{0} status handler does not exist'. format('[controller.status]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.status_hnd) q = queue.Queue() util.netutil.ssh_run_command(self._ssh_conn, self.status_hnd, '[controller.status]', q) cmd_output = '' while not q.empty(): cmd_output += str(q.get()) + ' ' if cmd_output.strip() == '1': logging.info('[controller.status]: Running-' ' {0}'.format(cmd_output)) elif cmd_output.strip() == '0': logging.info('[controller.status]: Not' 'Running- {0}'.format(cmd_output)) else: raise(stress_test.controller_exceptions. CtrlStatusUnknownError( '[controller.status_handler] Error while ' 'fetching status of the controller. Invalid ' 'value returned./n Returned status value: {0}'. format(cmd_output.strip()), 2)) return cmd_output.strip() except: raise(stress_test.controller_exceptions.CtrlStatusUnknownError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) def check_other_controller(self): """ Checks for processes listening on the specified port :raises controller_exceptions.CtrlPortConflictError: when another \ process listens on controller's port. """ logging.info( '[Controller] Checking if another process is ' 'listening on specified port. Port number: {0}.'. format(self.of_port)) try: try: # check if any process listens on controller port gpid = util.process.getpid_listeningonport(self.of_port, self._ssh_conn) if gpid != -1: raise(stress_test.controller_exceptions. CtrlPortConflictError( '[check_other_controller] Another process is ' 'active on port {0}'.format(self.of_port), 2)) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) except: raise(stress_test.controller_exceptions. CtrlPortConflictError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) def restart(self): """ Restarts the controller """ logging.info('[Controller] Restarting') self.stop() self.start() Cyclomatic complexity is too high in method start. (10)
Function `start` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring. def start(self): """ Wrapper to the controller start handler :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.CtrlStartError: When controller fails to \ start. """ logging.info('[Controller.start] Starting') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.start_hnd]): raise(IOError( '{0} start handler does not exist'. format('[controller.stop]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.start_hnd) if self._ssh_conn is None: os.environ['JAVA_OPTS'] = self.java_opts cmd = [self.start_hnd] else: cmd = ['export JAVA_OPTS="{0}";'.format(self.java_opts), self.start_hnd] if self.check_status() == '0': exit_status, cmd_output = util.netutil.ssh_run_command( self._ssh_conn, ' '.join(cmd), '[Controller.start]') self.pid = self.wait_until_listens(420000) logging.info('[Controller.start] Controller ' 'pid: {0}'.format(self.pid)) self.wait_until_up(420000) if exit_status != 0 or self.pid == -1: raise(stress_test.controller_exceptions.CtrlStartError( '[Controller.start] Fail to start. Start handler ' 'exited with non zero exit status. \n ' 'Handler output: {0}'.format(cmd_output), exit_status)) elif self.check_status() == '1': logging.info('[Controller.start] Controller already ' 'started.') except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) except: raise(stress_test.controller_exceptions.CtrlStartError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method stop. (7)
Function `stop` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring. def stop(self): """ Wrapper to the controller stop handler :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.CtrlStopError: if controller fails to \ stop successfully """ try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.stop_hnd]): raise(IOError( '{0} stop handler does not exist'. format('[controller.stop]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.stop_hnd) if self.check_status() == '1': logging.info('[Controller.stop] Stopping. Controller ' 'PID: {0}'.format(self.pid)) exit_status, cmd_output = util.netutil.ssh_run_command( self._ssh_conn, ' '.join([self.stop_hnd]), '[controller.stop]') util.process.wait_until_process_finishes(self.pid, self._ssh_conn) if exit_status == 0: logging.info("[Controller.stop] Successful stopped") else: raise(stress_test.controller_exceptions.CtrlStopError( '[Controller.stop] Controller failed to stop: {0}'. format(cmd_output), exit_status)) else: logging.info('[Controller.stop] Controller already ' 'stopped.') except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) except: raise(stress_test.controller_exceptions.CtrlStopError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method getcontroller. (6)
Function `getcontroller` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
Similar blocks of code found in 2 locations. Consider refactoring. def getcontroller(self): """ Wrapper to the get controller handler :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.CtrlGetError: if get controller process fails """ logging.info('[Controller] Downloading...') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.get_hnd]): raise(IOError( '{0} get controller handler does not exist'. format('[controller.build]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.get_hnd) exit_status, cmd_output = util.netutil.ssh_run_command( self._ssh_conn, ' '.join([self.get_hnd]), '[controller.get]') if exit_status == 0: logging.info("[Controller.get] Successfully downloaded") else: raise(stress_test.controller_exceptions.CtrlGetError( '[Controller.get] Failure during controller download. ' 'Get handler exited with non zero exit status. \n ' 'Handler output: {0}'. format(cmd_output)), exit_status) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) except: raise(stress_test.controller_exceptions.CtrlGetError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method build. (6)
Function `build` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
Similar blocks of code found in 2 locations. Consider refactoring. def build(self): """ Wrapper to the controller build handler :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.CtrlBuildError: if build process fails """ logging.info('[Controller] Building') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.build_hnd]): raise(IOError( '{0} build handler does not exist'. format('[controller.build]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.build_hnd) exit_status, cmd_output = util.netutil.ssh_run_command( self._ssh_conn, ' '.join([self.build_hnd]), '[controller.build]') if exit_status == 0: logging.info("[Controller.build] Successful building") else: raise(stress_test.controller_exceptions.CtrlBuildError( '[Controller.build] Failure during building. Build ' 'handler exited with non zero exit status. \n ' 'Handler output: {0}'. format(cmd_output)), exit_status) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) except: raise(stress_test.controller_exceptions.CtrlBuildError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method wait_until_listens. (7)
Function `wait_until_listens` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring. def wait_until_listens(self, timeout_ms): """ Waits for controller to start listening on specified port. :param timeout_ms: milliseconds to wait (in milliseconds). :returns: the process ID PID of the controller. :rtype: int :type timeout_ms: int :raises controller_exceptions.CtrlReadyStateError: If controller \ fails to start :raises controller_exceptions.CtrlPortConflictError: if another \ process listens on controllers port. """ logging.info('[Controller] Waiting to start listening on a port') try: try: timeout = time.time() + (float(timeout_ms) / 1000) while time.time() < timeout: time.sleep(1) gpid = util.process.getpid_listeningonport(self.of_port, self._ssh_conn) logging.info('[Controller] Returned pid listening ' 'on port {0}: {1}'.format(self.of_port, gpid)) if gpid > 0: return gpid elif gpid == 0: raise(stress_test.controller_exceptions. CtrlPortConflictError( 'Another controller seems to have started ' 'in the meantime. Exiting...')) raise (stress_test.controller_exceptions.CtrlReadyStateError( 'Controller failed to start within a period of {0} ' 'seconds'.format(float(timeout_ms) / 1000), 2)) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) except: raise(stress_test.controller_exceptions.CtrlReadyStateError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method wait_until_up. (6)
Function `wait_until_up` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. def wait_until_up(self, timeout_ms): """ Waits for controller status to become 1 (started). :param timeout_ms: milliseconds to wait (in milliseconds). :type timeout_ms: int :raises controller_exceptions.CtrlReadyStateError: If controller fails \ to reach a ready state within a certain period of time. """ logging.info('[Controller] Waiting to be started') try: try: timeout = time.time() + (float(timeout_ms) / 1000) while time.time() < timeout: time.sleep(1) if self.check_status() == '1': logging.info('[Controller] Started') return raise(stress_test.controller_exceptions.CtrlReadyStateError( 'Controller failed to start. Status check returned 0 ' 'after trying for {0} seconds.'. format(float(timeout_ms) / 1000), 2)) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) except: raise(stress_test.controller_exceptions.CtrlReadyStateError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Similar blocks of code found in 2 locations. Consider refactoring. def __del__(self): """ Method called when object is destroyed. Cleanup activities are triggered and open connections closed """ try: logging.info('Run controller stop.') self.stop() except Exception as e: logging.info('Fail stopping Controller during cleanup. ' 'Exception message: {0}'.format(e)) try: logging.info('Run controller cleanup.') self.cleanup() except Exception as e: logging.info('Fail cleaning Controller files during cleanup. ' 'Exception message: {0}'.format(e)) try: logging.info('Close controller node ssh connection.') self._ssh_conn.close() except Exception as e: logging.info('Fail closing ssh Controller node connection during ' 'cleanup. Exception message: {0}'.format(e)) class ODL(Controller): """ All OpenDaylight controller-related functionality is here """ def __init__(self, ctrl_base_dir, test_config): """ Initialize the creation of an OpenDaylight controller object. Inherits from Controller class. :param ctrl_base_dir: emulator base directory :param test_config: JSON input configuration :type ctrl_base_dir: str :type test_config: JSON configuration dictionary """ super(self.__class__, self).__init__(ctrl_base_dir, test_config) # The parameters initialized as None are dimensions of the test. # These values are passed outside, from the test in the main for loop. # --------------------------------------------------------------------- self.stat_period_ms = None self.init_ssh() self.build() if 'controller_flowmods_conf_handler' in test_config: self.flowmods_conf_hnd = \ ctrl_base_dir + test_config['controller_flowmods_conf_handler'] if 'controller_statistics_handler' in test_config: self.statistics_hnd = \ ctrl_base_dir + test_config['controller_statistics_handler'] if 'controller_persistent_handler' in test_config: self.persistence_hnd = \ ctrl_base_dir + test_config['controller_persistent_handler'] if 'controller_restconf_port' in test_config: self.restconf_port = test_config['controller_restconf_port'] self.restconf_user = test_config['controller_restconf_user'] self.restconf_pass = test_config['controller_restconf_password'] self.oper_hosts = (ctrl_base_dir + test_config['controller_oper_hosts_handler']) self.oper_switches = (ctrl_base_dir + test_config['controller_oper_switches_handler']) self.oper_links = (ctrl_base_dir + test_config['controller_oper_links_handler']) self.oper_flows = (ctrl_base_dir + test_config['controller_oper_flows_handler']) self.disable_persistence() def generate_xmls(self): """ Starts and then stops the controller to trigger the generation of \ controller's XML files. :raises controller_exceptions.ODLXMLError: if generation of XML files \ fails """ logging.info('[Controller] Generating XML files' ' (start and stop the Controller)') try: try: self.start() self.stop() except: raise(stress_test.controller_exceptions.ODLXMLError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) def disable_persistence(self): """ Configure controller persistent to false in order not to backup \ datastore on the disk. :raises controller_exceptions.ODLDisablePersistenceError: if disable \ of persistence fails """ logging.info('[Controller] Disabling persistence') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.persistence_hnd]): raise(IOError( '{0} disable_persistence handler does not exist'. format('[controller.disable_persistence]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.persistence_hnd) util.netutil.ssh_run_command(self._ssh_conn, ' '.join([self.persistence_hnd]), '[controller.disable_persistence]' ) except: raise(stress_test.controller_exceptions. ODLDisablePersistenceError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) def change_stats(self): """ Wrapper to the controller statistics handler. Changes the value of \ statistics interval in the configuration files of controller. :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.ODLChangeStats: if change of statistics \ interval fails """ logging.info('[Controller] Changing statistics period') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.statistics_hnd]): raise(IOError( '{0} statistics handler does not exist'. format('[controller.change_stats]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.statistics_hnd) util.netutil.ssh_run_command( self._ssh_conn, ' '.join([self.statistics_hnd, str(self.stat_period_ms)]), '[controller.statistics_handler]' ' Changing statistics interval') logging.info( '[Controller] Changed statistics period to {0} ms'. format(self.stat_period_ms)) except: raise(stress_test.controller_exceptions.ODLChangeStats) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) def flowmods_config(self): """ Configure controller to send flow modifications as a response to ARP \ ARP Packet_INs. :raises controller_exceptions.ODLFlowModConfError: if configuration \ actions to respond with flow modifications fail. """ logging.info('[Controller.flowmods_config] Configure flow ' 'modifications') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.flowmods_conf_hnd]): raise(IOError( '{0} Configure for FlowMods handler does not exist'. format('[controller.flowmods_config]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.flowmods_conf_hnd) util.netutil.ssh_run_command( self._ssh_conn, ' '.join([self.flowmods_conf_hnd]), '[controller.flowmods_config]')[0] logging.info('[Controller.flowmods_config] Controller is ' 'configured to send flow mods') except: raise(stress_test.controller_exceptions.ODLFlowModConfError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method get_oper_hosts. (7)
Function `get_oper_hosts` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.
Similar blocks of code found in 4 locations. Consider refactoring. def get_oper_hosts(self, new_ssh_conn=None): """ Wrapper to the controller oper_hosts handler. Makes a REST call to \ the NB interface of the controller and returns the number of hosts \ of the topology, recorded in operational datastore of the controller :param new_ssh_conn: an ssh connection client object :returns: number of hosts from controller's operational datastore :type new_ssh_conn: paramiko.SSHClient :rtype: int :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.ODLGetOperHostsError: if handler fails \ to run or return a valid value """ logging.info('[Controller] Query number of hosts ' 'registered in ODL operational DS') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.oper_hosts]): raise(IOError( '{0} get_oper_hosts handler does not exist'. format('[controller.get_oper_hosts]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.oper_hosts) if new_ssh_conn is not None: used_ssh_conn = new_ssh_conn else: used_ssh_conn = self._ssh_conn ret = util.netutil.ssh_run_command( used_ssh_conn, ' '.join([self.oper_hosts, str(self.ip), str(self.restconf_port), str(self.restconf_user), str(self.restconf_pass)]), '[controller.get_oper_hosts]')[1] if new_ssh_conn is not None: used_ssh_conn.close() try: return int(ret) except: return -1 except: raise(stress_test.controller_exceptions.ODLGetOperHostsError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method get_oper_switches. (7)
Function `get_oper_switches` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.
Similar blocks of code found in 4 locations. Consider refactoring. def get_oper_switches(self, new_ssh_conn=None): """ Wrapper to the controller oper_switches handler. Makes a REST call \ to the NB interface of the controller and returns the number of \ switches of the topology, recorded in operational datastore of the \ controller :param new_ssh_conn: an ssh connection client object :returns: number of switches from controller's operational datastore :type new_ssh_conn: paramiko.SSHClient :rtype: int :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.ODLGetOperSwitchesError: if handler \ fails to run or return a valid value """ logging.info('[Controller] Query number of switches ' ' registered in ODL operational DS') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.oper_switches]): raise(IOError( '{0} get_oper_switches handler does not exist'. format('[controller.get_oper_switches]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.oper_switches) if new_ssh_conn is not None: used_ssh_conn = new_ssh_conn else: used_ssh_conn = self._ssh_conn ret = util.netutil.ssh_run_command( used_ssh_conn, ' '.join([self.oper_switches, str(self.ip), str(self.restconf_port), str(self.restconf_user), str(self.restconf_pass)]), '[controller.get_oper_switches]')[1] if new_ssh_conn is not None: used_ssh_conn.close() try: return int(ret) except: return -1 except: raise(stress_test.controller_exceptions. ODLGetOperSwitchesError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method get_oper_links. (7)
Function `get_oper_links` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.
Similar blocks of code found in 4 locations. Consider refactoring. def get_oper_links(self, new_ssh_conn=None): """ Wrapper to the controller oper_links handler. Makes a REST call \ to the NB interface of the controller and returns the number of \ links of the topology, recorded in operational datastore of the \ controller :param new_ssh_conn: an ssh connection client object :returns: number of links from controller's operational datastore :type new_ssh_conn: paramiko.SSHClient :rtype: int :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.ODLGetOperLinksError: if handler \ fails to run or return a valid value """ logging.info('[Controller] Query number of links registered in ' ' ODL operational DS') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.oper_links]): raise(IOError( '{0} get_oper_links handler does not exist'. format('[controller.get_oper_links]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.oper_links) if new_ssh_conn is not None: used_ssh_conn = new_ssh_conn else: used_ssh_conn = self._ssh_conn ret = util.netutil.ssh_run_command( used_ssh_conn, ' '.join([self.oper_links, str(self.ip), str(self.restconf_port), str(self.restconf_user), str(self.restconf_pass)]), '[controller.get_oper_links]')[1] if new_ssh_conn is not None: used_ssh_conn.close() try: return int(ret) except: return -1 except: raise(stress_test.controller_exceptions.ODLGetOperLinksError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) Cyclomatic complexity is too high in method get_oper_flows. (7)
Function `get_oper_flows` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.
Similar blocks of code found in 4 locations. Consider refactoring. def get_oper_flows(self, new_ssh_conn=None): """ Wrapper to the controller oper_flows handler. Makes a REST call \ to the NB interface of the controller and returns the number of \ flows of the topology, recorded in operational datastore of the \ controller :param new_ssh_conn: an ssh connection client object :returns: number of flows from controller's operational datastore :type new_ssh_conn: paramiko.SSHClient :rtype: int :raises IOError: if the handler does not exist on the remote host :raises controller_exceptions.ODLGetOperFlowsError: if handler \ fails to run or return a valid value """ logging.info('[Controller] Query number of flows installed for ' 'all installed nodes of the topology') try: try: if not util.netutil.isfile(self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, [self.oper_flows]): raise(IOError( '{0} get_oper_flows handler does not exist'. format('[controller.get_oper_links]'))) else: util.netutil.make_remote_file_executable( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, self.oper_flows) if new_ssh_conn is not None: used_ssh_conn = new_ssh_conn else: used_ssh_conn = self._ssh_conn ret = util.netutil.ssh_run_command( used_ssh_conn, ' '.join([self.oper_flows, str(self.ip), str(self.restconf_port), str(self.restconf_user), str(self.restconf_pass)]), '[controller.operational_flows_handler]')[1] if new_ssh_conn is not None: used_ssh_conn.close() try: return int(ret) except: return -1 except: raise(stress_test.controller_exceptions.ODLGetOperFlowsError) except stress_test.controller_exceptions.CtrlError as e: self._error_handling(e.err_msg, e.err_code) def save_log(self, output_dir): """ Save controller log file :param output_dir: the directory where the controller logs are stored :type output_dir: str """ try: logging.info('[controller_save_log] collecting logs from ' 'controller node. Logs path:{0}'. format(self.logs_dir)) util.netutil.copy_dir_remote_to_local( self.ip, self.ssh_port, self.ssh_user, self.ssh_pass, os.path.join(self.base_dir, self.logs_dir), os.path.join(output_dir, 'log')) except: logging.error('[controller_save_log] Fail transferring controller' ' logs directory.') class ONOS(Controller): """ All ONOS controller-related functionality is here """ def __init__(self, ctrl_base_dir, test_config): """ Initialize the creation of an ONOS controller object. Inherits from Controller class. :param ctrl_base_dir: emulator base directory :param test_config: JSON input configuration :type ctrl_base_dir: str :type test_config: JSON configuration dictionary """ super(self.__class__, self).__init__(ctrl_base_dir, test_config) self.stat_period_ms = test_config['controller_statistics_period_ms'] self.oper_hosts = -1 self.oper_switches = -1 self.oper_links = -1 self.oper_flows = -1 self.init_ssh() self.build()