Пример #1
0
 def test_start_should_log_args(self, monkeypatch):
     monkeypatch.setattr(cmdutils, "command_log_line", mock.MagicMock())
     monkeypatch.setattr(commands, "log", fakelib.FakeLogger())
     cmdutils.command_log_line.return_value = "zorro"
     args = ["true"]
     commands.start(args)
     assert (logging.DEBUG, "zorro", {}) in commands.log.messages
Пример #2
0
 def test_out(self):
     p = commands.start(
         ["echo", "-n", "out"],
         stdout=subprocess.PIPE)
     out, err = p.communicate()
     assert out == b"out"
     assert err is None
Пример #3
0
 def test_in_err(self):
     p = commands.start(
         ["sh", "-c", "cat >&2"],
         stdin=subprocess.PIPE,
         stderr=subprocess.PIPE)
     out, err = p.communicate(b"data")
     assert out is None
     assert err == b"data"
Пример #4
0
 def test_in_out(self):
     p = commands.start(
         ["cat"],
         stdin=subprocess.PIPE,
         stdout=subprocess.PIPE)
     out, err = p.communicate(b"data")
     assert out == b"data"
     assert err is None
Пример #5
0
 def test_out_err(self):
     p = commands.start(
         ["sh", "-c", "echo -n out >&1; echo -n err >&2"],
         stdout=subprocess.PIPE,
         stderr=subprocess.PIPE)
     out, err = p.communicate()
     assert out == b"out"
     assert err == b"err"
Пример #6
0
 def test_start_nonexisting(self):
     with pytest.raises(OSError):
         args = ["doesn't exist"]
         commands.start(args, reset_cpu_affinity=False)
Пример #7
0
 def test_out(self):
     p = commands.start(["echo", "-n", "out"], stdout=subprocess.PIPE)
     out, err = p.communicate()
     assert out == b"out"
     assert err is None
Пример #8
0
 def test_false(self):
     p = commands.start(["false"])
     out, err = p.communicate()
     assert p.returncode == 1
     assert out is None
     assert err is None
Пример #9
0
 def test_false(self):
     p = commands.start(["false"])
     out, err = p.communicate()
     assert p.returncode == 1
     assert out is None
     assert err is None
Пример #10
0
 def test_sudo_terminate(self):
     p = commands.start(["sleep", "1"], sudo=True)
     p.terminate()
     assert p.wait() == -signal.SIGTERM
Пример #11
0
def run_logging(args, log_tag=None):
    """
    Start a command storing its stdout/stderr into a file, communicate with it,
    and wait until the command terminates. Ensures that the command is killed
    if an unexpected error is raised. Note that since the stdout/stderr is
    redirected to the file it is not piped to VDSM.

    args are logged when command starts, and are included in the exception if a
    command has failed. If args contain sensitive information that should not
    be logged, such as passwords, they must be wrapped with ProtectedPassword.
    While access to the directory with log files is restricted caution should
    be taken when logging commands. Avoid storing output of commands that may
    leak passwords or other sensitive information.

    The child process stdout and stderr are always buffered. If you have
    special needs, such as running the command without buffering stdout, or
    create a pipeline of several commands, use the lower level start()
    function.

    If log_tag is not used the log file name is
    'virtcmd-<command>-<datetime>-<random_string>.log'. If
    log_tag is used the format is
    'virtcmd-<command>-<log_tag>-<datetime>-<random_string>.log'.

    The granularity of <datetime> part of the file name is one second. To
    minimize file collision there is a random string of characters appended to
    the name.

    Arguments:
        args (list): Command arguments
        log_tag (str): Optional string to be included in log file name to
            better distinguish the log files and avoid potential name
            collisions. This could be for example VM ID.

    Returns:
        Path to the log file.

    Raises:
        LoggingError if the command terminated with a non-zero exit code.
        TerminatingFailure if command could not be terminated.
    """
    stdout = subprocess.DEVNULL
    stderr = subprocess.DEVNULL
    cmd_log_file = None

    timestamp = time.strftime('%Y%m%dT%H%M%S')
    command = os.path.basename(str(args[0]))
    log_tag = '' if log_tag is None else '-%s' % log_tag
    suffix = ''.join(random.choice(string.ascii_lowercase) for _ in range(4))
    cmd_log_path = os.path.join(
        _COMMANDS_LOG_DIR,
        'virtcmd-%s%s-%s-%s.log' % (command, log_tag, timestamp, suffix))
    try:
        os.makedirs(_COMMANDS_LOG_DIR, mode=0o750, exist_ok=True)
        cmd_log_file = os.open(cmd_log_path,
                               os.O_WRONLY | os.O_CREAT | os.O_APPEND,
                               mode=0o640)
    except OSError:
        log.exception('Failed to open log file')
        cmd_log_path = None
    else:
        stdout = cmd_log_file
        stderr = cmd_log_file
        log.debug('Running command %r with logs in %s', args, cmd_log_path)

    p = start(args, stdin=subprocess.PIPE, stdout=stdout, stderr=stderr)

    with terminating(p):
        p.communicate()

    log.debug(cmdutils.retcode_log_line(p.returncode))

    if cmd_log_file is not None:
        os.close(cmd_log_file)
    if p.returncode != 0:
        raise LoggingError(args, p.returncode, cmd_log_path)

    return cmd_log_path
