Example #1
0
    def _start(self):

        vardb = self.pkg.root_config.trees["vartree"].dbapi
        dbdir = vardb.getpath(self.pkg.cpv)
        if not os.path.exists(dbdir):
            # Apparently the package got uninstalled
            # already, so we can safely return early.
            self.returncode = os.EX_OK
            self._async_wait()
            return

        self.settings.setcpv(self.pkg)
        cat, pf = portage.catsplit(self.pkg.cpv)
        myebuildpath = os.path.join(dbdir, pf + ".ebuild")

        try:
            portage.doebuild_environment(myebuildpath,
                                         "prerm",
                                         settings=self.settings,
                                         db=vardb)
        except UnsupportedAPIException:
            # This is safe to ignore since this function is
            # guaranteed to set PORTAGE_BUILDDIR even though
            # it raises UnsupportedAPIException. The error
            # will be logged when it prevents the pkg_prerm
            # and pkg_postrm phases from executing.
            pass

        self._builddir_lock = EbuildBuildDir(scheduler=self.scheduler,
                                             settings=self.settings)
        self._start_task(
            AsyncTaskFuture(future=self._builddir_lock.async_lock()),
            self._start_unmerge,
        )
Example #2
0
    def _prefetch_exit(self, prefetcher):

        opts = self.opts
        pkg = self.pkg
        settings = self.settings

        if opts.fetchonly:
            fetcher = EbuildFetchonly(fetch_all=opts.fetch_all_uri,
                                      pkg=pkg,
                                      pretend=opts.pretend,
                                      settings=settings)
            retval = fetcher.execute()
            self.returncode = retval
            self.wait()
            return

        self._build_dir = EbuildBuildDir(pkg=pkg, settings=settings)
        self._build_dir.lock()

        # Cleaning needs to happen before fetch, since the build dir
        # is used for log handling.
        msg = " === (%s of %s) Cleaning (%s::%s)" % \
         (self.pkg_count.curval, self.pkg_count.maxval,
         self.pkg.cpv, self._ebuild_path)
        short_msg = "emerge: (%s of %s) %s Clean" % \
         (self.pkg_count.curval, self.pkg_count.maxval, self.pkg.cpv)
        self.logger.log(msg, short_msg=short_msg)

        pre_clean_phase = EbuildPhase(background=self.background,
                                      phase='clean',
                                      scheduler=self.scheduler,
                                      settings=self.settings)
        self._start_task(pre_clean_phase, self._pre_clean_exit)
Example #3
0
	def _start(self):

		pkg = self.pkg
		settings = self.settings
		settings.setcpv(pkg)
		self._tree = "bintree"
		self._bintree = self.pkg.root_config.trees[self._tree]
		self._verify = not self.opts.pretend

		dir_path = os.path.join(settings["PORTAGE_TMPDIR"],
			"portage", pkg.category, pkg.pf)
		self._build_dir = EbuildBuildDir(dir_path=dir_path,
			pkg=pkg, settings=settings)
		self._image_dir = os.path.join(dir_path, "image")
		self._infloc = os.path.join(dir_path, "build-info")
		self._ebuild_path = os.path.join(self._infloc, pkg.pf + ".ebuild")
		settings["EBUILD"] = self._ebuild_path
		debug = settings.get("PORTAGE_DEBUG") == "1"
		portage.doebuild_environment(self._ebuild_path, "setup",
			settings["ROOT"], settings, debug, 1, self._bintree.dbapi)
		settings.configdict["pkg"]["EMERGE_FROM"] = pkg.type_name

		# The prefetcher has already completed or it
		# could be running now. If it's running now,
		# wait for it to complete since it holds
		# a lock on the file being fetched. The
		# portage.locks functions are only designed
		# to work between separate processes. Since
		# the lock is held by the current process,
		# use the scheduler and fetcher methods to
		# synchronize with the fetcher.
		prefetcher = self.prefetcher
		if prefetcher is None:
			pass
		elif not prefetcher.isAlive():
			prefetcher.cancel()
		elif prefetcher.poll() is None:

			waiting_msg = ("Fetching '%s' " + \
				"in the background. " + \
				"To view fetch progress, run `tail -f " + \
				"/var/log/emerge-fetch.log` in another " + \
				"terminal.") % prefetcher.pkg_path
			msg_prefix = colorize("GOOD", " * ")
			from textwrap import wrap
			waiting_msg = "".join("%s%s\n" % (msg_prefix, line) \
				for line in wrap(waiting_msg, 65))
			if not self.background:
				writemsg(waiting_msg, noiselevel=-1)

			self._current_task = prefetcher
			prefetcher.addExitListener(self._prefetch_exit)
			return

		self._prefetch_exit(prefetcher)
