def test_populate_callback(self): """Test the population of the callback object for inspect scan.""" callback = InspectResultCallback(scan_task=self.scan_task) host = Mock() host.name = '1.2.3.4' task = Mock(args={'_raw_params': 'command line'}) result = Mock(_host=host, _result={'rc': 3}, _task=task) callback.v2_runner_on_unreachable(result)
def test_populate_callback(self): """Test the population of the callback object for inspect scan.""" callback = InspectResultCallback( scan_task=self.inspect_scan_task, inspect_results=self.inspect_results) host = Mock() host.name = '1.2.3.4' result = Mock(_host=host, _results={'rc': 3}) callback.v2_runner_on_unreachable(result)
def test_populate_callback(self): """Test the population of the callback object for inspect scan.""" callback = InspectResultCallback(scan_task=self.scan_task, manager_interrupt=self.interrupt) # cleaned unused variabled from event_dict event_dict = { 'runner_ident': 'f2100bac-7d64-43d2-8e6a-022c6f5104ac', 'event': 'runner_on_unreachable', 'event_data': { 'play': 'group_0', 'play_pattern': ' group_0 ', 'task': 'test if user has sudo cmd', 'task_action': 'raw', 'role': 'check_dependencies', 'host': '1.2.3.4', 'res': { 'unreachable': True, 'msg': 'Failed to connect to the host via ssh: ', 'changed': False }, 'pid': 2210 } } callback.task_on_unreachable(event_dict)
def _inspect_scan(self, manager_interrupt, connected, roles=DEFAULT_ROLES, base_ssh_executable=None, ssh_timeout=None): """Execute the host scan with the initialized source. :param manager_interrupt: Signal used to communicate termination of scan :param connected: list of (host, credential) pairs to inspect :param roles: list of roles to execute :param base_ssh_executable: ssh executable, or None for 'ssh'. Will be wrapped with a timeout before being passed to Ansible. :param ssh_timeout: string in the format of the 'timeout' command. Timeout for individual tasks. :returns: An array of dictionaries of facts """ connection_port = self.scan_task.source.port if self.scan_task.source.options is not None: use_paramiko = self.scan_task.source.options.use_paramiko else: use_paramiko = None if self.scan_job.options is not None: forks = self.scan_job.options.max_concurrency extra_vars = self.scan_job.options.get_extra_vars() else: forks = ScanOptions.get_default_forks() extra_vars = ScanOptions.get_default_extra_vars() if extra_vars.get(ScanOptions.EXT_PRODUCT_SEARCH_DIRS) is None: extra_vars[ScanOptions.EXT_PRODUCT_SEARCH_DIRS] = \ ' '.join(DEFAULT_SCAN_DIRS) ssh_executable = os.path.abspath( os.path.join(os.path.dirname(__file__), '../../../bin/timeout_ssh')) base_ssh_executable = base_ssh_executable or 'ssh' ssh_timeout = ssh_timeout or settings.QPC_SSH_INSPECT_TIMEOUT # pylint: disable=line-too-long # the ssh arg is required for become-pass because # ansible checks for an exact string match of ssh # anywhere in the command array # See https://github.com/ansible/ansible/blob/stable-2.3/lib/ansible/plugins/connection/ssh.py#L490-L500 # noqa # timeout_ssh will remove the ssh argument before running the command ssh_args = [ '--executable=' + base_ssh_executable, '--timeout=' + ssh_timeout, 'ssh' ] group_names, inventory = _construct_scan_inventory( connected, connection_port, forks, ssh_executable=ssh_executable, ssh_args=ssh_args) inventory_file = write_inventory(inventory) error_msg = '' log_message = 'START INSPECT PROCESSING GROUPS'\ ' with use_paramiko: %s, '\ '%d forks and extra_vars=%s' % (use_paramiko, forks, extra_vars) self.scan_task.log_message(log_message) scan_result = ScanTask.COMPLETED scan_message = 'success' for idx, group_name in enumerate(group_names): if manager_interrupt.value == ScanJob.JOB_TERMINATE_CANCEL: raise NetworkCancelException() if manager_interrupt.value == ScanJob.JOB_TERMINATE_PAUSE: raise NetworkPauseException() log_message = 'START INSPECT PROCESSING GROUP %d of %d' % ( (idx + 1), len(group_names)) self.scan_task.log_message(log_message) callback =\ InspectResultCallback( scan_task=self.scan_task) playbook = { 'name': 'scan systems for product fingerprint facts', 'hosts': group_name, 'gather_facts': False, 'roles': roles } result = run_playbook(inventory_file, callback, playbook, extra_vars, use_paramiko, forks=forks) if result != TaskQueueManager.RUN_OK: new_error_msg = _construct_error_msg(result) callback.finalize_failed_hosts() if result not in [ TaskQueueManager.RUN_UNREACHABLE_HOSTS, TaskQueueManager.RUN_FAILED_HOSTS ]: error_msg += '{}\n'.format(new_error_msg) if error_msg != '': raise AnsibleError(error_msg) return scan_message, scan_result
def _inspect_scan(self, connected, roles=DEFAULT_ROLES, base_ssh_executable=None, ssh_timeout=None): """Execute the host scan with the initialized source. :param connected: list of (host, credential) pairs to inspect :param roles: list of roles to execute :param base_ssh_executable: ssh executable, or None for 'ssh'. Will be wrapped with a timeout before being passed to Ansible. :param ssh_timeout: string in the format of the 'timeout' command. Timeout for individual tasks. :returns: An array of dictionaries of facts """ playbook = { 'name': 'scan systems for product fingerprint facts', 'hosts': 'all', 'gather_facts': False, 'strategy': 'free', 'roles': roles } connection_port = self.scan_task.source.port extra_vars = self.scan_job.get_extra_vars() forks = self.scan_job.options.max_concurrency ssh_executable = os.path.abspath( os.path.join(os.path.dirname(__file__), '../../../bin/timeout_ssh')) base_ssh_executable = base_ssh_executable or 'ssh' ssh_timeout = ssh_timeout or DEFAULT_TIMEOUT ssh_args = [ '--executable=' + base_ssh_executable, '--timeout=' + ssh_timeout ] group_names, inventory = _construct_scan_inventory( connected, connection_port, forks, ssh_executable=ssh_executable, ssh_args=ssh_args) inventory_file = write_inventory(inventory) error_msg = '' log_message = 'START PROCESSING GROUPS with concurrent of %d' % forks self.scan_task.log_message(log_message) scan_result = ScanTask.COMPLETED scan_message = 'success' for idx, group_name in enumerate(group_names): log_message = 'START PROCESSING GROUP %d of %d' % ( (idx + 1), len(group_names)) self.scan_task.log_message(log_message) callback =\ InspectResultCallback( scan_task=self.scan_task, inspect_results=self.scan_job.inspection_results) playbook = { 'name': 'scan systems for product fingerprint facts', 'hosts': group_name, 'gather_facts': False, 'roles': roles } result = run_playbook(inventory_file, callback, playbook, extra_vars, forks=forks) if result != TaskQueueManager.RUN_OK: new_error_msg = _construct_error_msg(result) scan_message = new_error_msg scan_result = ScanTask.FAILED callback.finalize_failed_hosts() if result != TaskQueueManager.RUN_UNREACHABLE_HOSTS and \ result != TaskQueueManager.RUN_FAILED_HOSTS: error_msg += '{}\n'.format(new_error_msg) if error_msg != '': raise AnsibleError(error_msg) # Clear this cache since new results are available self.facts = None return scan_message, scan_result
def _inspect_scan(self, manager_interrupt, connected, base_ssh_executable=None, ssh_timeout=None): """Execute the host scan with the initialized source. :param manager_interrupt: Signal used to communicate termination of scan :param connected: list of (host, credential) pairs to inspect :param roles: list of roles to execute :param base_ssh_executable: ssh executable, or None for 'ssh'. Will be wrapped with a timeout before being passed to Ansible. :param ssh_timeout: string in the format of the 'timeout' command. Timeout for individual tasks. :returns: An array of dictionaries of facts Note: base_ssh_executable & ssh_timeout are parameters that are only used for testing. """ # pylint: disable=too-many-locals,too-many-arguments # pylint: disable=too-many-branches,too-many-statements connection_port = self.scan_task.source.port if self.scan_task.source.options is not None: use_paramiko = self.scan_task.source.options.use_paramiko else: use_paramiko = False if self.scan_job.options is not None: forks = self.scan_job.options.max_concurrency extra_vars = self.scan_job.options.get_extra_vars() else: forks = ScanOptions.get_default_forks() extra_vars = ScanOptions.get_default_extra_vars() if extra_vars.get(ScanOptions.EXT_PRODUCT_SEARCH_DIRS) is None: extra_vars[ScanOptions.EXT_PRODUCT_SEARCH_DIRS] = \ ' '.join(DEFAULT_SCAN_DIRS) ssh_executable = os.path.abspath( os.path.join(os.path.dirname(__file__), '../../../bin/timeout_ssh')) base_ssh_executable = base_ssh_executable or 'ssh' ssh_timeout = ssh_timeout or settings.QPC_SSH_INSPECT_TIMEOUT # pylint: disable=line-too-long # the ssh arg is required for become-pass because # ansible checks for an exact string match of ssh # anywhere in the command array # See https://github.com/ansible/ansible/blob/stable-2.3/lib/ansible/plugins/connection/ssh.py#L490-L500 # noqa # timeout_ssh will remove the ssh argument before running the command ssh_args = [ '--executable=' + base_ssh_executable, '--timeout=' + ssh_timeout, 'ssh' ] group_names, inventory = _construct_scan_inventory( connected, connection_port, forks, ssh_executable=ssh_executable, ssh_args=ssh_args) inventory_file = write_to_yaml(inventory) error_msg = None log_message = 'START INSPECT PROCESSING GROUPS'\ ' with use_paramiko: %s, '\ '%d forks and extra_vars=%s' % (use_paramiko, forks, extra_vars) self.scan_task.log_message(log_message) scan_result = ScanTask.COMPLETED # Build Ansible Runner Dependencies for idx, group_name in enumerate(group_names): check_manager_interrupt(manager_interrupt.value) log_message = 'START INSPECT PROCESSING GROUP %d of %d' % ( (idx + 1), len(group_names)) self.scan_task.log_message(log_message) call = InspectResultCallback(self.scan_task, manager_interrupt) # Build Ansible Runner Parameters runner_settings = { 'idle_timeout': int(settings.NETWORK_INSPECT_JOB_TIMEOUT), 'job_timeout': int(settings.NETWORK_INSPECT_JOB_TIMEOUT), 'pexpect_timeout': 5 } playbook_path = os.path.join(settings.BASE_DIR, 'scanner/network/runner/inspect.yml') extra_vars['variable_host'] = group_name cmdline_list = [] vault_file_path = '--vault-password-file=%s' % ( settings.DJANGO_SECRET_PATH) cmdline_list.append(vault_file_path) forks_cmd = '--forks=%s' % (forks) cmdline_list.append(forks_cmd) if use_paramiko: cmdline_list.append('--connection=paramiko') all_commands = ' '.join(cmdline_list) if int(settings.ANSIBLE_LOG_LEVEL) == 0: quiet_bool = True verbosity_lvl = 0 else: quiet_bool = False verbosity_lvl = int(settings.ANSIBLE_LOG_LEVEL) try: runner_obj = ansible_runner.run( quiet=quiet_bool, settings=runner_settings, inventory=inventory_file, extravars=extra_vars, event_handler=call.event_callback, cancel_callback=call.cancel_callback, playbook=playbook_path, cmdline=all_commands, verbosity=verbosity_lvl) except Exception as error: error_msg = error raise AnsibleRunnerException(error_msg) final_status = runner_obj.status if final_status != 'successful': if final_status == 'canceled': interrupt = manager_interrupt.value if interrupt == ScanJob.JOB_TERMINATE_CANCEL: msg = log_messages.NETWORK_PLAYBOOK_STOPPED % ( 'INSPECT', 'canceled') else: msg = log_messages.NETWORK_PLAYBOOK_STOPPED % ( 'INSPECT', 'paused') self.scan_task.log_message(msg) check_manager_interrupt(interrupt) if final_status not in ['unreachable', 'failed']: if final_status == 'timeout': error_msg = log_messages.NETWORK_TIMEOUT_ERR else: error_msg = log_messages.NETWORK_UNKNOWN_ERR scan_result = ScanTask.FAILED call.finalize_failed_hosts() return error_msg, scan_result