Пример #12
0
 def testResetAffinityByDefault(self):
     proc = commands.start((EXT_SLEEP, '30s'))
     try:
         self.assertEqual(taskset.get(proc.pid), taskset.get(os.getpid()))
     finally:
         proc.kill()
Пример #13
0
 def test_child_terminated(self):
     p = commands.start(["sleep", "1"])
     commands.run(["kill", "-%d" % signal.SIGTERM, "%d" % p.pid])
     assert p.wait() == -signal.SIGTERM
Пример #14
0
 def test_start_nonexisting(self):
     with pytest.raises(OSError):
         args = ["doesn't exist"]
         commands.start(args, reset_cpu_affinity=False)
Пример #15
0
 def test_start_cat_out(self):
     p = commands.start(["cat"], stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE)
     out, err = p.communicate(b"data")
     assert out == b"data"
     assert err == b""
Пример #16
0
 def test_child_terminated(self):
     p = commands.start(["sleep", "1"])
     commands.run(["kill", "-%d" % signal.SIGTERM, "%d" % p.pid])
     assert p.wait() == -signal.SIGTERM
Пример #17
0
def _runHooksDir(data,
                 dir,
                 vmconf={},
                 raiseError=True,
                 errors=None,
                 params={},
                 hookType=_DOMXML_HOOK):
    if errors is None:
        errors = []

    scripts = _scriptsPerDir(dir)
    scripts.sort()

    if not scripts:
        return data

    data_fd, data_filename = tempfile.mkstemp()
    try:
        if hookType == _DOMXML_HOOK:
            os.write(data_fd, data.encode('utf-8') if data else b'')
        elif hookType == _JSON_HOOK:
            os.write(data_fd, json.dumps(data).encode('utf-8'))
        os.close(data_fd)

        scriptenv = os.environ.copy()

        # Update the environment using params and custom configuration
        env_update = [
            six.iteritems(params),
            six.iteritems(vmconf.get('custom', {}))
        ]

        # Encode custom properties to UTF-8 and save them to scriptenv
        # Pass str objects (byte-strings) without any conversion
        for k, v in itertools.chain(*env_update):
            try:
                if isinstance(v, six.text_type):
                    scriptenv[k] = v.encode('utf-8')
                else:
                    scriptenv[k] = v
            except UnicodeEncodeError:
                pass

        if vmconf.get('vmId'):
            scriptenv['vmId'] = vmconf.get('vmId')
        ppath = scriptenv.get('PYTHONPATH', '')
        hook = os.path.dirname(pkgutil.get_loader('vdsm.hook').get_filename())
        scriptenv['PYTHONPATH'] = ':'.join(ppath.split(':') + [hook])
        if hookType == _DOMXML_HOOK:
            scriptenv['_hook_domxml'] = data_filename
        elif hookType == _JSON_HOOK:
            scriptenv['_hook_json'] = data_filename

        for s in scripts:
            p = commands.start([s],
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               env=scriptenv)

            with commands.terminating(p):
                (out, err) = p.communicate()

            rc = p.returncode
            logging.info('%s: rc=%s err=%s', s, rc, err)
            if rc != 0:
                errors.append(err)

            if rc == 2:
                break
            elif rc > 2:
                logging.warning('hook returned unexpected return code %s', rc)

        if errors and raiseError:
            raise exception.HookError(err)

        with open(data_filename) as f:
            final_data = f.read()
    finally:
        os.unlink(data_filename)
    if hookType == _DOMXML_HOOK:
        return final_data
    elif hookType == _JSON_HOOK:
        return json.loads(final_data)
Пример #18
0
 def test_sudo_kill(self):
     p = commands.start(["sleep", "1"], sudo=True)
     p.kill()
     assert p.wait() == -signal.SIGKILL
Пример #19
0
 def setUp(self):
     self.proc = commands.start([EXT_SLEEP, "2"])
     self.proc_poll = self.proc.poll
     self.proc_kill = self.proc.kill
     self.proc_wait = self.proc.wait
Пример #20
0
 def test_sudo_terminate(self):
     p = commands.start(["sleep", "1"], sudo=True)
     p.terminate()
     assert p.wait() == -signal.SIGTERM
Пример #21
0
 def test_sudo_kill(self):
     p = commands.start(["sleep", "1"], sudo=True)
     p.kill()
     assert p.wait() == -signal.SIGKILL
Пример #22
0
 def test_true(self):
     p = commands.start(["true"])
     out, err = p.communicate()
     assert p.returncode == 0
     assert out is None
     assert err is None
Пример #23
0
 def test_out(self):
     p = commands.start(["echo", "-n", "it works"], stdout=subprocess.PIPE)
     out, err = commands.communicate(p)
     assert p.returncode == 0
     assert out == b"it works"
     assert err is None
Пример #24
0
 def test_true(self):
     p = commands.start(["true"])
     out, err = p.communicate()
     assert p.returncode == 0
     assert out is None
     assert err is None