def __call__(self, outputs, datetime=None) -> bool:
        command_out = outputs.get('stdout', None)
        time_output = outputs.get('stderr', None)
        rc = outputs.get('rc')
        try:
            exp_rc = self.options.get('rc', None)
            if exp_rc:
                if rc not in [int(_rc) for _rc in re.split(r'\s*\|\s*', exp_rc)]:
                    raise AssertionError(
                        f"Result return rc {rc} not match expected\nStdOut:\n\t{command_out}\nStdErr:\n\t{time_output}")
            data = time_output.split(',')
            row_dict = DotDict(**{k: v.replace('%', '') for (k, v) in [entry.split(':', 1) for entry in data]})
            for k in row_dict.keys():
                if k == 'Command':
                    continue
                row_dict.update({k: float(row_dict[k])})
            logger.info(f"Command: {row_dict.get('Command')} [Rc: {row_dict.get('Rc')}]")

            row = self.table.template(self.host_id, None, *tuple(list(row_dict.values()) + [-1]))
            du = model.data_factory(self.table, row, output=command_out, datetime=datetime)

            self.data_handler(du)
            return True
        except Exception as e:
            f, li = get_error_info()
            logger.error(f"{self.__class__.__name__}: {e}; File: {f}:{li}")
            raise RunnerError(f"{self}", f"{e}; File: {f}:{li}")
Beispiel #2
0
 def unregister(self, hook: AllowedHooks, kw):
     assert hook in AllowedHooks.get_hooks(
     ), f"Hook '{hook}' must be '{AllowedHooks.get_hooks()}'"
     h = [h for h in self._hooks.get(hook, []) if f"{h}" == h]
     assert len(h) == 0, f"Keyword '{kw}' not registered in '{hook}' scope"
     self._hooks.get(hook, []).remove(h[0])
     logger.info(f"Keyword '{kw}' successfully unregistered")
Beispiel #3
0
 def register(self, hook, kw, *args):
     if isinstance(hook, str):
         assert hook in AllowedHooks.get_hooks(
         ), f"Hook '{hook}' must be '{AllowedHooks.get_hooks()}'"
         hook = AllowedHooks[hook]
     self._hooks.setdefault(hook, []).append(Hook(kw, *args))
     logger.info(f"Keyword '{kw}' successfully registered")
 def resume_plugins(self):
     for name, plugin in self._active_plugins.items():
         try:
             plugin.start()
         except Exception as e:
             logger.warn(f"Plugin '{name}' resume error: {e}")
         else:
             logger.info(f"Plugin '{name}' resumed", also_console=True)
 def update(self, **plugin_modules):
     _registered_plugins = ''
     for plugin in plugin_modules.values():
         _registered_plugins += f'\t{plugin}\n'
         for table in plugin.affiliated_tables():
             _registered_plugins += f'\t\t{table.name}\n'
             TableSchemaService().register_table(table)
     super().update(**plugin_modules)
     logger.info(_registered_plugins)
 def _verify_folder_exist(self):
     with self.on_connection() as ssh:
         if self._start_in_folder.startswith('~'):
             _path = self._start_in_folder
             user_home = ssh.execute_command('echo $HOME').strip()
             _path = _path.replace('~', user_home)
             logger.info(f"Expand folder {self._start_in_folder} to {_path}")
             self._start_in_folder = _path
         ssh.directory_should_exist(os.path.expanduser(self._start_in_folder))