Example #4
0
    def _prefetch_exit(self, prefetcher):

        if self._was_cancelled():
            self.wait()
            return

        opts = self.opts
        pkg = self.pkg
        settings = self.settings

        if opts.fetchonly:
            if opts.pretend:
                fetcher = EbuildFetchonly(fetch_all=opts.fetch_all_uri,
                                          pkg=pkg,
                                          pretend=opts.pretend,
                                          settings=settings)
                retval = fetcher.execute()
                if retval == os.EX_OK:
                    self._current_task = None
                    self.returncode = os.EX_OK
                    self._async_wait()
                else:
                    # For pretend mode, the convention it to execute
                    # pkg_nofetch and return a successful exitcode.
                    self._start_task(
                        SpawnNofetchWithoutBuilddir(
                            background=self.background,
                            portdb=self.pkg.root_config.trees[
                                self._tree].dbapi,
                            ebuild_path=self._ebuild_path,
                            scheduler=self.scheduler,
                            settings=self.settings), self._default_final_exit)
                return

            fetcher = EbuildFetcher(config_pool=self.config_pool,
                                    ebuild_path=self._ebuild_path,
                                    fetchall=self.opts.fetch_all_uri,
                                    fetchonly=self.opts.fetchonly,
                                    background=False,
                                    logfile=None,
                                    pkg=self.pkg,
                                    scheduler=self.scheduler)
            self._start_task(fetcher, self._fetchonly_exit)
            return

        self._build_dir = EbuildBuildDir(scheduler=self.scheduler,
                                         settings=settings)
        self._start_task(AsyncTaskFuture(future=self._build_dir.async_lock()),
                         self._start_pre_clean)
Example #5
0
    def _prefetch_exit(self, prefetcher):

        if self._was_cancelled():
            self.wait()
            return

        opts = self.opts
        pkg = self.pkg
        settings = self.settings

        if opts.fetchonly:
            if opts.pretend:
                fetcher = EbuildFetchonly(fetch_all=opts.fetch_all_uri,
                                          pkg=pkg,
                                          pretend=opts.pretend,
                                          settings=settings)
                retval = fetcher.execute()
                self.returncode = retval
                self.wait()
                return
            else:
                fetcher = EbuildFetcher(config_pool=self.config_pool,
                                        ebuild_path=self._ebuild_path,
                                        fetchall=self.opts.fetch_all_uri,
                                        fetchonly=self.opts.fetchonly,
                                        background=False,
                                        logfile=None,
                                        pkg=self.pkg,
                                        scheduler=self.scheduler)
                self._start_task(fetcher, self._fetchonly_exit)
                return

        self._build_dir = EbuildBuildDir(scheduler=self.scheduler,
                                         settings=settings)
        self._start_task(AsyncTaskFuture(future=self._build_dir.async_lock()),
                         self._start_pre_clean)
Example #6
0
    def _start(self):

        pkg = self.pkg
        settings = self.settings
        settings.setcpv(pkg)
        self._tree = "bintree"
        self._bintree = self.pkg.root_config.trees[self._tree]
        self._verify = not self.opts.pretend

        # Use realpath like doebuild_environment() does, since we assert
        # that this path is literally identical to PORTAGE_BUILDDIR.
        dir_path = os.path.join(os.path.realpath(settings["PORTAGE_TMPDIR"]),
                                "portage", pkg.category, pkg.pf)
        self._image_dir = os.path.join(dir_path, "image")
        self._infloc = os.path.join(dir_path, "build-info")
        self._ebuild_path = os.path.join(self._infloc, pkg.pf + ".ebuild")
        settings["EBUILD"] = self._ebuild_path
        portage.doebuild_environment(self._ebuild_path,
                                     'setup',
                                     settings=self.settings,
                                     db=self._bintree.dbapi)
        if dir_path != self.settings['PORTAGE_BUILDDIR']:
            raise AssertionError("'%s' != '%s'" % \
             (dir_path, self.settings['PORTAGE_BUILDDIR']))
        self._build_dir = EbuildBuildDir(scheduler=self.scheduler,
                                         settings=settings)
        settings.configdict["pkg"]["EMERGE_FROM"] = "binary"
        settings.configdict["pkg"]["MERGE_TYPE"] = "binary"

        if eapi_exports_replace_vars(settings["EAPI"]):
            vardb = self.pkg.root_config.trees["vartree"].dbapi
            settings["REPLACING_VERSIONS"] = " ".join(
             set(portage.versions.cpv_getversion(x) \
              for x in vardb.match(self.pkg.slot_atom) + \
              vardb.match('='+self.pkg.cpv)))

        # The prefetcher has already completed or it
        # could be running now. If it's running now,
        # wait for it to complete since it holds
        # a lock on the file being fetched. The
        # portage.locks functions are only designed
        # to work between separate processes. Since
        # the lock is held by the current process,
        # use the scheduler and fetcher methods to
        # synchronize with the fetcher.
        prefetcher = self.prefetcher
        if prefetcher is None:
            pass
        elif prefetcher.isAlive() and \
         prefetcher.poll() is None:

            if not self.background:
                fetch_log = os.path.join(_emerge.emergelog._emerge_log_dir,
                                         'emerge-fetch.log')
                msg = (
                    'Fetching in the background:',
                    prefetcher.pkg_path,
                    'To view fetch progress, run in another terminal:',
                    'tail -f %s' % fetch_log,
                )
                out = portage.output.EOutput()
                for l in msg:
                    out.einfo(l)

            self._current_task = prefetcher
            prefetcher.addExitListener(self._prefetch_exit)
            return

        self._prefetch_exit(prefetcher)
