def run(self):
        _request = RequestHelpers()
        _request.url = self.requestURL.URL_GET_DEVICE_DETAIL % (
            self.data_command["test_device"])

        try:
            device = _request.get().json()
            try:
                if device['status_code'] == 500:  #device not exist
                    stringhelpers.err(
                        "DEVICE ID %s NOT EXIST | THREAD %s" %
                        (self.data_command["test_device"], self.name))
            except:  #process fang test device by command
                host = device['ip_mgmt']
                port = int(device['port_mgmt'])
                username = device['username']
                password = device['password']
                device_type = device['os']
                method = device['method']  #ssh, telnet
                parameters = {
                    'device_type': device_type,
                    'host': host,
                    'protocol': method,
                    'username': username,
                    'password': password,
                    'port': port
                }
                '''process command contains params'''
                command = None
                test_args = self.data_command['test_args']
                if len(test_args) > 0:
                    command = self.data_command['command']
                    for x in self.data_command['test_args']:
                        command = command.replace('@{%s}' % (x['name']),
                                                  x['value'])
                else:
                    command = self.data_command['command']
                '''####################################'''

                commands = [command]
                fac = FactoryConnector(**parameters)
                print("FANG DEVICE: host=%s, port=%s, devicetype=%s \n\n" %
                      (host, device['port_mgmt'], device_type))
                fang = fac.execute(commands)
                result_fang = fang.get_output()
                fang.remove_file_log(fac.file_log_command)  #remove file.log

                _request.url = self.requestURL.MEGA_URL_COMMANDLOG_GETBY_COMMANDID % (
                    self.data_command['command_id'])
                command_log = _request.get().json()
                if len(command_log) > 0:
                    cmd_log = {
                        'command_id': self.data_command['command_id'],
                        'device_id': self.data_command["test_device"],
                        'console_log': result_fang,
                        'result': dict(),
                        'command': command
                    }

                    # processing parsing command follow output ###########################################
                    command_type = self.data_command['type']
                    cmd_log = self.parsing(command_type, cmd_log)
                    ######################################################################################

                    try:
                        _request.url = self.requestURL.MEGA_URL_COMMANDLOG_UPDATE % (
                            command_log[0]['log_id'])
                        _request.params = cmd_log
                        _request.put()
                        stringhelpers.info(
                            "MEGA THREAD INFO: %s | THREAD %s" %
                            ("UPDATE COMMAND LOG SUCCESS", self.name))

                        #---------------update mega_status to command------------------------------------------------
                        _request.url = self.requestURL.MEGA_URL_COMMAND_UPDATE % (
                            self.data_command['command_id'])
                        _request.params = {'mega_status': 'tested'}
                        _request.put()
                        key_command = 'command_%d' % (
                            self.data_command['command_id'])
                        del self.dict_command[key_command]
                        #--------------------------------------------------------------------------------------------
                    except ConnectionError as _conErr:
                        stringhelpers.info(
                            "MEGA THREAD ERROR: %s | THREAD %s" %
                            (_conErr, self.name))
                else:
                    cmd_log = {
                        'command_id': self.data_command['command_id'],
                        'device_id': self.data_command["test_device"],
                        'console_log': result_fang,
                        'result': dict(),
                        'command': command
                    }

                    # processing parsing command follow output ###########################################
                    command_type = self.data_command['type']
                    cmd_log = self.parsing(command_type, cmd_log)
                    ######################################################################################

                    try:
                        _request.url = self.requestURL.MEGA_URL_COMMANDLOG_CREATE
                        _request.params = cmd_log
                        _request.post()
                        stringhelpers.info(
                            "MEGA THREAD INFO: %s | THREAD %s" %
                            ("INSERT COMMAND LOG SUCCESS", self.name))
                        # ---------------update mega_status to command------------------------------------------------
                        _request.url = self.requestURL.MEGA_URL_COMMAND_UPDATE % (
                            self.data_command['command_id'])
                        _request.params = {'mega_status': 'tested'}
                        _request.put()
                        key_command = 'command_%d' % (
                            self.data_command['command_id'])
                        del self.dict_command[key_command]
                        # --------------------------------------------------------------------------------------------
                    except ConnectionError as _conErr:
                        stringhelpers.info(
                            "MEGA THREAD ERROR: %s | THREAD %s" %
                            (_conErr, self.name))

        except Exception as e:
            stringhelpers.err("MEGA THREAD ERROR %s | THREAD %s" %
                              (e, self.name))
        except ConnectionError as errConn:
            stringhelpers.err("MEGA CONNECT API URL ERROR %s | THREAD %s" %
                              (_request.url, self.name))