Beispiel #7
0
    def create_host_monitor(self, host, username, password, port=22, alias=None, certificate=None,
                            timeout=None):
        """
        Create basic host connection module used for trace host
        Last created connection handled as 'current'
        In case tracing required for one host only, alias can be ignored

        Connection arguments:
        - host: IP address, DNS name,
        - username
        - password
        - port          : 22 if omitted
        - certificate   : key file (.pem) Optional

        Extra arguments:
        - alias: 'username@host:port' if omitted
        - timeout       : connection & command timeout
        - log_to_db     : logger will store logs into db (table: log; Will cause db file size size growing)

        Examples:
        |  KW                       |  Host     | Username | Password       | Port  | Alias             | Comments              |
        |  Create host monitor   | 127.0.0.1 | any_user | any_password   |       |                   | Default port; No alias |
        |  Create host monitor   | 127.0.0.1 | any_user | any_password   | 24    |                   | Custom port; No alias |
        |  Create host monitor   | 127.0.0.1 | any_user | any_password   | 24    |  ${my_name}       | Custom port; Alias    |
        |  Create host monitor   | 127.0.0.1 | any_user | any_password   |       |  alias=${my_name} | Default port; Alias    |
        |  Create host monitor   | 127.0.0.1 | any_user | any_password   |       |  certificate=key_file.pem | Certificate file will be assigned  |

        === Auto start/stop periods ===
        By default keyword `Start period`, `Stop period` assigned for start/end test accordingly following by test name

        Can be overwritten by key value pairs
        | listener method=keyword name

        Where listener are one of:
        | start_suite
        | end_suite
        | start_test
        | end_test

        """

        module: Optional[HostModule] = None

        if not db.DataHandlerService().is_active:
            self._init()
        try:
            module = HostModule(db.PlugInService(), db.DataHandlerService().add_data_unit,
                                host, username, password, port, alias, certificate, timeout)
            module.start()
            logger.info(f"Connection {module.alias} ready to be monitored")
            _alias = self._modules.register(module, module.alias)
            self._start_period(alias=module.alias)
        except Exception as e:
            BuiltIn().fatal_error(f"Cannot start module '{module}; Reason: {e}")
        else:
            return module.alias
Beispiel #8
0
 def exit(self):
     if self._is_logged_in:
         self._ssh.switch_connection(repr(self))
         self._close_ssh_library_connection_from_thread()
         self._is_logged_in = False
         logger.info(
             f"Host '{self.id}::{self.host_alias}': Connection closed")
     else:
         logger.info(
             f"Host '{self.id}::{self.host_alias}': Connection close not required (not opened)"
         )
 def pause_plugins(self):
     for name, plugin in self._active_plugins.items():
         try:
             assert plugin is not None
             plugin.stop()
         except AssertionError:
             logger.info(f"Plugin '{name}' already stopped")
         except Exception as e:
             logger.warn(f"Plugin '{name}:{plugin}' pause error: {e}")
         else:
             logger.info(f"Plugin '{name}' paused", also_console=True)
 def is_continue_expected(self):
     if not self._evaluate_tolerance():
         self.parameters.event.set()
         logger.error(f"Stop requested due of critical error")
         return False
     if self.parameters.event.isSet():
         logger.info(f"Stop requested by external source")
         return False
     if self._internal_event.isSet():
         logger.info(f"Stop requested internally")
         return False
     return True
Beispiel #11
0
    def downgrade_plugin(self, *args, **kwargs):
        """
        Downgrade aTop plugin: remove processes for monitor during execution

        Arguments:
        - args:     process names
        - kwargs:   kept process names only
        """
        processes_to_unregister = list(args) + list(kwargs.keys())
        for process in processes_to_unregister:
            ProcessMonitorRegistry().deactivate(self.id, process)
        logger.info(
            f"Following processes removed from monitor: {', '.join(processes_to_unregister)}"
        )
 def stop(self):
     try:
         assert self.event
         self.event.set()
         logger.debug(f"Terminating {self.alias}")
         self._configuration.update({'event': None})
         active_plugins = list(self._active_plugins.keys())
         while len(active_plugins) > 0:
             plugin = active_plugins.pop(0)
             self.plugin_terminate(plugin)
         # self._control_th.join()
     except AssertionError:
         logger.warn(f"Session '{self.alias}' not started yet")
     else:
         logger.info(f"Session '{self.alias}' stopped")
Beispiel #13
0
    def upgrade_plugin(self, *args, **kwargs):
        """
        Upgrade aTop plugin: add processes for monitor during execution

        Arguments:
        - args:     process names

        Future features:
        - kwargs:   process names following boolean flag (Default: False; If True error will raise if process diappearing)
        """
        kwargs.update(**{arg: False for arg in args})
        for process, control in kwargs.items():
            ProcessMonitorRegistry().activate(self.id, process, control)
            logger.debug(f"Process '{process}' activated")
        logger.info(
            f"Start monitor following processes: {', '.join([f'{k}={v}' for k, v in kwargs.items()])}"
        )