Example #7
0
    def _start(self):

        need_builddir = self.phase not in self._phases_without_builddir

        # This can happen if the pre-clean phase triggers
        # die_hooks for some reason, and PORTAGE_BUILDDIR
        # doesn't exist yet.
        if need_builddir and not os.path.isdir(
                self.settings["PORTAGE_BUILDDIR"]):
            msg = _("The ebuild phase '%s' has been aborted "
                    "since PORTAGE_BUILDDIR does not exist: '%s'") % (
                        self.phase, self.settings["PORTAGE_BUILDDIR"])
            self._eerror(textwrap.wrap(msg, 72))
            self.returncode = 1
            self._async_wait()
            return

        # Check if the cgroup hierarchy is in place. If it's not, mount it.
        if (os.geteuid() == 0 and platform.system() == "Linux"
                and "cgroup" in self.settings.features
                and self.phase not in _global_pid_phases):
            cgroup_root = "/sys/fs/cgroup"
            cgroup_portage = os.path.join(cgroup_root, "portage")

            try:
                # cgroup tmpfs
                if not os.path.ismount(cgroup_root):
                    # we expect /sys/fs to be there already
                    if not os.path.isdir(cgroup_root):
                        os.mkdir(cgroup_root, 0o755)
                    subprocess.check_call([
                        "mount",
                        "-t",
                        "tmpfs",
                        "-o",
                        "rw,nosuid,nodev,noexec,mode=0755",
                        "tmpfs",
                        cgroup_root,
                    ])

                # portage subsystem
                if not os.path.ismount(cgroup_portage):
                    if not os.path.isdir(cgroup_portage):
                        os.mkdir(cgroup_portage, 0o755)
                    subprocess.check_call([
                        "mount",
                        "-t",
                        "cgroup",
                        "-o",
                        "rw,nosuid,nodev,noexec,none,name=portage",
                        "tmpfs",
                        cgroup_portage,
                    ])
                    with open(os.path.join(cgroup_portage, "release_agent"),
                              "w") as f:
                        f.write(
                            os.path.join(
                                self.settings["PORTAGE_BIN_PATH"],
                                "cgroup-release-agent",
                            ))
                    with open(
                            os.path.join(cgroup_portage, "notify_on_release"),
                            "w") as f:
                        f.write("1")
                else:
                    # Update release_agent if it no longer exists, because
                    # it refers to a temporary path when portage is updating
                    # itself.
                    release_agent = os.path.join(cgroup_portage,
                                                 "release_agent")
                    try:
                        with open(release_agent) as f:
                            release_agent_path = f.readline().rstrip("\n")
                    except EnvironmentError:
                        release_agent_path = None

                    if release_agent_path is None or not os.path.exists(
                            release_agent_path):
                        with open(release_agent, "w") as f:
                            f.write(
                                os.path.join(
                                    self.settings["PORTAGE_BIN_PATH"],
                                    "cgroup-release-agent",
                                ))

                cgroup_path = tempfile.mkdtemp(
                    dir=cgroup_portage,
                    prefix="%s:%s." %
                    (self.settings["CATEGORY"], self.settings["PF"]),
                )
            except (subprocess.CalledProcessError, OSError):
                pass
            else:
                self.cgroup = cgroup_path

        if self.background:
            # Automatically prevent color codes from showing up in logs,
            # since we're not displaying to a terminal anyway.
            self.settings["NOCOLOR"] = "true"

        start_ipc_daemon = False
        if self._enable_ipc_daemon:
            self.settings.pop("PORTAGE_EBUILD_EXIT_FILE", None)
            if self.phase not in self._phases_without_builddir:
                start_ipc_daemon = True
                if "PORTAGE_BUILDDIR_LOCKED" not in self.settings:
                    self._build_dir = EbuildBuildDir(scheduler=self.scheduler,
                                                     settings=self.settings)
                    self._start_future = self._build_dir.async_lock()
                    self._start_future.add_done_callback(
                        functools.partial(
                            self._start_post_builddir_lock,
                            start_ipc_daemon=start_ipc_daemon,
                        ))
                    return
            else:
                self.settings.pop("PORTAGE_IPC_DAEMON", None)
        else:
            # Since the IPC daemon is disabled, use a simple tempfile based
            # approach to detect unexpected exit like in bug #190128.
            self.settings.pop("PORTAGE_IPC_DAEMON", None)
            if self.phase not in self._phases_without_builddir:
                exit_file = os.path.join(self.settings["PORTAGE_BUILDDIR"],
                                         ".exit_status")
                self.settings["PORTAGE_EBUILD_EXIT_FILE"] = exit_file
                try:
                    os.unlink(exit_file)
                except OSError:
                    if os.path.exists(exit_file):
                        # make sure it doesn't exist
                        raise
            else:
                self.settings.pop("PORTAGE_EBUILD_EXIT_FILE", None)

        self._start_post_builddir_lock(start_ipc_daemon=start_ipc_daemon)
