Exemplo n.º 1
0
    def finish(self):
        """Clean-up the upgrade-tool files and report about package changes."""
        shutil.rmtree(self._config.upgrade_tool_directory)

        if os.getuid() == 0:
            uid = pwd.getpwnam("landscape").pw_uid
            gid = grp.getgrnam("landscape").gr_gid
        else:
            uid = None
            gid = None

        reporter = find_reporter_command(self._config)

        # Force an apt-update run, because the sources.list has changed
        args = ["--force-apt-update"]

        if self._config.config is not None:
            args.append("--config=%s" % self._config.config)

        return spawn_process(reporter,
                             args=args,
                             uid=uid,
                             gid=gid,
                             path=os.getcwd(),
                             env=os.environ)
    def test_spawn_process_output(self):
        """
        The process returns the expected standard output.
        """
        def callback(args):
            out, err, code = args
            self.assertEqual(out, b"a b")
            self.assertEqual(err, b"")
            self.assertEqual(code, 0)

        result = spawn_process(self.command, args=("a", "b"))
        result.addCallback(callback)
        return result
    def test_spawn_process_with_stdin(self):
        """
        Optionally C{spawn_process} accepts a C{stdin} argument.
        """
        create_text_file(self.command, "#!/bin/sh\n/bin/cat")

        def callback(args):
            out, err, code = args
            self.assertEqual(b"hello", out)

        result = spawn_process(self.command, stdin="hello")
        result.addCallback(callback)
        return result
Exemplo n.º 4
0
    def run_apt_update(self):
        """Run apt-update and log a warning in case of non-zero exit code.

        @return: a deferred returning (out, err, code)
        """
        if (self._config.force_apt_update or self._apt_sources_have_changed()
            or self._apt_update_timeout_expired(
                self._config.apt_update_interval)):

            result = spawn_process(self.apt_update_filename)

            def callback((out, err, code)):
                accepted_apt_errors = (
                    "Problem renaming the file /var/cache/apt/srcpkgcache.bin",
                    "Problem renaming the file /var/cache/apt/pkgcache.bin")

                touch_file(self._config.update_stamp_filename)
                logging.debug(
                    "'%s' exited with status %d (out='%s', err='%s')" % (
                        self.apt_update_filename, code, out, err))

                if code != 0:
                    logging.warning("'%s' exited with status %d (%s)" % (
                        self.apt_update_filename, code, err))

                    # Errors caused by missing cache files are acceptable, as
                    # they are not an issue for the lists update process.
                    # These errors can happen if an 'apt-get clean' is run
                    # while 'apt-get update' is running.
                    for message in accepted_apt_errors:
                        if message in err:
                            out, err, code = "", "", 0
                            break

                elif not self._facade.get_channels():
                    code = 1
                    err = ("There are no APT sources configured in %s or %s." %
                           (self.sources_list_filename,
                            self.sources_list_directory))

                deferred = self._broker.call_if_accepted(
                    "package-reporter-result", self.send_result, code, err)
                deferred.addCallback(lambda ignore: (out, err, code))
                return deferred

            return result.addCallback(callback)

        else:
            logging.debug("'%s' didn't run, update interval has not passed" %
                          self.apt_update_filename)
            return succeed(("", "", 0))
    def test_spawn_process_error(self):
        """
        The process returns the expected standard error.
        """
        create_text_file(self.command, "#!/bin/sh\necho -n $@ >&2")

        def callback(args):
            out, err, code = args
            self.assertEqual(out, b"")
            self.assertEqual(err, b"a b")
            self.assertEqual(code, 0)

        result = spawn_process(self.command, args=("a", "b"))
        result.addCallback(callback)
        return result
    def test_spawn_process_return_value(self):
        """
        The process is executed and returns the expected exit code.
        """
        create_text_file(self.command, "#!/bin/sh\nexit 2")

        def callback(args):
            out, err, code = args
            self.assertEqual(out, b"")
            self.assertEqual(err, b"")
            self.assertEqual(code, 2)

        result = spawn_process(self.command)
        result.addCallback(callback)
        return result
Exemplo n.º 7
0
    def _apt_update(self, deferred):
        """
        Run apt-update using the passed in deferred, which allows for callers
        to inspect the result code.
        """
        env = {}
        if self._config.http_proxy:
            env["http_proxy"] = self._config.http_proxy
        if self._config.https_proxy:
            env["https_proxy"] = self._config.https_proxy
        result = spawn_process(self.apt_update_filename, env=env)

        def callback(args, deferred):
            return deferred.callback(args)

        return result.addCallback(callback, deferred)