Beispiel #14
0
    def login(self):
        host = self.parameters.host
        port = self.parameters.port
        username = self.parameters.username
        password = self.parameters.password
        certificate = self.parameters.certificate

        if len(self._session_errors) == 0:
            logger.info(f"Host '{self.host_alias}': Connecting")
        else:
            logger.warn(
                f"Host '{self.host_alias}': Restoring at {len(self._session_errors)} time"
            )

        self._ssh.open_connection(host, repr(self), port)

        start_ts = datetime.now()
        while True:
            try:
                if certificate:
                    logger.debug(
                        f"Host '{self.host_alias}': Login with user/certificate"
                    )
                    self._ssh.login_with_public_key(username, certificate, '')
                else:
                    logger.debug(
                        f"Host '{self.host_alias}': Login with user/password")
                    self._ssh.login(username, password)
            except paramiko.AuthenticationException:
                raise
            except Exception as e:
                logger.warn(
                    f"Host '{self.host_alias}': Connection failed; Reason: {e}"
                )
            else:
                self._is_logged_in = True
                logger.info(
                    f"Host '{self.host_alias}': Connection established")
                break
            finally:
                duration = (datetime.now() - start_ts).total_seconds()
                if duration >= self.parameters.timeout:
                    raise TimeoutError(
                        f"Cannot connect to '{self.host_alias}' during {self.parameters.timeout}s"
                    )
Beispiel #15
0
def print_plugins_table(plugins, show_tables=True, show_charts=True, title='Plugins/Tables/Charts'):
    _str = ''
    _title_line = "+- {title:59s} -----+".format(title=f"RemoteMonitorLibrary ({title}) Version: {VERSION}")
    _delimiter = "+------------------+---------------------------+--------------------+"
    _template = "| {col1:16s} | {col2:25s} | {col3:18s} |"
    _str += f"{_title_line}\n"
    for name, plugin in plugins.items():
        _str += _template.format(col1=name, col2=' ', col3='PlugIn') + '\n'
        if show_tables:
            _str += '\n'.join([_template.format(col1=' ', col2=t.name, col3='Table') + '\n'
                               for t in plugin.affiliated_tables()])
        if show_charts:
            for c in plugin.affiliated_charts():
                _str += _template.format(col1=' ', col2=c.title, col3='Chart') + '\n'
                for s in c.sections:
                    _str += _template.format(col1=' ', col2='  ' + s.replace(c.title, ''), col3='Section') + '\n'
        _str += _delimiter + '\n'

    logger.info(f"{_str.strip()}", also_console=True)
 def _run_command(self, context_object, flow: Enum):
     total_output = ''
     try:
         flow_values = getattr(self, flow.value)
         if len(flow_values) == 0:
             raise EmptyCommandSet()
         logger.debug(f"Iteration {flow.name} started")
         for i, cmd in enumerate(flow_values):
             run_status = cmd(context_object, **self.parameters)
             total_output += ('\n' if len(total_output) > 0 else ''
                              ) + "{} [Result: {}]".format(cmd, run_status)
             sleep(0.05)
     except EmptyCommandSet:
         logger.warn(f"Iteration {flow.name} ignored")
     except Exception as e:
         raise RunnerError(f"{self}", f"Command set '{flow.name}' failed",
                           e)
     else:
         logger.info(f"Iteration {flow.name} completed\n{total_output}")
 def plugin_terminate(self, plugin_name, **options):
     try:
         plugins_to_stop = self.get_plugin(plugin_name, **options)
         assert len(plugins_to_stop
                    ) > 0, f"Plugins '{plugin_name}' not matched in list"
         for plugin in plugins_to_stop:
             try:
                 plugin.stop(timeout=options.get('timeout', None))
                 assert plugin.iteration_counter > 0
             except AssertionError:
                 logger.warn(
                     f"Plugin '{plugin}' didn't got monitor data during execution"
                 )
     except (AssertionError, IndexError) as e:
         logger.info(
             f"Plugin '{plugin_name}' raised error: {type(e).__name__}: {e}"
         )
     else:
         logger.info(f"PlugIn '{plugin_name}' gracefully stopped",
                     also_console=True)
 def plugin_start(self, plugin_name, *args, **options):
     plugin_conf = self.config.clone()
     tail = plugin_conf.update(**options)
     plugin = self._plugin_registry.get(plugin_name, None)
     try:
         assert plugin, f"Plugin '{plugin_name}' not registered"
         plugin = plugin(plugin_conf.parameters,
                         self._data_handler,
                         host_id=self.host_id,
                         *args,
                         **tail)
     except Exception as e:
         raise RuntimeError(
             "Cannot create plugin instance '{}, args={}, parameters={}, options={}'"
             "\nError: {}".format(
                 plugin_name, ', '.join([f"{a}" for a in args]), ', '.join([
                     f"{k}={v}" for k, v in plugin_conf.parameters.items()
                 ]), ', '.join([f"{k}={v}" for k, v in tail.items()]), e))
     else:
         plugin.start()
         logger.info(f"\nPlugin {plugin_name} Started\n{plugin.info}",
                     also_console=True)
         self._active_plugins[plugin.id] = plugin
 def _persistent_worker(self):
     logger.info(f"\nPlugIn '{self}' started")
     while self.is_continue_expected:
         with self.on_connection() as context:
             self._run_command(context, self.flow_type.Setup)
             logger.info(f"Host {self}: Setup completed", also_console=True)
             while self.is_continue_expected:
                 try:
                     start_ts = datetime.now()
                     _timedelta = timedelta(seconds=self.parameters.interval) \
                         if self.parameters.interval is not None else timedelta(seconds=0)
                     next_ts = start_ts + _timedelta
                     self._run_command(context, self.flow_type.Command)
                     if self.parameters.interval is not None:
                         evaluate_duration(start_ts, next_ts,
                                           self.host_alias)
                     while datetime.now() < next_ts:
                         if not self.is_continue_expected:
                             break
                         sleep(0.5)
                 except RunnerError as e:
                     self._session_errors.append(e)
                     logger.warn(
                         "Error execute on: {name}; Reason: {error} (Attempt {real} from {allowed})"
                         .format(
                             name=str(self),
                             error=e,
                             real=len(self._session_errors),
                             allowed=self._fault_tolerance,
                         ))
                 else:
                     if len(self._session_errors):
                         logger.debug(
                             f"Host '{self}': Runtime errors occurred during tolerance period cleared"
                         )
                         self._session_errors.clear()
             sleep(2)
             self._run_command(context, self.flow_type.Teardown)
             logger.info(f"Host {self}: Teardown completed",
                         also_console=True)
     sleep(2)
     logger.info(f"PlugIn '{self}' stopped")
 def _non_persistent_worker(self):
     logger.info(f"\nPlugIn '{self}' started")
     with self.on_connection() as ssh:
         self._run_command(ssh, self.flow_type.Setup)
         logger.info(f"Host {self}: Setup completed", also_console=True)
     while self.is_continue_expected:
         with self.on_connection() as ssh:
             # try:
             start_ts = datetime.now()
             _timedelta = timedelta(seconds=self.parameters.interval) \
                 if self.parameters.interval is not None else timedelta(seconds=0)
             next_ts = start_ts + _timedelta
             self._run_command(ssh, self.flow_type.Command)
             if self.parameters.interval is not None:
                 evaluate_duration(start_ts, next_ts, self.host_alias)
         while datetime.now() < next_ts:
             if not self.is_continue_expected:
                 break
             sleep(0.5)
     with self.on_connection() as ssh:
         self._run_command(ssh, self.flow_type.Teardown)
         logger.info(f"Host {self}: Teardown completed", also_console=True)
     logger.info(f"PlugIn '{self}' stopped")
 def clear_all(self, closer_method='stop'):
     for conn in self._connections:
         logger.info(f"Clear {conn}", also_console=True)
         getattr(conn, closer_method)()
