Example #1
0
    def start(self):
        '''
        Start the daemon subprocess
        '''
        # Late import
        import salt.utils.nb_popen as nb_popen
        log.info('[%s][%s] Starting DAEMON in CWD: %s', self.log_prefix,
                 self.cli_display_name, self.cwd)
        proc_args = [self.get_script_path(self.cli_script_name)
                     ] + self.get_base_script_args() + self.get_script_args()

        if sys.platform.startswith('win'):
            # Windows needs the python executable to come first
            proc_args.insert(0, sys.executable)

        log.info('[%s][%s] Running \'%s\'...', self.log_prefix,
                 self.cli_display_name, ' '.join(proc_args))

        self._terminal = nb_popen.NonBlockingPopen(proc_args,
                                                   env=self.environ,
                                                   cwd=self.cwd)
        process_output_thread = threading.Thread(target=self._process_output)
        process_output_thread.daemon = True
        self._running.set()
        process_output_thread.start()
        self._children = collect_child_processes(self._terminal.pid)
        atexit.register(self.terminate)
        return True
Example #2
0
    def init_terminal(self, cmdline, **kwargs):
        '''
        Instantiate a terminal with the passed cmdline and kwargs and return it.

        Additionaly, it sets a reference to it in self._terminal and also collects
        an initial listing of child processes which will be used when terminating the
        terminal
        '''
        # Late import
        import salt.utils.nb_popen as nb_popen
        self._terminal = nb_popen.NonBlockingPopen(cmdline, **kwargs)
        self._children = collect_child_processes(self._terminal.pid)
        atexit.register(self.terminate)
        return self._terminal
Example #3
0
    def run(self, tags=(), timeout=10):  # pylint: disable=arguments-differ
        '''
        Run the given command synchronously
        '''
        # Late import
        import salt.ext.six as six
        import salt.utils.nb_popen as nb_popen
        exitcode = 0
        timeout_expire = time.time() + timeout
        environ = self.environ.copy()
        environ['PYTEST_LOG_PREFIX'] = '[{0}][EventListen] '.format(
            self.log_prefix)
        proc_args = [self.get_script_path(self.cli_script_name)
                     ] + self.get_base_script_args() + self.get_script_args()

        if sys.platform.startswith('win'):
            # Windows needs the python executable to come first
            proc_args.insert(0, sys.executable)

        log.info('[%s][%s] Running \'%s\' in CWD: %s...', self.log_prefix,
                 self.cli_display_name, ' '.join(proc_args), self.cwd)

        to_match_events = set(tags)
        matched_events = {}

        terminal = nb_popen.NonBlockingPopen(proc_args,
                                             cwd=self.cwd,
                                             env=environ,
                                             stdout=subprocess.PIPE,
                                             stderr=subprocess.PIPE)

        # Consume the output
        stdout = six.b('')
        stderr = six.b('')

        process_output = six.b('')
        events_processed = 0
        try:
            while True:
                if terminal.stdout is not None:
                    try:
                        out = terminal.recv(4096)
                    except IOError:
                        out = six.b('')
                    if out:
                        stdout += out
                        process_output += out
                if terminal.stderr is not None:
                    try:
                        err = terminal.recv_err(4096)
                    except IOError:
                        err = ''
                    if err:
                        stderr += err
                if out is None and err is None:
                    if to_match_events:
                        exitcode = 1
                    log.warning(
                        '[%s][%s] Premature exit?! Failed to find all of the required event tags. '
                        'Total events processed: %s', self.log_prefix,
                        self.cli_display_name, events_processed)
                    break

                if process_output:
                    lines = process_output.split(b'}\n')
                    if lines[-1] != b'':
                        process_output = lines.pop()
                    else:
                        process_output = six.b('')
                        lines.pop()
                    for line in lines:
                        match = self.EVENT_MATCH_RE.match(
                            line.decode(__salt_system_encoding__))  # pylint: disable=undefined-variable
                        if match:
                            events_processed += 1
                            tag, data = match.groups()
                            if tag in to_match_events:
                                matched_events[tag] = json.loads(data + '}')
                                to_match_events.remove(tag)

                    log.info('[%s][%s] Events processed so far: %d',
                             self.log_prefix, self.cli_display_name,
                             events_processed)

                if not to_match_events:
                    log.debug('[%s][%s] ALL EVENT TAGS FOUND!!!',
                              self.log_prefix, self.cli_display_name)
                    break

                if timeout_expire < time.time():
                    log.warning(
                        '[%s][%s] Failed to find all of the required event tags. Total events processed: %s',
                        self.log_prefix, self.cli_display_name,
                        events_processed)
                    exitcode = 1
                    break
        except (SystemExit, KeyboardInterrupt):
            pass
        finally:
            if terminal.stdout:
                terminal.stdout.close()
            if terminal.stderr:
                terminal.stderr.close()

        terminate_process(pid=terminal.pid,
                          kill_children=True,
                          slow_stop=self.slow_stop)

        if six.PY3:
            # pylint: disable=undefined-variable
            stdout = stdout.decode(__salt_system_encoding__)
            stderr = stderr.decode(__salt_system_encoding__)
            # pylint: enable=undefined-variable

        json_out = {'matched': matched_events, 'unmatched': to_match_events}
        return ShellResult(exitcode, stdout, stderr, json_out)