Example #8
0
    def _start(self):

        need_builddir = self.phase not in self._phases_without_builddir

        # This can happen if the pre-clean phase triggers
        # die_hooks for some reason, and PORTAGE_BUILDDIR
        # doesn't exist yet.
        if need_builddir and \
         not os.path.isdir(self.settings['PORTAGE_BUILDDIR']):
            msg = _("The ebuild phase '%s' has been aborted "
            "since PORTAGE_BUILDDIR does not exist: '%s'") % \
            (self.phase, self.settings['PORTAGE_BUILDDIR'])
            self._eerror(textwrap.wrap(msg, 72))
            self._set_returncode((self.pid, 1 << 8))
            self._async_wait()
            return

        # Check if the cgroup hierarchy is in place. If it's not, mount it.
        if (os.geteuid() == 0 and platform.system() == 'Linux'
                and 'cgroup' in self.settings.features
                and self.phase not in self._phases_without_cgroup):
            cgroup_root = '/sys/fs/cgroup'
            cgroup_portage = os.path.join(cgroup_root, 'portage')

            try:
                # cgroup tmpfs
                if not os.path.ismount(cgroup_root):
                    # we expect /sys/fs to be there already
                    if not os.path.isdir(cgroup_root):
                        os.mkdir(cgroup_root, 0o755)
                    subprocess.check_call([
                        'mount', '-t', 'tmpfs', '-o',
                        'rw,nosuid,nodev,noexec,mode=0755', 'tmpfs',
                        cgroup_root
                    ])

                # portage subsystem
                if not os.path.ismount(cgroup_portage):
                    if not os.path.isdir(cgroup_portage):
                        os.mkdir(cgroup_portage, 0o755)
                    subprocess.check_call([
                        'mount', '-t', 'cgroup', '-o',
                        'rw,nosuid,nodev,noexec,none,name=portage', 'tmpfs',
                        cgroup_portage
                    ])

                cgroup_path = tempfile.mkdtemp(
                    dir=cgroup_portage,
                    prefix='%s:%s.' %
                    (self.settings["CATEGORY"], self.settings["PF"]))
            except (subprocess.CalledProcessError, OSError):
                pass
            else:
                self.cgroup = cgroup_path

        if self.background:
            # Automatically prevent color codes from showing up in logs,
            # since we're not displaying to a terminal anyway.
            self.settings['NOCOLOR'] = 'true'

        if self._enable_ipc_daemon:
            self.settings.pop('PORTAGE_EBUILD_EXIT_FILE', None)
            if self.phase not in self._phases_without_builddir:
                if 'PORTAGE_BUILDDIR_LOCKED' not in self.settings:
                    self._build_dir = EbuildBuildDir(scheduler=self.scheduler,
                                                     settings=self.settings)
                    self._build_dir.lock()
                self.settings['PORTAGE_IPC_DAEMON'] = "1"
                self._start_ipc_daemon()
            else:
                self.settings.pop('PORTAGE_IPC_DAEMON', None)
        else:
            # Since the IPC daemon is disabled, use a simple tempfile based
            # approach to detect unexpected exit like in bug #190128.
            self.settings.pop('PORTAGE_IPC_DAEMON', None)
            if self.phase not in self._phases_without_builddir:
                exit_file = os.path.join(self.settings['PORTAGE_BUILDDIR'],
                                         '.exit_status')
                self.settings['PORTAGE_EBUILD_EXIT_FILE'] = exit_file
                try:
                    os.unlink(exit_file)
                except OSError:
                    if os.path.exists(exit_file):
                        # make sure it doesn't exist
                        raise
            else:
                self.settings.pop('PORTAGE_EBUILD_EXIT_FILE', None)

        if self.fd_pipes is None:
            self.fd_pipes = {}
        null_fd = None
        if 0 not in self.fd_pipes and \
         self.phase not in self._phases_interactive_whitelist and \
         "interactive" not in self.settings.get("PROPERTIES", "").split():
            null_fd = os.open('/dev/null', os.O_RDONLY)
            self.fd_pipes[0] = null_fd

        try:
            SpawnProcess._start(self)
        finally:
            if null_fd is not None:
                os.close(null_fd)
    def testIpcDaemon(self):
        event_loop = global_event_loop()
        tmpdir = tempfile.mkdtemp()
        build_dir = None
        try:
            env = {}

            # Pass along PORTAGE_USERNAME and PORTAGE_GRPNAME since they
            # need to be inherited by ebuild subprocesses.
            if 'PORTAGE_USERNAME' in os.environ:
                env['PORTAGE_USERNAME'] = os.environ['PORTAGE_USERNAME']
            if 'PORTAGE_GRPNAME' in os.environ:
                env['PORTAGE_GRPNAME'] = os.environ['PORTAGE_GRPNAME']

            env['PORTAGE_PYTHON'] = _python_interpreter
            env['PORTAGE_BIN_PATH'] = PORTAGE_BIN_PATH
            env['PORTAGE_PYM_PATH'] = PORTAGE_PYM_PATH
            env['PORTAGE_BUILDDIR'] = os.path.join(tmpdir, 'cat', 'pkg-1')
            env['PYTHONDONTWRITEBYTECODE'] = os.environ.get(
                'PYTHONDONTWRITEBYTECODE', '')

            if "__PORTAGE_TEST_HARDLINK_LOCKS" in os.environ:
                env["__PORTAGE_TEST_HARDLINK_LOCKS"] = \
                 os.environ["__PORTAGE_TEST_HARDLINK_LOCKS"]

            build_dir = EbuildBuildDir(scheduler=event_loop, settings=env)
            event_loop.run_until_complete(build_dir.async_lock())
            ensure_dirs(env['PORTAGE_BUILDDIR'])

            input_fifo = os.path.join(env['PORTAGE_BUILDDIR'], '.ipc_in')
            output_fifo = os.path.join(env['PORTAGE_BUILDDIR'], '.ipc_out')
            os.mkfifo(input_fifo)
            os.mkfifo(output_fifo)

            for exitcode in (0, 1, 2):
                exit_command = ExitCommand()
                commands = {'exit': exit_command}
                daemon = EbuildIpcDaemon(commands=commands,
                                         input_fifo=input_fifo,
                                         output_fifo=output_fifo)
                proc = SpawnProcess(args=[
                    BASH_BINARY, "-c",
                    '"$PORTAGE_BIN_PATH"/ebuild-ipc exit %d' % exitcode
                ],
                                    env=env)
                task_scheduler = TaskScheduler(iter([daemon, proc]),
                                               max_jobs=2,
                                               event_loop=event_loop)

                self.received_command = False

                def exit_command_callback():
                    self.received_command = True
                    task_scheduler.cancel()

                exit_command.reply_hook = exit_command_callback
                start_time = time.time()
                self._run(event_loop, task_scheduler, self._SCHEDULE_TIMEOUT)

                hardlock_cleanup(env['PORTAGE_BUILDDIR'],
                                 remove_all_locks=True)

                self.assertEqual(self.received_command, True,
                 "command not received after %d seconds" % \
                 (time.time() - start_time,))
                self.assertEqual(proc.isAlive(), False)
                self.assertEqual(daemon.isAlive(), False)
                self.assertEqual(exit_command.exitcode, exitcode)

            # Intentionally short timeout test for EventLoop/AsyncScheduler.
            # Use a ridiculously long sleep_time_s in case the user's
            # system is heavily loaded (see bug #436334).
            sleep_time_s = 600  # seconds
            short_timeout_s = 0.010  # seconds

            for i in range(3):
                exit_command = ExitCommand()
                commands = {'exit': exit_command}
                daemon = EbuildIpcDaemon(commands=commands,
                                         input_fifo=input_fifo,
                                         output_fifo=output_fifo)
                proc = SleepProcess(seconds=sleep_time_s)
                task_scheduler = TaskScheduler(iter([daemon, proc]),
                                               max_jobs=2,
                                               event_loop=event_loop)

                self.received_command = False

                def exit_command_callback():
                    self.received_command = True
                    task_scheduler.cancel()

                exit_command.reply_hook = exit_command_callback
                start_time = time.time()
                self._run(event_loop, task_scheduler, short_timeout_s)

                hardlock_cleanup(env['PORTAGE_BUILDDIR'],
                                 remove_all_locks=True)

                self.assertEqual(self.received_command, False,
                 "command received after %d seconds" % \
                 (time.time() - start_time,))
                self.assertEqual(proc.isAlive(), False)
                self.assertEqual(daemon.isAlive(), False)
                self.assertEqual(proc.returncode == os.EX_OK, False)

        finally:
            if build_dir is not None:
                event_loop.run_until_complete(build_dir.async_unlock())
            shutil.rmtree(tmpdir)