Exemplo n.º 8
0
    def upgrade(self,
                code_name,
                operation_id,
                allow_third_party=False,
                debug=False):
        """Run the upgrade-tool command and send a report of the results.

        @param code_name: The code-name of the release to upgrade to.
        @param operation_id: The activity id for this task.
        @param allow_third_party: Whether to enable non-official APT repo.
        @param debug: Whether to turn on debug level logging.
        """
        upgrade_tool_directory = self._config.upgrade_tool_directory
        upgrade_tool_filename = os.path.join(upgrade_tool_directory, code_name)
        args = ["--frontend", "DistUpgradeViewNonInteractive"]
        env = os.environ.copy()
        if allow_third_party:
            env["RELEASE_UPRADER_ALLOW_THIRD_PARTY"] = "True"
        if debug:
            env["DEBUG_UPDATE_MANAGER"] = "True"

        result = spawn_process(upgrade_tool_filename,
                               args=args,
                               env=env,
                               path=upgrade_tool_directory,
                               wait_pipes=False)

        def send_operation_result(args):
            out, err, code = args
            out = out.decode("utf-8")
            err = err.decode("utf-8")

            if code == 0:
                status = SUCCEEDED
            else:
                status = FAILED
            text = self.make_operation_result_text(out, err)
            message = self.make_operation_result_message(
                operation_id, status, text, code)
            logging.info("Queuing message with release upgrade results to "
                         "exchange urgently.")
            return self._send_message(message)

        result.addCallback(send_operation_result)
        return result
    def test_spawn_process_callback_multiple_newlines(self):
        """
        If output ends with more than one newline, empty lines are preserved.
        """
        create_text_file(self.command, "#!/bin/sh\n/bin/echo -ne $@")
        param = r"some text\nanother line\n\n\n"
        expected = [b"some text", b"another line", b"", b""]
        lines = []

        def line_received(line):
            lines.append(line)

        def callback(args):
            out, err, code = args
            self.assertEqual(expected, lines)

        result = spawn_process(self.command,
                               args=(param, ),
                               line_received=line_received)
        result.addCallback(callback)
        return result
    def test_spawn_process_callback(self):
        """
        If a callback for process output is provieded, it is called for every
        line of output.
        """
        create_text_file(self.command, "#!/bin/sh\n/bin/echo -ne $@")
        param = r"some text\nanother line\nok, last one\n"
        expected = [b"some text", b"another line", b"ok, last one"]
        lines = []

        def line_received(line):
            lines.append(line)

        def callback(args):
            out, err, code = args
            self.assertEqual(expected, lines)

        result = spawn_process(self.command,
                               args=(param, ),
                               line_received=line_received)
        result.addCallback(callback)
        return result
    def test_spawn_process_callback_no_newline(self):
        """
        If output ends without a newline, the line is still passed to the
        callback.
        """
        create_text_file(self.command, "#!/bin/sh\n/bin/echo -ne $@")
        param = r"some text\nanother line\nok, last one"
        expected = [b"some text", b"another line", b"ok, last one"]
        lines = []

        def line_received(line):
            lines.append(line)

        def callback(args):
            out, err, code = args
            self.assertEqual(expected, lines)

        result = spawn_process(self.command,
                               args=(param, ),
                               line_received=line_received)
        result.addCallback(callback)
        return result
    def test_spawn_process_with_signal(self):
        """
        In case the process gets terminated by a signal, it raises a
        C{SignalError}.
        """
        # This script will kill itself.
        create_text_file(self.command, """\
#!/bin/sh
kill $$
""")

        def callback(args):
            raise RuntimeError("Errback was not called.")

        def errback(failure):
            out, err, code = failure.value.args
            self.assertEqual(out, b"")
            self.assertEqual(err, b"")
            self.assertEqual(code, 15)  # 15 for SIGTERM

        result = spawn_process(self.command)
        result.addCallbacks(callback, errback)
        return result
Exemplo n.º 13
0
 def _run_process(self, command, args, uid=None, gid=None):
     """
     Run the process in an asynchronous fashion, to be overriden in tests.
     """
     return spawn_process(command, args, uid=uid, gid=gid)