Example #2
0
class MegaAction(threading.Thread):
    """ Thread instance each process mega """
    def __init__(self, name, data_action=None, dict_action={}):
        threading.Thread.__init__(self)
        self.name = name
        self.data_action = data_action
        self.requestURL = RequestURL()
        self.dict_action = dict_action
        self._request = RequestHelpers()
        self.data_command = None
        self.action_log = {'result': {'outputs': dict()}}
        self.fang = None
        self.log_output_file_name = None
        # sao the nay

    def run(self):

        self._request.url = self.requestURL.URL_GET_DEVICE_DETAIL % (
            self.data_action["test_device"])

        try:
            device = self._request.get().json()
            try:
                if device['status_code'] == 500:  #device not exist
                    stringhelpers.err(
                        "DEVICE ID %s NOT EXIST | THREAD %s" %
                        (self.data_action["test_device"], self.name))
            except:  #process fang test device by command
                host = device['ip_mgmt']
                port = int(device['port_mgmt'])
                username = device['username']
                password = device['password']
                device_type = device['os']
                method = device['method']  #ssh, telnet
                parameters = {
                    'device_type': device_type,
                    'host': host,
                    'protocol': method.lower(),
                    'username': username,
                    'password': password,
                    'port': port,
                    'timeout': 300
                }

                key_list_command = "%s|%s" % (device['vendor'], device['os'])
                key_rollback = 'rollback'
                self.log_output_file_name = "action_%s.log" % (
                    self.data_action['action_id'])
                self.action_log['result']['outputs'][key_list_command] = {}
                self.action_log['result']['outputs'][key_list_command][
                    'config'] = []
                self.action_log['result']['outputs'][key_list_command][
                    'rollback'] = []

                _list_action_commands = self.data_action['commands'][
                    key_list_command]['config']  #list action_command config
                _list_action_rollback = self.data_action['commands'][
                    key_list_command][
                        'rollback']  #list action_command rollback

                #--------------- list dict action command --------------------------------------------------------------
                _dict_list_command = dict()
                _dict_list_params = self.data_action['test_args']
                _array_step = []
                if len(_list_action_commands) > 0:
                    count = 0
                    for _command in _list_action_commands:
                        count = count + 1
                        _dict_list_command[str(count)] = _command
                        _array_step.append(str(count))  # save step command
                else:
                    pass
                #-------------------------------------------------------------------------------------------------------
                # --------------- list dict action command rollback---------------------------------------------------------------------
                _dict_list_command_rollback = dict()
                _dict_list_params_rollback = self.data_action['rollback_args']
                _array_step_rollback = []
                if len(_list_action_rollback) > 0:
                    count = 0
                    for _command in _list_action_rollback:
                        count = count + 1
                        _dict_list_command_rollback[str(count)] = _command
                        _array_step_rollback.append(
                            str(count))  # save step command rollback
                else:
                    pass
                    # -------------------------------------------------------------------------------------------------------

                fac = FactoryConnector(**parameters)
                '''#############################process command by dependency########################################'''
                if len(_array_step) > 0:

                    print(
                        "MEGA ACTION FANG DEVICE: host=%s, port=%s, devicetype=%s \n\n"
                        % (parameters['host'], parameters['port'],
                           parameters['device_type']))
                    self.fang = fac.execute_keep_alive(
                        loginfo=self.log_output_file_name)

                    compare_final_output = []
                    previous_final_output = []
                    for step in _array_step:
                        _command_running = _dict_list_command[step]
                        #if _command_running['dependency'] == '0':
                        command_id = _command_running.get('command_id', 0)
                        if command_id > 0:  #command_id > 0
                            dependency = int(_command_running['dependency'])
                            if dependency > 0:  # run need compare
                                dependStep = dependency
                                if (int(_command_running['condition']) == int(
                                        previous_final_output[dependStep -
                                                              1])):
                                    output_info = self.process_each_command(
                                        command_id, _dict_list_params)
                                    if output_info is not None:
                                        previous_final_output.append(
                                            output_info[str(
                                                command_id)]['final_output'])
                                        self.action_log['result']['outputs'][
                                            key_list_command]['config'].append(
                                                output_info)
                                        stringhelpers.info(
                                            "\nstep %s: %s" %
                                            (step, str(output_info)))
                                    else:
                                        previous_final_output.append(False)
                                else:
                                    stringhelpers.err(
                                        "MEGA ACTIONS STEP: %s NOT AVAIABLE WITH FINAL_OUTPUT OF STEP %d| THREAD %s"
                                        % (step, dependStep, self.name))
                                    previous_final_output.append(False)
                                    continue
                            else:  # dependency == 0
                                output_info = self.process_each_command(
                                    command_id, _dict_list_params)
                                if output_info is not None:
                                    previous_final_output.append(output_info[
                                        str(command_id)]['final_output'])

                                    self.action_log['result']['outputs'][
                                        key_list_command]['config'].append(
                                            output_info)
                                    stringhelpers.info(
                                        "\nstep %s: %s" %
                                        (step, str(output_info)))
                                    if int(step) > 1:
                                        if int(output_info[str(command_id)]
                                               ['final_output']) == int(
                                                   _command_running.get(
                                                       'condition', 0)):
                                            compare_final_output.append(True)
                                        else:
                                            self.action_log[
                                                'final_output'] = False
                                            compare_final_output = []
                                            break
                                else:
                                    previous_final_output.append(False)
                                    if int(step) > 1:
                                        self.action_log['final_output'] = False
                                        compare_final_output = []
                                        break
                        else:  #last command in actions check point
                            try:
                                dependency = int(
                                    _command_running['dependency'])
                                if dependency > 0 and int(step) > 0:
                                    continue
                                if (int(_command_running['condition']) == int(
                                        previous_final_output[dependency -
                                                              1])):
                                    compare_final_output.append(True)
                                else:
                                    compare_final_output.append(False)
                            except:
                                pass

                    #-------------- compare final_output for action ----------------------------------------------------
                    try:
                        if len(compare_final_output) > 0:
                            first_value = None
                            count = 0
                            for x in compare_final_output:
                                if count == 0:
                                    first_value = x
                                else:
                                    first_value = func_compare(
                                        '=', first_value, x)
                                count = count + 1
                            self.action_log['final_output'] = first_value
                        else:
                            if len(previous_final_output) > 0:
                                for x in previous_final_output:
                                    self.dict_state_result[
                                        'final_result_action'] = x
                            else:
                                self.dict_state_result[
                                    'final_result_action'] = False

                    except Exception as ex:
                        stringhelpers.err(
                            "MEGA ACTIONS THREAD ERROR COMAPRE ACTION FINAL-OUTPUT: %s | THREAD %s"
                            % (ex, self.name))
                    #---------------------------------------------------------------------------------------------------
                '''##################################################################################################'''
                '''#############################process command by rollback dependency########################################'''
                if len(_array_step_rollback) > 0:
                    print(
                        "MEGA ACTION ROLLBACK FANG DEVICE: host=%s, port=%s, devicetype=%s \n\n"
                        % (parameters['host'], parameters['port'],
                           parameters['device_type']))
                    #self.fang = fac.execute_keep_alive(loginfo=self.log_output_file_name)

                    compare_final_output = []
                    previous_final_output = []
                    for step in _array_step_rollback:
                        _command_running = _dict_list_command_rollback[step]
                        # if _command_running['dependency'] == '0':
                        command_id = _command_running.get('command_id', 0)
                        if command_id > 0:  # command_id > 0
                            dependency = int(_command_running['dependency'])
                            if dependency > 0:  # run need compare
                                dependStep = dependency
                                if (int(_command_running['condition']) == int(
                                        previous_final_output[dependStep -
                                                              1])):
                                    output_info = self.process_each_command(
                                        command_id, _dict_list_params_rollback)
                                    if output_info is not None:
                                        previous_final_output.append(
                                            output_info[str(
                                                command_id)]['final_output'])
                                        self.action_log['result']['outputs'][
                                            key_list_command][
                                                'rollback'].append(output_info)
                                        stringhelpers.info(
                                            "\nstep %s: %s" %
                                            (step, str(output_info)))
                                    else:
                                        previous_final_output.append(False)

                                else:
                                    stringhelpers.err(
                                        "MEGA ACTIONS ROLLBACK STEP: %s NOT AVAIABLE WITH FINAL_OUTPUT OF STEP %d| THREAD %s"
                                        % (step, dependStep, self.name))
                                    previous_final_output.append(False)
                                    continue
                            else:  # dependency == 0
                                output_info = self.process_each_command(
                                    command_id, _dict_list_params_rollback)
                                if output_info is not None:
                                    previous_final_output.append(output_info[
                                        str(command_id)]['final_output'])

                                    self.action_log['result']['outputs'][
                                        key_list_command]['rollback'].append(
                                            output_info)
                                    stringhelpers.info(
                                        "\nstep %s: %s" %
                                        (step, str(output_info)))
                                    if int(step) > 1:
                                        if int(output_info[str(command_id)]
                                               ['final_output']) == int(
                                                   _command_running.get(
                                                       'condition', 0)):
                                            compare_final_output.append(True)
                                        else:
                                            self.action_log[
                                                'final_output'] = False
                                            compare_final_output = []
                                            break
                                else:
                                    previous_final_output.append(False)
                                    if int(step) > 1:
                                        self.action_log['final_output'] = False
                                        compare_final_output = []
                                        break
                        else:  # last command in actions check point
                            try:  #catch error not command rollback
                                dependency = int(
                                    _command_running['dependency'])
                                if dependency > 0 and int(step) > 0:
                                    continue
                                if (int(_command_running['condition']) == int(
                                        previous_final_output[dependency -
                                                              1])):
                                    compare_final_output.append(True)
                                else:
                                    compare_final_output.append(False)
                            except:
                                print("DO NOT COMMAND ROLLBACK\n")

                    stringhelpers.err(
                        "MEGA ACTIONS THREAD ROLLBACK FINISHED: | THREAD %s" %
                        (self.name))

                    # -------------- compare final_output for action ----------------------------------------------------
                    try:
                        if len(compare_final_output) > 0:
                            first_value = None
                            count = 0
                            for x in compare_final_output:
                                if count == 0:
                                    first_value = x
                                else:
                                    first_value = func_compare(
                                        '=', first_value, x)
                                count = count + 1

                            self.action_log['final_output'] = first_value
                    except Exception as ex:
                        stringhelpers.err(
                            "MEGA ACTIONS THREAD ERROR ROLLBACK COMAPRE ACTION FINAL-OUTPUT: %s | THREAD %s"
                            % (ex, self.name))
                        # ---------------------------------------------------------------------------------------------------
                '''##################################################################################################'''

                # ------------------------------------ process save log action --------------------------------------

                self._request.url = self.requestURL.MEGA_URL_ACTIONLOG_GETBY_ACTIONID % (
                    self.data_action['action_id'])
                _request_action_log = self._request.get().json()
                if len(_request_action_log) > 0:  # update action log

                    self.action_log['action_id'] = self.data_action[
                        'action_id']
                    self.action_log['device_id'] = self.data_action[
                        "test_device"]
                    try:
                        self._request.url = self.requestURL.MEGA_URL_ACTIONLOG_UPDATE % (
                            _request_action_log[0]['log_id'])
                        self._request.params = self.action_log
                        self._request.put()
                        stringhelpers.info(
                            "MEGA ACTIONS THREAD INFO: %s | THREAD %s" %
                            ("UPDATE ACTIONS LOG SUCCESS", self.name))

                        # ---------------update mega_status to action------------------------------------------------
                        self._request.url = self.requestURL.MEGA_URL_ACTION_UPDATE % (
                            self.data_action['action_id'])
                        self._request.params = {'mega_status': 'tested'}
                        self._request.put()
                        key_action = 'action_%d' % (
                            self.data_action['action_id'])
                        del self.dict_action[key_action]
                        # --------------------------------------------------------------------------------------------
                    except ConnectionError as _conErr:
                        stringhelpers.info(
                            "MEGA ACTIONS THREAD ERROR: %s | THREAD %s" %
                            (_conErr, self.name))
                else:  # insert action log
                    self.action_log['action_id'] = self.data_action[
                        'action_id']
                    self.action_log['device_id'] = self.data_action[
                        "test_device"]

                    try:
                        self._request.url = self.requestURL.MEGA_URL_ACTIONLOG_CREATE
                        self._request.params = self.action_log
                        self._request.post()
                        stringhelpers.info(
                            "MEGA ACTIONS THREAD INFO: %s | THREAD %s" %
                            ("INSERT ACTIONS LOG SUCCESS", self.name))
                        # ---------------update mega_status to action------------------------------------------------
                        self._request.url = self.requestURL.MEGA_URL_ACTION_UPDATE % (
                            self.data_action['action_id'])
                        self._request.params = {'mega_status': 'tested'}
                        self._request.put()
                        key_action = 'action_%d' % (
                            self.data_action['action_id'])
                        del self.dict_action[key_action]
                        # --------------------------------------------------------------------------------------------
                    except ConnectionError as _conErr:
                        stringhelpers.err(
                            "MEGA ACTIONS THREAD ERROR: %s | THREAD %s" %
                            (_conErr, self.name))

                        # ---------------------------------------------------------------------------------------------------

                self.fang.remove_file_log(self.log_output_file_name)
                # stringhelpers.warn(str(self.action_log))
                self.fang.terminal()  # finished fang command

        except Exception as e:
            stringhelpers.err("MEGA ACTIONS THREAD ERROR %s | THREAD %s" %
                              (e, self.name))
        except ConnectionError as errConn:
            stringhelpers.err(
                "MEGA ACTIONS CONNECT API URL ERROR %s | THREAD %s" %
                (self._request.url, self.name))

    def process_each_command(self, command_id=0, _dict_list_params={}):
        '''process command contains params'''
        try:
            self._request.url = self.requestURL.MEGA_URL_COMMAND_DETAIL % (
                command_id)
            self.data_command = self._request.get().json()
            command = None

            ################### process args for command ##############################################
            if len(_dict_list_params.items()) > 0:
                for k, v in _dict_list_params.items():
                    if command is None:
                        command = self.data_command['command']
                        command = command.replace('@{%s}' % (k), v)
                    else:
                        command = command.replace('@{%s}' % (k), v)

            else:
                command = self.data_command['command']
            ###########################################################################################
            commands = [command]
            #stringhelpers.info_green(command)

            self.fang.execute_action_command(commands,
                                             blanks=2,
                                             error_reporting=True,
                                             timeout=30,
                                             terminal=False)
            #result_fang = self.fang.get_output()
            result_fang = self.fang.get_action_output(
                self.log_output_file_name)

            # processing parsing command follow output ###########################################
            command_type = self.data_command['type']
            action_command_log = self.parsing(command_type, command_id,
                                              result_fang, commands[0])
            return action_command_log
            ######################################################################################
        except Exception as e:
            stringhelpers.err(
                "MEGA ACTION PROCESS EACH COMMAND ERROR %s | THREAD %s" %
                (e, self.name))
            return None
        except ConnectionError as errConn:
            stringhelpers.err(
                "MEGA ACTION CONNECT API URL ERROR %s | THREAD %s" %
                (errConn, self.name))
            return None

    def parsing(self,
                command_type=0,
                command_id=0,
                result_fang=None,
                command_text=None):
        final_result_output = []
        output_result = dict()
        key = str(command_id)
        output_result[key] = dict()
        output_result[key]['output'] = []
        try:
            if command_type == 3:  # alway using for ironman
                if isinstance(self.data_command['output'], str):
                    data_command_output = json.loads(
                        self.data_command['output'])
                else:
                    data_command_output = self.data_command['output']
                for output_item in data_command_output:
                    start_by = output_item['start_by']
                    end_by = output_item['end_by']
                    if start_by == '' and end_by == '':
                        result = {
                            'value': '0',
                            'compare': True,
                            'command_type': str(command_type),
                            'command_id': str(command_id),
                            'command_text': command_text,
                            'console_log': result_fang
                        }
                        output_result[key]['output'].append(result)
                        #output_result[key]['console_log'] = result_fang
                        output_result[key]['final_output'] = True
                    else:
                        if end_by == 'end_row':
                            end_by = '\r\n'
                        _ret_value = stringhelpers.find_between(
                            result_fang, start_by, end_by).strip()

                        result = {
                            'value': _ret_value,
                            'compare': True,
                            'command_type': str(command_type),
                            'command_id': str(command_id),
                            'command_text': command_text,
                            'console_log': result_fang
                        }
                        output_result[key]['output'].append(result)
                        #output_result[key]['console_log'] = result_fang
                        output_result[key]['final_output'] = True
                return output_result
            elif command_type == 2 or command_type == 1:
                if isinstance(self.data_command['output'], str):
                    data_command_output = json.loads(
                        self.data_command['output'])
                else:
                    data_command_output = self.data_command['output']
                for output_item in data_command_output:
                    #if output_item['start_by'] is not '' and output_item['end_by'] is not '':
                    try:
                        start_by = output_item['start_by']
                        end_by = output_item['end_by']
                        standard_value = output_item['standard_value']
                        compare = output_item['compare']
                        if end_by == 'end_row':
                            end_by = '\r\n'
                        compare_value = stringhelpers.find_between(
                            result_fang, start_by, end_by)
                        if compare_value is not None or compare_value is not "":
                            compare_value = compare_value.strip()
                        if compare_value is '' or compare_value is None:
                            compare_value = result_fang
                        #if compare_value is not None or compare_value is not '':
                        if compare != "contains":
                            compare_value = int(compare_value)
                            standard_value = int(standard_value)
                        retvalue_compare = func_compare(
                            compare, standard_value, compare_value)
                        if compare_value == '':
                            result = {
                                'value': compare_value,
                                'compare': retvalue_compare,
                                'compare_operator': compare,
                                'command_type': str(command_type),
                                'command_id': str(command_id),
                                'command_text': command_text,
                                'console_log': result_fang
                            }  # if compare_value empty save raw data
                        else:
                            result = {
                                'value': compare_value,
                                'compare': retvalue_compare,
                                'compare_operator': compare,
                                'command_type': str(command_type),
                                'command_id': str(command_id),
                                'command_text': command_text,
                                'console_log': result_fang
                            }
                        output_result[key]['output'].append(result)
                        # save final result of each output
                        final_result_output.append(retvalue_compare)
                    except Exception as _error:
                        _strError = "MEGA ACTION PARSING COMMAND TYPE %d ERROR %s | THREAD %s" % (
                            command_type, _error, self.name)
                        result = {
                            'value': compare_value,
                            'compare': retvalue_compare,
                            'error': _strError,
                            'command_type': command_type,
                            'command_id': str(command_id),
                            'command_text': command_text,
                            'console_log': result_fang
                        }
                        output_result[key]['output'].append(result)
                        output_result[key]['parsing_status'] = 'ERROR'
                        stringhelpers.err(_strError)
                        final_result_output.append(False)

                # determine operator for final output
                try:
                    final_operator = []
                    for x in self.data_command['final_output']:
                        if x == '&' or x == '|':
                            final_operator.append(x)
                        else:
                            pass

                    # compare final output
                    number_operator = 0
                    first_value = None
                    for x in final_result_output:
                        if len(final_operator) > 0:
                            if number_operator == 0:
                                first_value = x
                            else:
                                first_value = func_compare(
                                    final_operator[number_operator - 1],
                                    first_value, x)
                            number_operator = number_operator + 1

                            if number_operator == len(final_result_output):
                                output_result[key][
                                    'final_output'] = first_value
                        else:
                            output_result[key]['final_output'] = x
                except Exception as _errorFinal:
                    if len(final_result_output) > 0:
                        output_result[key][
                            'final_output'] = final_result_output[0]
                    _strError = "\nMEGA ACTION CALCULATOR FINAL_OUTPUT  COMMAND_TYPE %d ERROR %s | THREAD %s" % (
                        command_type, _errorFinal, self.name)
                    stringhelpers.err(_strError)

                return output_result
        except Exception as _errorException:
            output_result[key]['parsing_status'] = 'ERROR'
            _strError = "MEGA ACTION PARSING COMMAND TYPE %d ERROR %s | THREAD %s" % (
                command_type, _errorException, self.name)
            stringhelpers.err(_strError)
            return output_result