Example #10
0
	def _start(self):

		need_builddir = self.phase not in self._phases_without_builddir

		# This can happen if the pre-clean phase triggers
		# die_hooks for some reason, and PORTAGE_BUILDDIR
		# doesn't exist yet.
		if need_builddir and \
			not os.path.isdir(self.settings['PORTAGE_BUILDDIR']):
			msg = _("The ebuild phase '%s' has been aborted "
			"since PORTAGE_BUILDIR does not exist: '%s'") % \
			(self.phase, self.settings['PORTAGE_BUILDDIR'])
			self._eerror(textwrap.wrap(msg, 72))
			self._set_returncode((self.pid, 1 << 8))
			self.wait()
			return

		if self.background:
			# Automatically prevent color codes from showing up in logs,
			# since we're not displaying to a terminal anyway.
			self.settings['NOCOLOR'] = 'true'

		if self._enable_ipc_daemon:
			self.settings.pop('PORTAGE_EBUILD_EXIT_FILE', None)
			if self.phase not in self._phases_without_builddir:
				if 'PORTAGE_BUILDIR_LOCKED' not in self.settings:
					self._build_dir = EbuildBuildDir(
						scheduler=self.scheduler, settings=self.settings)
					self._build_dir.lock()
				self.settings['PORTAGE_IPC_DAEMON'] = "1"
				self._start_ipc_daemon()
			else:
				self.settings.pop('PORTAGE_IPC_DAEMON', None)
		else:
			# Since the IPC daemon is disabled, use a simple tempfile based
			# approach to detect unexpected exit like in bug #190128.
			self.settings.pop('PORTAGE_IPC_DAEMON', None)
			if self.phase not in self._phases_without_builddir:
				exit_file = os.path.join(
					self.settings['PORTAGE_BUILDDIR'],
					'.exit_status')
				self.settings['PORTAGE_EBUILD_EXIT_FILE'] = exit_file
				try:
					os.unlink(exit_file)
				except OSError:
					if os.path.exists(exit_file):
						# make sure it doesn't exist
						raise
			else:
				self.settings.pop('PORTAGE_EBUILD_EXIT_FILE', None)

		if self.fd_pipes is None:
			self.fd_pipes = {}
		null_fd = None
		if 0 not in self.fd_pipes and \
			self.phase not in self._phases_interactive_whitelist and \
			"interactive" not in self.settings.get("PROPERTIES", "").split():
			null_fd = os.open('/dev/null', os.O_RDONLY)
			self.fd_pipes[0] = null_fd

		try:
			SpawnProcess._start(self)
		finally:
			if null_fd is not None:
				os.close(null_fd)
