def connect(hosts, callback, credential, connection_port, forks=50): """Attempt to connect to hosts using the given credential. :param hosts: The collection of hosts to test connections :param callback: The Ansible callback to accept the results. :param credential: The credential used for connections :param connection_port: The connection port :param forks: number of forks to run with, default of 50 :returns: list of connected hosts credential tuples and list of host that failed connection """ inventory = construct_connect_inventory(hosts, credential, connection_port) inventory_file = write_inventory(inventory) extra_vars = {} playbook = {'name': 'discovery play', 'hosts': 'all', 'gather_facts': 'no', 'tasks': [{'action': {'module': 'raw', 'args': parse_kv('echo "Hello"')}}]} _handle_ssh_passphrase(credential) result = run_playbook(inventory_file, callback, playbook, extra_vars, forks=forks) if (result != TaskQueueManager.RUN_OK and result != TaskQueueManager.RUN_UNREACHABLE_HOSTS): raise _construct_error(result)
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 _connect(manager_interrupt, scan_task, hosts, result_store, credential, connection_port, use_paramiko=False, forks=50, exclude_hosts=None, base_ssh_executable=None, ssh_timeout=None): """Attempt to connect to hosts using the given credential. :param manager_interrupt: Signal used to communicate termination of scan :param scan_task: The scan task for this connection job :param hosts: The collection of hosts to test connections :param result_store: The result store to accept the results. :param credential: The credential used for connections :param connection_port: The connection port :param use_paramiko: use paramiko instead of ssh for connection :param forks: number of forks to run with, default of 50 :param exclude_hosts: Optional. Hosts to exclude from test connections :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: list of connected hosts credential tuples and list of host that failed connection """ cred_data = CredentialSerializer(credential).data 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_CONNECT_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_connect_inventory( hosts, cred_data, connection_port, forks, exclude_hosts, ssh_executable, ssh_args) inventory_file = write_inventory(inventory) extra_vars = {} _handle_ssh_passphrase(cred_data) error_msg = '' log_message = 'START CONNECT PROCESSING GROUPS'\ ' with use_paramiko: %s,' \ '%d forks and extra_vars=%s' % (use_paramiko, forks, extra_vars) scan_task.log_message(log_message) 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() group_ips = inventory.get('all').get('children').get(group_name).get( 'hosts').keys() group_ips = ["'%s'" % ip for ip in group_ips] group_ip_string = ', '.join(group_ips) log_message = 'START CONNECT PROCESSING GROUP %d of %d. '\ 'About to connect to hosts [%s]' % ( (idx + 1), len(group_names), group_ip_string) scan_task.log_message(log_message) callback = ConnectResultCallback(result_store, credential, scan_task.source) playbook = { 'name': 'attempt connection to systems', 'hosts': group_name, 'gather_facts': False, 'tasks': [{ 'action': { 'module': 'raw', 'args': parse_kv('echo "Hello"') } }] } 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) 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)
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): """Execute the host scan with the initialized source. :returns: An array of dictionaries of facts """ roles = [ 'check_dependencies', 'connection', 'cpu', 'date', 'dmi', 'etc_release', 'virt', 'virt_what', 'host_done' ] playbook = { 'name': 'scan systems for product fingerprint facts', 'hosts': 'all', 'gather_facts': False, 'strategy': 'free', 'roles': roles } connection_port = self.scan_task.source.port connected, failed, completed = self.obtain_discovery_data() forks = self.scan_job.options.max_concurrency num_completed = len(completed) num_remaining = len(connected) num_total = num_remaining + num_completed num_failed = len(failed) if num_total == 0: msg = 'Inventory provided no reachable hosts.' raise ScannerException(msg) logger.info('Inspect scan task started for %s.', self.scan_task) log_msg = '%d total connected, %d completed, %d'\ ' remaining, and make %d failed hosts' logger.info(log_msg, num_total, num_completed, num_remaining, num_failed) # Save counts self.scan_task.systems_count = len(connected) self.scan_task.systems_scanned = 0 self.scan_task.systems_failed = 0 self.scan_task.save() group_names, inventory = construct_scan_inventory( connected, connection_port, forks) inventory_file = write_inventory(inventory) error_msg = '' for group_name in group_names: callback = ResultCallback(scan_task=self.scan_task, inspect_results=self.inspect_results) playbook = { 'name': 'scan systems for product fingerprint facts', 'hosts': group_name, 'gather_facts': False, 'roles': roles } result = run_playbook(inventory_file, callback, playbook, forks=forks) if result != TaskQueueManager.RUN_OK: new_error_msg = _construct_error_msg(result) logger.error(new_error_msg) 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