Beispiel #1
0
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)
Beispiel #2
0
    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
Beispiel #3
0
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)
Beispiel #4
0
    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
Beispiel #5
0
    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