Example #11
0
    def _prefetch_exit(self, prefetcher):

        if self._was_cancelled():
            self.wait()
            return

        opts = self.opts
        pkg = self.pkg
        settings = self.settings

        if opts.fetchonly:
            if opts.pretend:
                fetcher = EbuildFetchonly(fetch_all=opts.fetch_all_uri,
                                          pkg=pkg,
                                          pretend=opts.pretend,
                                          settings=settings)
                retval = fetcher.execute()
                if retval == os.EX_OK:
                    self._current_task = None
                    self.returncode = os.EX_OK
                    self._async_wait()
                else:
                    # For pretend mode, the convention it to execute
                    # pkg_nofetch and return a successful exitcode.
                    self._start_task(
                        SpawnNofetchWithoutBuilddir(
                            background=self.background,
                            portdb=self.pkg.root_config.trees[
                                self._tree].dbapi,
                            ebuild_path=self._ebuild_path,
                            scheduler=self.scheduler,
                            settings=self.settings), self._default_final_exit)
                return

            quiet_setting = settings.get("PORTAGE_QUIET", False)
            fetch_log = None
            logwrite_access = False
            if quiet_setting:
                fetch_log = os.path.join(_emerge.emergelog._emerge_log_dir,
                                         "emerge-fetch.log")
                logwrite_access = os.access(first_existing(fetch_log), os.W_OK)

            fetcher = EbuildFetcher(
                config_pool=self.config_pool,
                ebuild_path=self._ebuild_path,
                fetchall=self.opts.fetch_all_uri,
                fetchonly=self.opts.fetchonly,
                background=quiet_setting if logwrite_access else False,
                logfile=fetch_log if logwrite_access else None,
                pkg=self.pkg,
                scheduler=self.scheduler,
            )

            if fetch_log and logwrite_access:
                fetcher.addExitListener(self._fetchonly_exit)
                self._task_queued(fetcher)
                self.scheduler.fetch.schedule(fetcher, force_queue=True)
            else:
                self._start_task(fetcher, self._fetchonly_exit)
            return

        self._build_dir = EbuildBuildDir(scheduler=self.scheduler,
                                         settings=settings)
        self._start_task(AsyncTaskFuture(future=self._build_dir.async_lock()),
                         self._start_pre_clean)
Example #12
0
    def _start(self):

        vardb = self.pkg.root_config.trees["vartree"].dbapi
        dbdir = vardb.getpath(self.pkg.cpv)
        if not os.path.exists(dbdir):
            # Apparently the package got uninstalled
            # already, so we can safely return early.
            self.returncode = os.EX_OK
            self._async_wait()
            return

        self.settings.setcpv(self.pkg)
        cat, pf = portage.catsplit(self.pkg.cpv)
        myebuildpath = os.path.join(dbdir, pf + ".ebuild")

        try:
            portage.doebuild_environment(myebuildpath,
                                         "prerm",
                                         settings=self.settings,
                                         db=vardb)
        except UnsupportedAPIException:
            # This is safe to ignore since this function is
            # guaranteed to set PORTAGE_BUILDDIR even though
            # it raises UnsupportedAPIException. The error
            # will be logged when it prevents the pkg_prerm
            # and pkg_postrm phases from executing.
            pass

        self._builddir_lock = EbuildBuildDir(scheduler=self.scheduler,
                                             settings=self.settings)
        self._builddir_lock.lock()

        portage.prepare_build_dirs(settings=self.settings, cleanup=True)

        # Output only gets logged if it comes after prepare_build_dirs()
        # which initializes PORTAGE_LOG_FILE.
        retval, pkgmap = _unmerge_display(self.pkg.root_config,
                                          self.opts,
                                          "unmerge", [self.pkg.cpv],
                                          clean_delay=0,
                                          writemsg_level=self._writemsg_level)

        if retval != os.EX_OK:
            self._builddir_lock.unlock()
            self.returncode = retval
            self._async_wait()
            return

        self._writemsg_level(">>> Unmerging %s...\n" % (self.pkg.cpv, ),
                             noiselevel=-1)
        self._emergelog("=== Unmerging... (%s)" % (self.pkg.cpv, ))

        unmerge_task = MergeProcess(
            mycat=cat,
            mypkg=pf,
            settings=self.settings,
            treetype="vartree",
            vartree=self.pkg.root_config.trees["vartree"],
            scheduler=self.scheduler,
            background=self.background,
            mydbapi=self.pkg.root_config.trees["vartree"].dbapi,
            prev_mtimes=self.ldpath_mtimes,
            logfile=self.settings.get("PORTAGE_LOG_FILE"),
            unmerge=True)

        self._start_task(unmerge_task, self._unmerge_exit)