Example #4
0
    def run(self, *args, **kwargs):
        '''
        Run the given command synchronously
        '''
        # Late import
        import salt.ext.six as six
        import salt.utils.nb_popen as nb_popen
        timeout = kwargs.get('timeout', self.DEFAULT_TIMEOUT)
        if 'fail_hard' in kwargs:
            # Explicit fail_hard passed
            fail_hard = kwargs.pop('fail_hard')
        else:
            # Get the value of the _salt_fail_hard fixture
            try:
                fail_hard = self.request.getfixturevalue('_salt_fail_hard')
            except AttributeError:
                fail_hard = self.request.getfuncargvalue('_salt_fail_hard')
        if fail_hard is True:
            fail_method = pytest.fail
        else:
            fail_method = pytest.xfail
        log.info('The fail hard setting for %s is: %s', self.cli_script_name,
                 fail_hard)
        minion_tgt = self.get_minion_tgt(**kwargs)
        timeout_expire = time.time() + kwargs.pop('timeout',
                                                  self.DEFAULT_TIMEOUT)
        environ = self.environ.copy()
        environ['PYTEST_LOG_PREFIX'] = '[{0}] '.format(self.log_prefix)
        proc_args = [self.get_script_path(self.cli_script_name)
                     ] + self.get_base_script_args() + self.get_script_args()

        if sys.platform.startswith('win'):
            # Windows needs the python executable to come first
            proc_args.insert(0, sys.executable)

        if minion_tgt is not None:
            proc_args.append(minion_tgt)
        proc_args.extend(list(args))
        for key in kwargs:
            proc_args.append('{0}={1}'.format(key, kwargs[key]))

        log.info('[%s][%s] Running \'%s\' in CWD: %s ...', self.log_prefix,
                 self.cli_display_name, ' '.join(proc_args), self.cwd)

        terminal = nb_popen.NonBlockingPopen(proc_args,
                                             cwd=self.cwd,
                                             env=environ,
                                             stdout=subprocess.PIPE,
                                             stderr=subprocess.PIPE)
        # Consume the output
        stdout = six.b('')
        stderr = six.b('')

        try:
            while True:
                # We're not actually interested in processing the output, just consume it
                if terminal.stdout is not None:
                    try:
                        out = terminal.recv(4096)
                    except IOError:
                        out = six.b('')
                    if out:
                        stdout += out
                if terminal.stderr is not None:
                    try:
                        err = terminal.recv_err(4096)
                    except IOError:
                        err = ''
                    if err:
                        stderr += err
                if out is None and err is None:
                    break
                if timeout_expire < time.time():
                    terminate_process(pid=terminal.pid,
                                      kill_children=True,
                                      slow_stop=self.slow_stop)
                    fail_method(
                        '[{0}][{1}] Failed to run: args: {2!r}; kwargs: {3!r}; Error: {4}'
                        .format(
                            self.log_prefix, self.cli_display_name, args,
                            kwargs,
                            '[{0}][{1}] Timed out after {2} seconds!'.format(
                                self.log_prefix, self.cli_display_name,
                                timeout)))
        except (SystemExit, KeyboardInterrupt):
            pass
        finally:
            if terminal.stdout:
                terminal.stdout.close()
            if terminal.stderr:
                terminal.stderr.close()

        terminate_process(pid=terminal.pid,
                          kill_children=True,
                          slow_stop=self.slow_stop)

        if six.PY3:
            # pylint: disable=undefined-variable
            stdout = stdout.decode(__salt_system_encoding__)
            stderr = stderr.decode(__salt_system_encoding__)
            # pylint: enable=undefined-variable

        exitcode = terminal.returncode
        stdout, stderr, json_out = self.process_output(minion_tgt, stdout,
                                                       stderr)
        return ShellResult(exitcode, stdout, stderr, json_out)