Beispiel #22
0
    | --variable RP_ENDPOINT:http://<your portal URI>:8080
    | --variable RP_LAUNCH:<Lunch name>
    | --variable RP_PROJECT:<Portal project name in lower case>
    | --variable ENV:TIRAMISU
    | --variable PLATFORM:CUSTOM_REMOTE_CHROME
    | --variable x_api_version:1.4.0
     
     For portal installation and further information look in [https://github.com/reportportal/agent-Python-RobotFramework|ReportPortal]
    
    """

try:
    from robotframework_reportportal import logger as portal_logger
    from robotframework_reportportal.exception import RobotServiceException
    PORTAL = True
    logger.info(f"RobotFramework portal available")
except (ImportError, ValueError):
    PORTAL = False


def upload_file_to_portal(link_title, file_path):
    if not PORTAL:
        return

    try:
        _, file_name = os.path.split(file_path)
        with open(file_path, 'rb') as file_reader:
            file_data = file_reader.read()
        portal_logger.info(link_title, attachment={
            'name': file_name,
            'data': file_data,
Beispiel #23
0
 def stop_monitor_plugin(self, plugin_name, alias=None, **options):
     monitor = self._modules.get_connection(alias)
     monitor.plugin_terminate(plugin_name, **options)
     logger.info(f"PlugIn '{plugin_name}' stopped on {monitor.alias}", also_console=True)