Example #13
0
    def _fetch_exit(self, fetcher):
        opts = self.opts
        pkg = self.pkg

        fetch_failed = False
        if opts.fetchonly:
            fetch_failed = self._final_exit(fetcher) != os.EX_OK
        else:
            fetch_failed = self._default_exit(fetcher) != os.EX_OK

        if fetch_failed and fetcher.logfile is not None and \
         os.path.exists(fetcher.logfile):
            self.settings["PORTAGE_LOG_FILE"] = fetcher.logfile

        if fetch_failed or opts.fetchonly:
            self.wait()
            return

        logger = self.logger
        opts = self.opts
        pkg_count = self.pkg_count
        scheduler = self.scheduler
        settings = self.settings
        features = settings.features
        ebuild_path = self._ebuild_path
        system_set = pkg.root_config.sets["system"]

        self._build_dir = EbuildBuildDir(pkg=pkg, settings=settings)
        self._build_dir.lock()

        # Cleaning is triggered before the setup
        # phase, in portage.doebuild().
        msg = " === (%s of %s) Cleaning (%s::%s)" % \
         (pkg_count.curval, pkg_count.maxval, pkg.cpv, ebuild_path)
        short_msg = "emerge: (%s of %s) %s Clean" % \
         (pkg_count.curval, pkg_count.maxval, pkg.cpv)
        logger.log(msg, short_msg=short_msg)

        #buildsyspkg: Check if we need to _force_ binary package creation
        self._issyspkg = "buildsyspkg" in features and \
          system_set.findAtomForPackage(pkg) and \
          not opts.buildpkg

        if opts.buildpkg or self._issyspkg:

            self._buildpkg = True

            msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
             (pkg_count.curval, pkg_count.maxval, pkg.cpv, ebuild_path)
            short_msg = "emerge: (%s of %s) %s Compile" % \
             (pkg_count.curval, pkg_count.maxval, pkg.cpv)
            logger.log(msg, short_msg=short_msg)

        else:
            msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
             (pkg_count.curval, pkg_count.maxval, pkg.cpv, ebuild_path)
            short_msg = "emerge: (%s of %s) %s Compile" % \
             (pkg_count.curval, pkg_count.maxval, pkg.cpv)
            logger.log(msg, short_msg=short_msg)

        build = EbuildExecuter(background=self.background,
                               pkg=pkg,
                               scheduler=scheduler,
                               settings=settings)
        self._start_task(build, self._build_exit)
Example #14
0
	def _start(self):

		root_config = self.pkg.root_config
		portdb = root_config.trees["porttree"].dbapi
		ebuild_path = portdb.findname(self.pkg.cpv)
		if ebuild_path is None:
			raise AssertionError("ebuild not found for '%s'" % self.pkg.cpv)
		settings = self.config_pool.allocate()
		settings.setcpv(self.pkg)
		if self.prefetch and \
			self._prefetch_size_ok(portdb, settings, ebuild_path):
			self.config_pool.deallocate(settings)
			self.returncode = os.EX_OK
			self.wait()
			return

		# In prefetch mode, logging goes to emerge-fetch.log and the builddir
		# should not be touched since otherwise it could interfere with
		# another instance of the same cpv concurrently being built for a
		# different $ROOT (currently, builds only cooperate with prefetchers
		# that are spawned for the same $ROOT).
		if not self.prefetch:
			self._build_dir = EbuildBuildDir(pkg=self.pkg, settings=settings)
			self._build_dir.lock()
			self._build_dir.clean_log()
			portage.prepare_build_dirs(self.pkg.root, self._build_dir.settings, 0)
			if self.logfile is None:
				self.logfile = settings.get("PORTAGE_LOG_FILE")

		phase = "fetch"
		if self.fetchall:
			phase = "fetchall"

		# If any incremental variables have been overridden
		# via the environment, those values need to be passed
		# along here so that they are correctly considered by
		# the config instance in the subproccess.
		fetch_env = os.environ.copy()
		fetch_env['PORTAGE_CONFIGROOT'] = settings['PORTAGE_CONFIGROOT']

		nocolor = settings.get("NOCOLOR")
		if nocolor is not None:
			fetch_env["NOCOLOR"] = nocolor

		fetch_env["PORTAGE_NICENESS"] = "0"
		if self.prefetch:
			fetch_env["PORTAGE_PARALLEL_FETCHONLY"] = "1"

		ebuild_binary = os.path.join(
			settings["PORTAGE_BIN_PATH"], "ebuild")

		fetch_args = [ebuild_binary, ebuild_path, phase]
		debug = settings.get("PORTAGE_DEBUG") == "1"
		if debug:
			fetch_args.append("--debug")

		if not self.background and nocolor not in ('yes', 'true'):
			# Force consistent color output, in case we are capturing fetch
			# output through a normal pipe due to unavailability of ptys.
			fetch_args.append('--color=y')

		self.args = fetch_args
		self.env = fetch_env
		if self._build_dir is None:
			# Free settings now since we only have a local reference.
			self.config_pool.deallocate(settings)
		SpawnProcess._start(self)
Example #15
0
    def testIpcDaemon(self):
        tmpdir = tempfile.mkdtemp()
        build_dir = None
        try:
            env = {}

            # Pass along PORTAGE_USERNAME and PORTAGE_GRPNAME since they
            # need to be inherited by ebuild subprocesses.
            if 'PORTAGE_USERNAME' in os.environ:
                env['PORTAGE_USERNAME'] = os.environ['PORTAGE_USERNAME']
            if 'PORTAGE_GRPNAME' in os.environ:
                env['PORTAGE_GRPNAME'] = os.environ['PORTAGE_GRPNAME']

            env['PORTAGE_PYTHON'] = _python_interpreter
            env['PORTAGE_BIN_PATH'] = PORTAGE_BIN_PATH
            env['PORTAGE_PYM_PATH'] = PORTAGE_PYM_PATH
            env['PORTAGE_BUILDDIR'] = os.path.join(tmpdir, 'cat', 'pkg-1')

            if "__PORTAGE_TEST_HARDLINK_LOCKS" in os.environ:
                env["__PORTAGE_TEST_HARDLINK_LOCKS"] = \
                 os.environ["__PORTAGE_TEST_HARDLINK_LOCKS"]

            task_scheduler = TaskScheduler(max_jobs=2)
            build_dir = EbuildBuildDir(scheduler=task_scheduler.sched_iface,
                                       settings=env)
            build_dir.lock()
            ensure_dirs(env['PORTAGE_BUILDDIR'])

            input_fifo = os.path.join(env['PORTAGE_BUILDDIR'], '.ipc_in')
            output_fifo = os.path.join(env['PORTAGE_BUILDDIR'], '.ipc_out')
            os.mkfifo(input_fifo)
            os.mkfifo(output_fifo)

            for exitcode in (0, 1, 2):
                exit_command = ExitCommand()
                commands = {'exit': exit_command}
                daemon = EbuildIpcDaemon(commands=commands,
                                         input_fifo=input_fifo,
                                         output_fifo=output_fifo,
                                         scheduler=task_scheduler.sched_iface)
                proc = SpawnProcess(args=[
                    BASH_BINARY, "-c",
                    '"$PORTAGE_BIN_PATH"/ebuild-ipc exit %d' % exitcode
                ],
                                    env=env,
                                    scheduler=task_scheduler.sched_iface)

                self.received_command = False

                def exit_command_callback():
                    self.received_command = True
                    task_scheduler.clear()
                    task_scheduler.wait()

                exit_command.reply_hook = exit_command_callback
                start_time = time.time()
                task_scheduler.add(daemon)
                task_scheduler.add(proc)
                task_scheduler.run(timeout=self._SCHEDULE_TIMEOUT)
                task_scheduler.clear()
                task_scheduler.wait()
                hardlock_cleanup(env['PORTAGE_BUILDDIR'],
                                 remove_all_locks=True)

                self.assertEqual(self.received_command, True,
                 "command not received after %d seconds" % \
                 (time.time() - start_time,))
                self.assertEqual(proc.isAlive(), False)
                self.assertEqual(daemon.isAlive(), False)
                self.assertEqual(exit_command.exitcode, exitcode)

            # Intentionally short timeout test for QueueScheduler.run()
            sleep_time_s = 10  # 10.000 seconds
            short_timeout_ms = 10  #  0.010 seconds

            for i in range(3):
                exit_command = ExitCommand()
                commands = {'exit': exit_command}
                daemon = EbuildIpcDaemon(commands=commands,
                                         input_fifo=input_fifo,
                                         output_fifo=output_fifo,
                                         scheduler=task_scheduler.sched_iface)
                proc = SpawnProcess(
                    args=[BASH_BINARY, "-c",
                          'exec sleep %d' % sleep_time_s],
                    env=env,
                    scheduler=task_scheduler.sched_iface)

                self.received_command = False

                def exit_command_callback():
                    self.received_command = True
                    task_scheduler.clear()
                    task_scheduler.wait()

                exit_command.reply_hook = exit_command_callback
                start_time = time.time()
                task_scheduler.add(daemon)
                task_scheduler.add(proc)
                task_scheduler.run(timeout=short_timeout_ms)
                task_scheduler.clear()
                task_scheduler.wait()
                hardlock_cleanup(env['PORTAGE_BUILDDIR'],
                                 remove_all_locks=True)

                self.assertEqual(self.received_command, False,
                 "command received after %d seconds" % \
                 (time.time() - start_time,))
                self.assertEqual(proc.isAlive(), False)
                self.assertEqual(daemon.isAlive(), False)
                self.assertEqual(proc.returncode == os.EX_OK, False)

        finally:
            if build_dir is not None:
                build_dir.unlock()
            shutil.rmtree(tmpdir)