Example #1
0
def error(text, exitcode=1):
        """Emit an error message prefixed by the command name """

        emsg("pkgmerge: %s" % text)

        if exitcode != None:
                sys.exit(exitcode)
Example #2
0
def __echo_manifest(pth, out_func, strip_newline=False):
        try:
                with open(pth, "rb") as fh:
                        text = ""
                        act = ""
                        for l in fh:
                                text += l
                                act += l.rstrip()
                                if act.endswith("\\"):
                                        act = act.rstrip("\\")
                                        continue
                                if __resolve_echo_line(act):
                                        if strip_newline:
                                                text = text.rstrip()
                                        elif text[-1] != "\n":
                                                text += "\n"
                                        out_func(text)
                                text = ""
                                act = ""
                        if text != "" and __resolve_echo_line(act):
                                if text[-1] != "\n":
                                        text += "\n"
                                out_func(text)
        except EnvironmentError:
                ret_code = 1
                emsg(_("Could not open %s to echo manifest") %
                    manifest_path)
Example #3
0
                def activate_live_be(cmd):
                        cmd += [self.clone_dir]

                        # Activate the clone.
                        exec_cmd(cmd)

                        if be.beActivate(self.be_name_clone) != 0:
                                emsg(_("pkg: unable to activate %s") \
                                    % self.be_name_clone)
                                return

                        # Consider the last operation a success, and log it as
                        # ending here so that it will be recorded in the new
                        # image's history.
                        self.img.history.log_operation_end()

                        if be.beUnmount(self.be_name_clone) != 0:
                                emsg(_("pkg: unable to unmount %s") \
                                    % self.clone_dir)
                                return

                        os.rmdir(self.clone_dir)

                        msg(_("""
A clone of %s exists and has been updated and activated.
On the next boot the Boot Environment %s will be mounted on '/'.
Reboot when ready to switch to this updated BE.
""") % \
                            (self.be_name, self.be_name_clone))
Example #4
0
def write_res(deps, out_file, echo_manifest, manifest_path):
        """Write the dependencies resolved, and possibly the manifest, to the
        destination file.

        'deps' is a list of the resolved dependencies.

        'out_file' is the path to the destination file.

        'echo_manifest' determines whether to repeat the original manifest in
        the destination file.

        'manifest_path' the path to the manifest which generated the
        dependencies."""

        ret_code = 0
        try:
                out_fh = open(out_file, "wb")
        except EnvironmentError:
                ret_code = 1
                emsg(_("Could not open output file %s for writing") %
                    out_file)
                return ret_code
        if echo_manifest:
                __echo_manifest(manifest_path, out_fh.write)
        for d in deps:
                out_fh.write("%s\n" % d)
        out_fh.close()
        return ret_code
Example #5
0
def trans_create_repository(repo_uri, args):
        """DEPRECATED"""

        repo_props = {}
        opts, pargs = getopt.getopt(args, "", ["set-property="])
        for opt, arg in opts:
                if opt == "--set-property":
                        try:
                                prop, p_value = arg.split("=", 1)
                                p_sec, p_name = prop.split(".", 1)
                        except ValueError:
                                usage(_("property arguments must be of "
                                    "the form '<section.property>="
                                    "<value>'."), cmd="create-repository")
                        repo_props.setdefault(p_sec, {})
                        repo_props[p_sec][p_name] = p_value

        xport, pub = setup_transport_and_pubs(repo_uri, remote=False)

        try:
                trans.Transaction(repo_uri, create_repo=True,
                    repo_props=repo_props, xport=xport, pub=pub)
        except trans.TransactionRepositoryConfigError, e:
                error(e, cmd="create-repository")
                emsg(_("Invalid repository configuration values were "
                    "specified using --set-property or required values are "
                    "missing.  Please provide the correct and/or required "
                    "values using the --set-property option."))
Example #6
0
def pkgdeps_to_dir(pkg_deps, manifest_paths, out_dir, suffix, echo_manifest):
        """Given an output directory, for each manifest given, writes the
        dependencies resolved to a file in the output directory.

        'pkg_deps' is a dictionary that maps a path to a manifest to the
        dependencies that were resolved for that manifest.

        'manifest_paths' is a list of the paths to the manifests for which
        file dependencies were resolved.

        'out_dir' is the path to the directory into which the dependency files
        should be written.

        'suffix' is the string to append to the end of each output file.

        'echo_manifest' is a boolean which determines whether the original
        manifest will be written out or not."""

        ret_code = 0
        if not os.path.exists(out_dir):
                try:
                        os.makedirs(out_dir)
                except EnvironmentError, e:
                        e_dic = {"dir": out_dir}
                        if len(e.args) > 0:
                                e_dic["err"] = e.args[1]
                        else:
                                e_dic["err"] = e.args[0]
                        emsg(_("Out dir %(out_dir)s does not exist and could "
                            "not be created. Error is: %(err)s") % e_dic)
                        return 1
Example #7
0
        def restore_image(self):

                """Restore a failed image-update attempt."""

                self.__reset_image_state(failure=True)

                # Leave the clone around for debugging purposes if we're
                # operating on the live BE.
                if self.is_live_BE:
                        emsg(_(" The running system has not been modified. "
                            "Modifications were only made to a clone of the "
                            "running system.  This clone is mounted at %s "
                            "should you wish to inspect it.") % self.clone_dir)

                else:
                        # Rollback and destroy the snapshot.
                        try:
                                if be.beRollback(self.be_name,
                                    self.snapshot_name) != 0:
                                        emsg(_("pkg: unable to rollback BE %s "
                                            "and restore image") % self.be_name)

                                self.destroy_snapshot()
                                os.rmdir(self.clone_dir)
                        except Exception, e:
                                self.img.history.log_operation_error(error=e)
                                raise e

                        msg(_("%s failed to be updated. No changes have been "
                            "made to %s.") % (self.be_name, self.be_name))
Example #8
0
        def close(self, add_to_catalog=True):
                """Closes an open transaction, returning the published FMRI for
                the corresponding package, and its current state in the catalog.
                """
                def split_trans_id(tid):
                        m = re.match("(\d+)_(.*)", tid)
                        return m.group(1), urllib.unquote(m.group(2))

                trans_id = self.get_basename()
                pkg_fmri = split_trans_id(trans_id)[1]

                # set package state to SUBMITTED
                pkg_state = "SUBMITTED"

                # set state to PUBLISHED
                if self.append_trans:
                        pkg_fmri, pkg_state = self.accept_append(add_to_catalog)
                else:
                        pkg_fmri, pkg_state = self.accept_publish(
                            add_to_catalog)

                # Discard the in-flight transaction data.
                try:
                        shutil.rmtree(self.dir)
                except EnvironmentError, e:
                        # Ensure that the error goes to stderr, and then drive
                        # on as the actual package was published.
                        misc.emsg(e)
Example #9
0
        def restore_install_uninstall(self):

                """Restore a failed install or uninstall attempt.
                        Clone the snapshot, mount the BE and
                        notify user of its existence. Rollback
                        if not operating on a live BE"""

                if self.is_live_BE:
                        # Create a new BE based on the previously taken
                        # snapshot.

                        ret, self.be_name_clone, not_used = \
                            be.beCopy(None, self.be_name, self.snapshot_name)
                        if ret != 0:
                                # If the above beCopy() failed we will try it
                                # without expecting the BE clone name to be
                                # returned by libbe. We do this in case an old
                                # version of libbe is on a system with
                                # a new version of pkg.
                                self.be_name_clone = self.be_name + "_" + \
                                    self.snapshot_name

                                ret, not_used, not_used2 = \
                                    be.beCopy(self.be_name_clone, \
                                    self.be_name, self.snapshot_name)
                                if ret != 0:
                                        emsg(_("pkg: unable to create BE %s") \
                                           % self.be_name_clone)
                                        return

                        if be.beMount(self.be_name_clone, self.clone_dir) != 0:
                                emsg(_("pkg: unable to mount BE %(name)s "
                                    "on %(clone_dir)s") %
                                    { "name": self.be_name_clone,
                                      "clone_dir": self.clone_dir })
                                return

                        emsg(_("The Boot Environment %(name)s failed to be "
                            "updated. A snapshot was taken before the failed "
                            "attempt and is mounted here %(clone_dir)s. Use "
                            "'beadm unmount %(clone_name)s' and then 'beadm "
                            "activate %(clone_name)s' if you wish to boot "
                            "to this BE.") %
                            { "name": self.be_name,
                              "clone_dir": self.clone_dir,
                              "clone_name": self.be_name_clone })
                else:
                        if be.beRollback(self.be_name, self.snapshot_name) != 0:
                                emsg("pkg: unable to rollback BE %s" % \
                                    self.be_name)

                        self.destroy_snapshot()

                        emsg(_("The Boot Environment %s failed to be updated. "
                          "A snapshot was taken before the failed attempt "
                          "and has been restored so no changes have been "
                          "made to %s.") % (self.be_name, self.be_name))
Example #10
0
 def exec_cmd(cmd):
         ret = 0
         try:
                 ret = subprocess.call(cmd,
                     stdout = file("/dev/null"),
                     stderr = subprocess.STDOUT)
         except OSError, e:
                 emsg(_("pkg: A system error %(e)s was caught "
                     "executing %(cmd)s") %
                     { "e": e, "cmd": " ".join(cmd) })
Example #11
0
        def destroy_snapshot(self):

                """Destroy a snapshot of the BE being operated on.
                        Note that this will destroy the last created
                        snapshot and does not support destroying
                        multiple snapshots. Create another instance of
                        BootEnv to manage multiple snapshots."""

                if be.beDestroySnapshot(self.be_name, self.snapshot_name) != 0:
                        emsg(_("pkg: unable to destroy snapshot %s") % \
                            self.snapshot_name)
Example #12
0
 def get_ssl_passphrase(*ignored):
         p = None
         try:
                 p = subprocess.Popen(cmdline, shell=True,
                         stdout=subprocess.PIPE,
                         stderr=None)
                 p.wait()
         except Exception, __e:
                 emsg("pkg.depotd: an error occurred while "
                     "executing [%s]; unable to obtain the "
                     "passphrase needed to decrypt the SSL "
                     "private key file: %s" % (cmdline, __e))
                 sys.exit(1)
Example #13
0
File: sign.py Project: aszeszo/test
def usage(usage_error=None, cmd=None, retcode=EXIT_BADOPT):
        """Emit a usage message and optionally prefix it with a more specific
        error message.  Causes program to exit."""

        if usage_error:
                error(usage_error, cmd=cmd)
        emsg (_("""\
Usage:
        pkgsign -s path_or_uri [-acikn] [--no-index] [--no-catalog]
            (fmri|pattern) ...
"""))

        sys.exit(retcode)
Example #14
0
File: pull.py Project: aszeszo/test
def error(text):
        """Emit an error message prefixed by the command name """

        # If we get passed something like an Exception, we can convert
        # it down to a string.
        text = str(text)

        # If the message starts with whitespace, assume that it should come
        # *before* the command-name prefix.
        text_nows = text.lstrip()
        ws = text[:len(text) - len(text_nows)]

        # This has to be a constant value as we can't reliably get our actual
        # program name on all platforms.
        emsg(ws + "pkgrecv: " + text_nows)
Example #15
0
def usage(errmsg="", exitcode=2):
        """Emit a usage message and optionally prefix it with a more specific
        error message.  Causes program to exit."""

        if errmsg:
                emsg("pkgmerge: %s" % errmsg)

        msg(_("""\
Usage:
        pkgmerge [-n] -d dest_repo -s variant=value[,...],src_repo ...
            [-p publisher_prefix ... ] [pkg_fmri_pattern ...]

Options:
        -d dest_repo
                The filesystem path or URI of the target repository to publish
                the merged packages to.  The target repository must already
                exist; new repositories can be created using pkgrepo(1).

        -n
                Perform a trial run with no changes made to the target
                repository.

        -s variant=value,src_repo
                The variant name and value to use for packages from this source,
                followed by the filesystem path or URI of the source repository
                or package archive to retrieve packages from.  Multiple variants
                may be specified separated by commas.  The same variants must
                be named for all sources.  This option may be specified multiple
                times.

        -p publisher_prefix
                The name of the publisher we should merge packages from.  This
                option may be specified multiple times.  If no -p option is
                used, the default is to merge packages from all publishers in
                all source repositories.

        --help or -?
                Displays a usage message.

Environment:
        TMPDIR, TEMP, TMP
                The absolute path of the directory where temporary data should
                be stored during program execution.
"""))

        sys.exit(exitcode)
Example #16
0
File: sign.py Project: aszeszo/test
def error(text, cmd=None):
        """Emit an error message prefixed by the command name """

        if cmd:
                text = "%s: %s" % (cmd, text)
                
        else:
                text = "%s: %s" % (PKG_CLIENT_NAME, text)


        # If the message starts with whitespace, assume that it should come
        # *before* the command-name prefix.
        text_nows = text.lstrip()
        ws = text[:len(text) - len(text_nows)]

        # This has to be a constant value as we can't reliably get our actual
        # program name on all platforms.
        emsg(ws + text_nows)
Example #17
0
def error(text, cmd=None):
        """Emit an error message prefixed by the command name """

        if not isinstance(text, basestring):
                # Assume it's an object that can be stringified.
                text = str(text)

        # If the message starts with whitespace, assume that it should come
        # *before* the command-name prefix.
        text_nows = text.lstrip()
        ws = text[:len(text) - len(text_nows)]

        if cmd:
                text_nows = "%s: %s" % (cmd, text_nows)
                pkg_cmd = "pkgsend "
        else:
                pkg_cmd = "pkgsend: "

        # This has to be a constant value as we can't reliably get our actual
        # program name on all platforms.
        emsg(ws + pkg_cmd + text_nows)
Example #18
0
def usage(usage_error=None, cmd=None, retcode=2):
        """Emit a usage message and optionally prefix it with a more specific
        error message.  Causes program to exit."""

        if usage_error:
                error(usage_error, cmd=cmd)
        emsg (_("""\
Usage:
        pkgdepend [options] command [cmd_options] [operands]

Subcommands:
        pkgdepend generate [-IMm] -d dir [-d dir] [-D name=value] [-k path]
            manifest_path
        pkgdepend [options] resolve [-dmosv] manifest ...

Options:
        -R dir
        --help or -?
Environment:
        PKG_IMAGE"""))

        sys.exit(retcode)
Example #19
0
        def activate_image(self):

                """Activate a clone of the BE being operated on.
                        If were operating on a non-live BE then
                        destroy the snapshot."""

                def exec_cmd(cmd):
                        ret = 0
                        try:
                                ret = subprocess.call(cmd,
                                    stdout = file("/dev/null"),
                                    stderr = subprocess.STDOUT)
                        except OSError, e:
                                emsg(_("pkg: A system error %(e)s was caught "
                                    "executing %(cmd)s") %
                                    { "e": e, "cmd": " ".join(cmd) })

                        if ret != 0:
                                emsg(_("pkg: '%(cmd)s' failed. \nwith a "
                                    "return code of %(ret)d.") %
                                    { "cmd": " ".join(cmd), "ret": ret })
                                return
Example #20
0
def format_update_error(e):
        # This message is displayed to the user whenever an
        # ImageFormatUpdateNeeded exception is encountered.
        emsg("\n")
        emsg(str(e))
        emsg(_("To continue, the target image must be upgraded "
            "before it can be used.  See pkg(1) update-format for more "
            "information."))
Example #21
0
def usage(usage_error=None, cmd=None, retcode=EXIT_BADOPT):
    """Emit a usage message and optionally prefix it with a more specific
        error message.  Causes program to exit."""

    if usage_error:
        error(usage_error, cmd=cmd)
    emsg(
        _("""\
Usage:
        pkgdepend [options] command [cmd_options] [operands]

Subcommands:
        pkgdepend generate [-IMm] -d dir [-d dir] [-D name=value] [-k path]
            manifest_file
        pkgdepend resolve [-EmoSv] [-d output_dir]
            [-e external_package_file]... [-s suffix] manifest_file ...

Options:
        -R dir
        --help or -?
Environment:
        PKG_IMAGE"""))

    sys.exit(retcode)
Example #22
0
    def download_done(self):
        """ Call when all downloading is finished """
        if self.dl_goal_nbytes != 0:
            self.dl_output_done()

        if self.dl_cur_npkgs != self.dl_goal_npkgs:
            emsg("\nExpected %s pkgs, received %s pkgs instead." % (self.dl_goal_npkgs, self.dl_cur_npkgs))
        if self.dl_cur_nfiles != self.dl_goal_nfiles:
            emsg("\nExpected %s files, received %s files instead." % (self.dl_goal_nfiles, self.dl_cur_nfiles))
        if self.dl_cur_nbytes != self.dl_goal_nbytes:
            emsg("\nExpected %s bytes, received %s bytes instead." % (self.dl_goal_nbytes, self.dl_cur_nbytes))

        assert self.dl_cur_npkgs == self.dl_goal_npkgs
        assert self.dl_cur_nfiles == self.dl_goal_nfiles
        assert self.dl_cur_nbytes == self.dl_goal_nbytes
Example #23
0
        def download_done(self):
                """ Call when all downloading is finished """
                if self.dl_goal_nbytes != 0:
                        self.dl_output_done()

                if self.dl_cur_npkgs != self.dl_goal_npkgs:
                        emsg("\nExpected %s pkgs, received %s pkgs instead." %
                            (self.dl_goal_npkgs, self.dl_cur_npkgs))
                if self.dl_cur_nfiles != self.dl_goal_nfiles:
                        emsg("\nExpected %s files, received %s files instead."
                            % (self.dl_goal_nfiles, self.dl_cur_nfiles))
                if self.dl_cur_nbytes != self.dl_goal_nbytes:
                        emsg("\nExpected %s bytes, received %s bytes instead."
                            % (self.dl_goal_nbytes, self.dl_cur_nbytes))

                assert self.dl_cur_npkgs == self.dl_goal_npkgs
                assert self.dl_cur_nfiles == self.dl_goal_nfiles
                assert self.dl_cur_nbytes == self.dl_goal_nbytes
Example #24
0
def main_func():
    if len(sys.argv) != 2:
        emsg(_("pkg.migrate takes a single directory as a paramter."))
        return 2

    dir_loc = os.path.abspath(sys.argv[1])

    if not os.path.isdir(dir_loc):
        emsg(_("The argument must be a directory to migrate from older " "layouts to the current\npreferred layout."))
        return 2

    fm = file_manager.FileManager(root=dir_loc, readonly=False)
    try:
        for f in fm.walk():
            # A non-readonly FileManager will move a file under a
            # non-preferred layout to the preferred layout during a
            # lookup.
            fm.lookup(f)
    except file_manager.UnrecognizedFilePaths, e:
        emsg(e)
        return 1
Example #25
0
def main_func():
        if len(sys.argv) != 2:
                emsg(_("pkg.migrate takes a single directory as a paramter."))
                return 2
        
        dir_loc = os.path.abspath(sys.argv[1])

        if not os.path.isdir(dir_loc):
                emsg(_("The argument must be a directory to migrate from older "
                    "layouts to the current\npreferred layout."))
                return 2

        fm = file_manager.FileManager(root=dir_loc, readonly=False)
        try:
                for f in fm.walk():
                        # A non-readonly FileManager will move a file under a
                        # non-preferred layout to the preferred layout during a
                        # lookup.
                        fm.lookup(f)
        except file_manager.UnrecognizedFilePaths as e:
                emsg(e)
                return 1
        return 0
Example #26
0
        def read_publisher(self, meta_root, cp, s):
                # publisher block has alias, prefix, origin, and mirrors
                changed = False
                try:
                        alias = cp.get(s, "alias")
                except ConfigParser.NoOptionError:
                        alias = None

                prefix = cp.get(s, "prefix")

                if prefix.startswith(fmri.PREF_PUB_PFX):
                        raise RuntimeError(
                            "Invalid Publisher name: %s" % prefix)

                origin = cp.get(s, "origin")
                try:
                        d = cp.get(s, "disabled")
                except ConfigParser.NoOptionError:
                        d = 'False'
                disabled = d.lower() in ("true", "yes")

                mir_str = cp.get(s, "mirrors")
                if mir_str == "None":
                        mirrors = []
                else:
                        mirrors = self.read_list(mir_str)

                try:
                        ssl_key = cp.get(s, "ssl_key")
                        if ssl_key == "None":
                                ssl_key = None
                except ConfigParser.NoOptionError:
                        ssl_key = None

                try:
                        ssl_cert = cp.get(s, "ssl_cert")
                        if ssl_cert == "None":
                                ssl_cert = None
                except ConfigParser.NoOptionError:
                        ssl_cert = None

                try:
                        # XXX this should really be client_uuid, but is being
                        # left with this name for compatibility with older
                        # clients.
                        client_uuid = cp.get(s, "uuid")
                        if client_uuid == "None":
                                client_uuid = None
                except ConfigParser.NoOptionError:
                        client_uuid = None

                # Load selected repository data.
                # XXX this is temporary until a switch to a more expressive
                # configuration format is made.
                repo_data = {
                    "collection_type": None,
                    "description": None,
                    "legal_uris": None,
                    "name": None,
                    "refresh_seconds": None,
                    "registered": None,
                    "registration_uri": None,
                    "related_uris": None,
                    "sort_policy": None,
                }

                for key in repo_data:
                        try:
                                val = cp.get(s, "repo.%s" % key)
                                if key.endswith("_uris"):
                                        val = self.read_list(val)
                                        if val == "None":
                                                val = []
                                else:
                                        if val == "None":
                                                val = None
                                repo_data[key] = val
                        except ConfigParser.NoOptionError:
                                if key.endswith("_uris"):
                                        repo_data[key] = []
                                else:
                                        repo_data[key] = None

                # Normalize/sanitize repository data.
                val = repo_data["registered"]
                if val is not None and val.lower() in ("true", "yes", "1"):
                        repo_data["registered"] = True
                else:
                        repo_data["registered"] = False

                for attr in ("collection_type", "sort_policy"):
                        if not repo_data[attr]:
                                # Assume default value for attr.
                                del repo_data[attr]

                if repo_data["refresh_seconds"] is None:
                        repo_data["refresh_seconds"] = \
                            REPO_REFRESH_SECONDS_DEFAULT

                # Guard against invalid configuration for ssl information. If
                # this isn't done, the user won't be able to load the client
                # to fix the problem.
                if not origin.startswith("https"):
                        ssl_key = None
                        ssl_cert = None

                #
                # For zones, where the reachability of an absolute path
                # changes depending on whether you're in the zone or not.  So
                # we have a different policy: ssl_key and ssl_cert are treated
                # as zone root relative.
                #
                ngz = self.variants.get("variant.opensolaris.zone",
                    "global") == "nonglobal"

                if ssl_key:
                        if ngz:
                                ssl_key = os.path.normpath(self.__imgroot +
                                    os.sep + ssl_key)
                        else:
                                ssl_key = os.path.abspath(ssl_key)
                        if not os.path.exists(ssl_key):
                                # XXX need client messaging framework
                                emsg(api_errors.NoSuchKey(ssl_key, uri=origin,
                                    publisher=prefix))
                                ssl_key = None

                if ssl_cert:
                        if ngz:
                                ssl_cert = os.path.normpath(self.__imgroot +
                                    os.sep + ssl_cert)
                        else:
                                ssl_cert = os.path.abspath(ssl_cert)
                        if not os.path.exists(ssl_cert):
                                # XXX need client messaging framework
                                emsg(api_errors.NoSuchCertificate(ssl_cert,
                                    uri=origin, publisher=prefix))
                                ssl_cert = None

                r = publisher.Repository(**repo_data)
                r.add_origin(origin, ssl_cert=ssl_cert, ssl_key=ssl_key)
                for m in mirrors:
                        r.add_mirror(m, ssl_cert=ssl_cert, ssl_key=ssl_key)

                # Root directory for this publisher's metadata.
                pmroot = os.path.join(meta_root, prefix)

                pub = publisher.Publisher(prefix, alias=alias,
                    client_uuid=client_uuid, disabled=disabled,
                    meta_root=pmroot, repositories=[r])

                # write out the UUID if it was set
                if pub.client_uuid != client_uuid:
                        changed = True

                return prefix, pub, changed
Example #27
0
        def __init__(self, root):
                self.be_name = None
                self.dataset = None
                self.be_name_clone = None
                self.clone_dir = None
                self.img = None
                self.is_live_BE = False
                self.is_valid = False
                self.snapshot_name = None
                self.root = root
                rc = 0

                assert root != None

                # Check for the old beList() API since pkg(1) can be
                # back published and live on a system without the latest libbe.
                beVals = be.beList()
                if isinstance(beVals[0], int):
                        rc, self.beList = beVals
                else:
                        self.beList = beVals

                # Happens e.g. in zones (at least, for now)
                if not self.beList or rc != 0:
                        raise RuntimeError, "nobootenvironments"

                # Need to find the name of the BE we're operating on in order
                # to create a snapshot and/or a clone of the BE.

                for i, beVals in enumerate(self.beList):
                        # pkg(1) expects a directory as the target of an
                        # operation. BootEnv needs to determine if this target
                        # directory maps to a BE. If a bogus directory is
                        # provided to pkg(1) via -R, then pkg(1) just updates
                        # '/' which also causes BootEnv to manage '/' as well.
                        # This should be fixed before this class is ever
                        # instantiated.

                        be_name = beVals.get("orig_be_name")

                        # If we're not looking at a boot env entry or an
                        # entry that is not mounted then continue.
                        if not be_name or not beVals.get("mounted"):
                                continue

                        # Check if we're operating on the live BE.
                        # If so it must also be active. If we are not
                        # operating on the live BE, then verify
                        # that the mountpoint of the BE matches
                        # the -R argument passed in by the user.
                        if root == '/':
                                if not beVals.get("active"):
                                        continue
                                else:
                                        self.is_live_BE = True
                        else:
                                if beVals.get("mountpoint") != root:
                                        continue

                        # Set the needed BE components so snapshots
                        # and clones can be managed.
                        self.be_name = be_name

                        self.dataset = beVals.get("dataset")

                        # Let libbe provide the snapshot name
                        err, snapshot_name = be.beCreateSnapshot(self.be_name)
                        self.clone_dir = tempfile.mkdtemp()

                        # Check first field for failure.
                        # 2nd field is the returned snapshot name
                        if err == 0:
                                self.snapshot_name = snapshot_name
                        else:
                                emsg(_("pkg: unable to create an auto "
                                    "snapshot. pkg recovery is disabled."))
                                raise RuntimeError, "recoveryDisabled"
                        self.is_valid = True
                        break

                else:
                        # We will get here if we don't find find any BE's. e.g
                        # if were are on UFS.
                        raise RuntimeError, "recoveryDisabled"
    def read_publisher(self, meta_root, cp, s):
        # publisher block has alias, prefix, origin, and mirrors
        changed = False
        try:
            alias = cp.get(s, "alias")
        except ConfigParser.NoOptionError:
            alias = None

        prefix = cp.get(s, "prefix")

        if prefix.startswith(fmri.PREF_PUB_PFX):
            raise RuntimeError("Invalid Publisher name: %s" % prefix)

        origin = cp.get(s, "origin")
        try:
            d = cp.get(s, "disabled")
        except ConfigParser.NoOptionError:
            d = 'False'
        disabled = d.lower() in ("true", "yes")

        mir_str = cp.get(s, "mirrors")
        if mir_str == "None":
            mirrors = []
        else:
            mirrors = self.read_list(mir_str)

        try:
            ssl_key = cp.get(s, "ssl_key")
            if ssl_key == "None":
                ssl_key = None
        except ConfigParser.NoOptionError:
            ssl_key = None

        try:
            ssl_cert = cp.get(s, "ssl_cert")
            if ssl_cert == "None":
                ssl_cert = None
        except ConfigParser.NoOptionError:
            ssl_cert = None

        try:
            # XXX this should really be client_uuid, but is being
            # left with this name for compatibility with older
            # clients.
            client_uuid = cp.get(s, "uuid")
            if client_uuid == "None":
                client_uuid = None
        except ConfigParser.NoOptionError:
            client_uuid = None

        # Load selected repository data.
        # XXX this is temporary until a switch to a more expressive
        # configuration format is made.
        repo_data = {
            "collection_type": None,
            "description": None,
            "legal_uris": None,
            "name": None,
            "refresh_seconds": None,
            "registered": None,
            "registration_uri": None,
            "related_uris": None,
            "sort_policy": None,
        }

        for key in repo_data:
            try:
                val = cp.get(s, "repo.%s" % key)
                if key.endswith("_uris"):
                    val = self.read_list(val)
                    if val == "None":
                        val = []
                else:
                    if val == "None":
                        val = None
                repo_data[key] = val
            except ConfigParser.NoOptionError:
                if key.endswith("_uris"):
                    repo_data[key] = []
                else:
                    repo_data[key] = None

        # Normalize/sanitize repository data.
        val = repo_data["registered"]
        if val is not None and val.lower() in ("true", "yes", "1"):
            repo_data["registered"] = True
        else:
            repo_data["registered"] = False

        for attr in ("collection_type", "sort_policy"):
            if not repo_data[attr]:
                # Assume default value for attr.
                del repo_data[attr]

        if repo_data["refresh_seconds"] is None:
            repo_data["refresh_seconds"] = \
                REPO_REFRESH_SECONDS_DEFAULT

        # Guard against invalid configuration for ssl information. If
        # this isn't done, the user won't be able to load the client
        # to fix the problem.
        if not origin.startswith("https"):
            ssl_key = None
            ssl_cert = None

        #
        # For zones, where the reachability of an absolute path
        # changes depending on whether you're in the zone or not.  So
        # we have a different policy: ssl_key and ssl_cert are treated
        # as zone root relative.
        #
        ngz = self.variants.get("variant.opensolaris.zone",
                                "global") == "nonglobal"

        if ssl_key:
            if ngz:
                ssl_key = os.path.normpath(self.__imgroot + os.sep + ssl_key)
            else:
                ssl_key = os.path.abspath(ssl_key)
            if not os.path.exists(ssl_key):
                # XXX need client messaging framework
                emsg(
                    api_errors.NoSuchKey(ssl_key, uri=origin,
                                         publisher=prefix))
                ssl_key = None

        if ssl_cert:
            if ngz:
                ssl_cert = os.path.normpath(self.__imgroot + os.sep + ssl_cert)
            else:
                ssl_cert = os.path.abspath(ssl_cert)
            if not os.path.exists(ssl_cert):
                # XXX need client messaging framework
                emsg(
                    api_errors.NoSuchCertificate(ssl_cert,
                                                 uri=origin,
                                                 publisher=prefix))
                ssl_cert = None

        r = publisher.Repository(**repo_data)
        r.add_origin(origin, ssl_cert=ssl_cert, ssl_key=ssl_key)
        for m in mirrors:
            r.add_mirror(m, ssl_cert=ssl_cert, ssl_key=ssl_key)

        # Root directory for this publisher's metadata.
        pmroot = os.path.join(meta_root, prefix)

        pub = publisher.Publisher(prefix,
                                  alias=alias,
                                  client_uuid=client_uuid,
                                  disabled=disabled,
                                  meta_root=pmroot,
                                  repositories=[r])

        # write out the UUID if it was set
        if pub.client_uuid != client_uuid:
            changed = True

        return prefix, pub, changed
Example #29
0
def error(message=""):
    """Emit an error message prefixed by the command name. """
    misc.emsg("pkglint: {0}".format(message))

    if logger is not None:
        logger.error(_("Error: {0}").format(message))
Example #30
0
def generate(args):
    """Produce a list of file dependencies from a manfiest and a proto
        area."""
    try:
        opts, pargs = getopt.getopt(args, "d:D:Ik:Mm?", ["help"])
    except getopt.GetoptError as e:
        usage(_("illegal global option -- {0}").format(e.opt))

    remove_internal_deps = True
    echo_manf = False
    show_missing = False
    show_usage = False
    isa_paths = []
    run_paths = []
    platform_paths = []
    dyn_tok_conv = {}
    proto_dirs = []

    for opt, arg in opts:
        if opt == "-d":
            if not os.path.isdir(arg):
                usage(_("The proto directory {0} could not be "
                        "found.".format(arg)),
                      retcode=2)
            proto_dirs.append(os.path.abspath(arg))
        elif opt == "-D":
            try:
                dyn_tok_name, dyn_tok_val = arg.split("=", 1)
            except:
                usage(_("-D arguments must be of the form " "'name=value'."))
            if not dyn_tok_name[0] == "$":
                dyn_tok_name = "$" + dyn_tok_name
            dyn_tok_conv.setdefault(dyn_tok_name, []).append(dyn_tok_val)
        elif opt == "-I":
            remove_internal_deps = False
        elif opt == "-k":
            run_paths.append(arg)
        elif opt == "-m":
            echo_manf = True
        elif opt == "-M":
            show_missing = True
        elif opt in ("--help", "-?"):
            show_usage = True
    if show_usage:
        usage(retcode=0)
    if len(pargs) > 2 or len(pargs) < 1:
        usage(_("Generate only accepts one or two arguments."))

    if "$ORIGIN" in dyn_tok_conv:
        usage(
            _("ORIGIN may not be specified using -D. It will be "
              "inferred from the\ninstall paths of the files."))

    retcode = 0

    manf = pargs[0]

    if not os.path.isfile(manf):
        usage(_("The manifest file {0} could not be found.").format(manf),
              retcode=2)

    if len(pargs) > 1:
        if not os.path.isdir(pargs[1]):
            usage(_("The proto directory {0} could not be found.").format(
                pargs[1]),
                  retcode=2)
        proto_dirs.insert(0, os.path.abspath(pargs[1]))
    if not proto_dirs:
        usage(_("At least one proto directory must be provided."), retcode=2)

    try:
        ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(
            manf, proto_dirs, dyn_tok_conv, run_paths, remove_internal_deps)
    except (actions.MalformedActionError, actions.UnknownActionError) as e:
        error(
            _("Could not parse manifest {manifest} because of the "
              "following line:\n{line}").format(manifest=manf,
                                                line=e.actionstr))
        return 1
    except api_errors.ApiException as e:
        error(e)
        return 1

    if echo_manf:
        fh = open(manf, "rb")
        for l in fh:
            msg(l.rstrip())
        fh.close()

    for d in sorted(ds):
        msg(d)

    for key, value in pkg_attrs.iteritems():
        msg(actions.attribute.AttributeAction(**{key: value}))

    if show_missing:
        for m in ms:
            emsg(m)

    for e in es:
        emsg(e)
        retcode = 1
    return retcode
Example #31
0
    def restore_install_uninstall(self):
        """Restore a failed install or uninstall attempt.
                        Clone the snapshot, mount the BE and
                        notify user of its existence. Rollback
                        if not operating on a live BE"""

        if self.is_live_BE:
            # Create a new BE based on the previously taken
            # snapshot.

            ret, self.be_name_clone, not_used = \
                be.beCopy(None, self.be_name, self.snapshot_name)
            if ret != 0:
                # If the above beCopy() failed we will try it
                # without expecting the BE clone name to be
                # returned by libbe. We do this in case an old
                # version of libbe is on a system with
                # a new version of pkg.
                self.be_name_clone = self.be_name + "_" + \
                    self.snapshot_name

                ret, not_used, not_used2 = \
                    be.beCopy(self.be_name_clone, \
                    self.be_name, self.snapshot_name)
                if ret != 0:
                    emsg(_("pkg: unable to create BE %s") \
                       % self.be_name_clone)
                    return

            if be.beMount(self.be_name_clone, self.clone_dir) != 0:
                emsg(
                    _("pkg: unable to mount BE %(name)s "
                      "on %(clone_dir)s") % {
                          "name": self.be_name_clone,
                          "clone_dir": self.clone_dir
                      })
                return

            emsg(
                _("The Boot Environment %(name)s failed to be "
                  "updated. A snapshot was taken before the failed "
                  "attempt and is mounted here %(clone_dir)s. Use "
                  "'beadm unmount %(clone_name)s' and then 'beadm "
                  "activate %(clone_name)s' if you wish to boot "
                  "to this BE.") % {
                      "name": self.be_name,
                      "clone_dir": self.clone_dir,
                      "clone_name": self.be_name_clone
                  })
        else:
            if be.beRollback(self.be_name, self.snapshot_name) != 0:
                emsg("pkg: unable to rollback BE %s" % \
                    self.be_name)

            self.destroy_snapshot()

            emsg(
                _("The Boot Environment %s failed to be updated. "
                  "A snapshot was taken before the failed attempt "
                  "and has been restored so no changes have been "
                  "made to %s.") % (self.be_name, self.be_name))
Example #32
0
                proxy_conf = {
                        "tools.proxy.on": True,
                        "tools.proxy.local": "",
                        "tools.proxy.base": proxy_base
                }

                # Now merge or add our proxy configuration information into the
                # existing configuration.
                for entry in proxy_conf:
                        conf["/"][entry] = proxy_conf[entry]

        scfg.acquire_in_flight()
        try:
                scfg.acquire_catalog(rebuild=rebuild, verbose=True)
        except (catalog.CatalogPermissionsException, errors.SvrConfigError), _e:
                emsg("pkg.depotd: %s" % _e)
                sys.exit(1)

        try:
                if nasty:
                        root = cherrypy.Application(depot.NastyDepotHTTP(scfg,
                            repo_config_file))
                else:
                        root = cherrypy.Application(depot.DepotHTTP(scfg,
                            repo_config_file))
        except rc.InvalidAttributeValueError, _e:
                emsg("pkg.depotd: repository.conf error: %s" % _e)
                sys.exit(1)

        try:
                cherrypy.quickstart(root, config=conf)
Example #33
0
def usage(text=None, retcode=2, full=False):
        """Optionally emit a usage message and then exit using the specified
        exit code."""

        if text:
                emsg(text)

        if not full:
                # The full usage message isn't desired.
                emsg(_("Try `pkg.depotd --help or -?' for more "
                    "information."))
                sys.exit(retcode)

        print("""\
Usage: /usr/lib/pkg.depotd [-a address] [-d inst_root] [-p port] [-s threads]
           [-t socket_timeout] [--cfg] [--content-root]
           [--disable-ops op[/1][,...]] [--debug feature_list]
           [--image-root dir] [--log-access dest] [--log-errors dest]
           [--mirror] [--nasty] [--nasty-sleep] [--proxy-base url]
           [--readonly] [--ssl-cert-file] [--ssl-dialog] [--ssl-key-file]
           [--sort-file-max-size size] [--writable-root dir]

        -a address      The IP address on which to listen for connections.  The
                        default value is 0.0.0.0 (INADDR_ANY) which will listen
                        on all active interfaces.  To listen on all active IPv6
                        interfaces, use '::'.
        -d inst_root    The file system path at which the server should find its
                        repository data.  Required unless PKG_REPO has been set
                        in the environment.
        -p port         The port number on which the instance should listen for
                        incoming package requests.  The default value is 80 if
                        ssl certificate and key information has not been
                        provided; otherwise, the default value is 443.
        -s threads      The number of threads that will be started to serve
                        requests.  The default value is 10.
        -t timeout      The maximum number of seconds the server should wait for
                        a response from a client before closing a connection.
                        The default value is 60.
        --cfg           The pathname of the file to use when reading and writing
                        depot configuration data, or a fully qualified service
                        fault management resource identifier (FMRI) of the SMF
                        service or instance to read configuration data from.
        --content-root  The file system path to the directory containing the
                        the static and other web content used by the depot's
                        browser user interface.  The default value is
                        '/usr/share/lib/pkg'.
        --disable-ops   A comma separated list of operations that the depot
                        should not configure.  If, for example, you wanted
                        to omit loading search v1, 'search/1' should be
                        provided as an argument, or to disable all search
                        operations, simply 'search'.
        --debug         The name of a debug feature to enable; or a whitespace
                        or comma separated list of features to enable.
                        Possible values are: headers, hash=sha1+sha256,
                        hash=sha256, hash=sha1+sha512_256, hash=sha512_256
        --image-root    The path to the image whose file information will be
                        used as a cache for file data.
        --log-access    The destination for any access related information
                        logged by the depot process.  Possible values are:
                        stderr, stdout, none, or an absolute pathname.  The
                        default value is stdout if stdout is a tty; otherwise
                        the default value is none.
        --log-errors    The destination for any errors or other information
                        logged by the depot process.  Possible values are:
                        stderr, stdout, none, or an absolute pathname.  The
                        default value is stderr.
        --mirror        Package mirror mode; publishing and metadata operations
                        disallowed.  Cannot be used with --readonly or
                        --rebuild.
        --nasty         Instruct the server to misbehave.  At random intervals
                        it will time-out, send bad responses, hang up on
                        clients, and generally be hostile.  The option
                        takes a value (1 to 100) for how nasty the server
                        should be.
        --nasty-sleep   In nasty mode (see --nasty), how many seconds to
                        randomly sleep when a random sleep occurs.
        --proxy-base    The url to use as the base for generating internal
                        redirects and content.
        --readonly      Read-only operation; modifying operations disallowed.
                        Cannot be used with --mirror or --rebuild.
        --ssl-cert-file The absolute pathname to a PEM-encoded Certificate file.
                        This option must be used with --ssl-key-file.  Usage of
                        this option will cause the depot to only respond to SSL
                        requests on the provided port.
        --ssl-dialog    Specifies what method should be used to obtain the
                        passphrase needed to decrypt the file specified by
                        --ssl-key-file.  Supported values are: builtin,
                        exec:/path/to/program, smf, or an SMF FMRI.  The
                        default value is builtin.  If smf is specified, an
                        SMF FMRI must be provided using the --cfg option.
        --ssl-key-file  The absolute pathname to a PEM-encoded Private Key file.
                        This option must be used with --ssl-cert-file.  Usage of
                        this option will cause the depot to only respond to SSL
                        requests on the provided port.
        --sort-file-max-size
                        The maximum size of the indexer sort file. Used to
                        limit the amount of RAM the depot uses for indexing,
                        or increase it for speed.
        --writable-root The path to a directory to which the program has write
                        access.  Used with --readonly to allow server to
                        create needed files, such as search indices, without
                        needing write access to the package information.
Options:
        --help or -?

Environment:
        PKG_REPO                Used as default inst_root if -d not provided.
        PKG_DEPOT_CONTENT       Used as default content_root if --content-root
                                not provided.""")
        sys.exit(retcode)
Example #34
0
                dconf.set_property("pkg", "socket_timeout",
                    SOCKET_TIMEOUT_DEFAULT)
                socket_timeout = dconf.get_property("pkg", "socket_timeout")

        threads = dconf.get_property("pkg", "threads")
        if not threads:
                dconf.set_property("pkg", "threads", THREADS_DEFAULT)
                threads = dconf.get_property("pkg", "threads")

        # If the program is going to reindex, the port is irrelevant since
        # the program will not bind to a port.
        if not exit_ready:
                try:
                        cherrypy.process.servers.check_port(address, port)
                except Exception as e:
                        emsg("pkg.depotd: unable to bind to the specified "
                            "port: {0:d}. Reason: {1}".format(port, e))
                        sys.exit(1)
        else:
                # Not applicable if we're not going to serve content
                dconf.set_property("pkg", "content_root", "")

        # Any relative paths should be made absolute using pkg_root.  'pkg_root'
        # is a special property that was added to enable internal deployment of
        # multiple disparate versions of the pkg.depotd software.
        pkg_root = dconf.get_property("pkg", "pkg_root")

        repo_config_file = dconf.get_property("pkg", "cfg_file")
        if repo_config_file and not os.path.isabs(repo_config_file):
                repo_config_file = os.path.join(pkg_root, repo_config_file)

        if content_root and not os.path.isabs(content_root):
Example #35
0
def usage(text):
    if text:
        emsg(text)

    print """\
Usage: /usr/lib/pkg.depotd [-d repo_dir] [-p port] [-s threads]
           [-t socket_timeout] [--cfg-file] [--content-root] [--debug]
           [--log-access dest] [--log-errors dest] [--mirror] [--nasty]
           [--proxy-base url] [--readonly] [--rebuild] [--ssl-cert-file]
           [--ssl-dialog] [--ssl-key-file] [--writable-root dir]

        --cfg-file      The pathname of the file from which to read and to
                        write configuration information.
        --content-root  The file system path to the directory containing the
                        the static and other web content used by the depot's
                        browser user interface.  The default value is
                        '/usr/share/lib/pkg'.
        --debug         The name of a debug feature to enable; or a whitespace
                        or comma separated list of features to enable.  Possible
                        values are: headers.
        --log-access    The destination for any access related information
                        logged by the depot process.  Possible values are:
                        stderr, stdout, none, or an absolute pathname.  The
                        default value is stdout if stdout is a tty; otherwise
                        the default value is none.
        --log-errors    The destination for any errors or other information
                        logged by the depot process.  Possible values are:
                        stderr, stdout, none, or an absolute pathname.  The
                        default value is stderr.
        --mirror        Package mirror mode; publishing and metadata operations
                        disallowed.  Cannot be used with --readonly or
                        --rebuild.
        --nasty         Instruct the server to misbehave.  At random intervals
                        it will time-out, send bad responses, hang up on
                        clients, and generally be hostile.  The option
                        takes a value (1 to 100) for how nasty the server
                        should be.
        --proxy-base    The url to use as the base for generating internal
                        redirects and content.
        --readonly      Read-only operation; modifying operations disallowed.
                        Cannot be used with --mirror or --rebuild.
        --rebuild       Re-build the catalog from pkgs in depot.  Cannot be
                        used with --mirror or --readonly.
        --ssl-cert-file The absolute pathname to a PEM-encoded Certificate file.
                        This option must be used with --ssl-key-file.  Usage of
                        this option will cause the depot to only respond to SSL
                        requests on the provided port.
        --ssl-dialog    Specifies what method should be used to obtain the
                        passphrase needed to decrypt the file specified by
                        --ssl-key-file.  Supported values are: builtin,
                        exec:/path/to/program, or smf:fmri.  The default value
                        is builtin.
        --ssl-key-file  The absolute pathname to a PEM-encoded Private Key file.
                        This option must be used with --ssl-cert-file.  Usage of
                        this option will cause the depot to only respond to SSL
                        requests on the provided port.
        --writable-root The path to a directory to which the program has write
                        access.  Used with --readonly to allow server to
                        create needed files, such as search indices, without
                        needing write access to the package information.
"""
    sys.exit(2)
Example #36
0
def usage(text=None, retcode=2, full=False):
        """Optionally emit a usage message and then exit using the specified
        exit code."""

        if text:
                emsg(text)

        if not full:
                # The full usage message isn't desired.
                emsg(_("Try `pkg.depotd --help or -?' for more "
                    "information."))
                sys.exit(retcode)

        print """\
Usage: /usr/lib/pkg.depotd [-a address] [-d inst_root] [-p port] [-s threads]
           [-t socket_timeout] [--cfg] [--content-root]
           [--disable-ops op[/1][,...]] [--debug feature_list]
           [--image-root dir] [--log-access dest] [--log-errors dest]
           [--mirror] [--nasty] [--nasty-sleep] [--proxy-base url]
           [--readonly] [--ssl-cert-file] [--ssl-dialog] [--ssl-key-file]
           [--sort-file-max-size size] [--writable-root dir]

        -a address      The IP address on which to listen for connections.  The
                        default value is 0.0.0.0 (INADDR_ANY) which will listen
                        on all active interfaces.  To listen on all active IPv6
                        interfaces, use '::'.
        -d inst_root    The file system path at which the server should find its
                        repository data.  Required unless PKG_REPO has been set
                        in the environment.
        -p port         The port number on which the instance should listen for
                        incoming package requests.  The default value is 80 if
                        ssl certificate and key information has not been
                        provided; otherwise, the default value is 443.
        -s threads      The number of threads that will be started to serve
                        requests.  The default value is 10.
        -t timeout      The maximum number of seconds the server should wait for
                        a response from a client before closing a connection.
                        The default value is 60.
        --cfg           The pathname of the file to use when reading and writing
                        depot configuration data, or a fully qualified service
                        fault management resource identifier (FMRI) of the SMF
                        service or instance to read configuration data from.
        --content-root  The file system path to the directory containing the
                        the static and other web content used by the depot's
                        browser user interface.  The default value is
                        '/usr/share/lib/pkg'.
        --disable-ops   A comma separated list of operations that the depot
                        should not configure.  If, for example, you wanted
                        to omit loading search v1, 'search/1' should be
                        provided as an argument, or to disable all search
                        operations, simply 'search'.
        --debug         The name of a debug feature to enable; or a whitespace
                        or comma separated list of features to enable.
                        Possible values are: headers.
        --image-root    The path to the image whose file information will be
                        used as a cache for file data.
        --log-access    The destination for any access related information
                        logged by the depot process.  Possible values are:
                        stderr, stdout, none, or an absolute pathname.  The
                        default value is stdout if stdout is a tty; otherwise
                        the default value is none.
        --log-errors    The destination for any errors or other information
                        logged by the depot process.  Possible values are:
                        stderr, stdout, none, or an absolute pathname.  The
                        default value is stderr.
        --mirror        Package mirror mode; publishing and metadata operations
                        disallowed.  Cannot be used with --readonly or
                        --rebuild.
        --nasty         Instruct the server to misbehave.  At random intervals
                        it will time-out, send bad responses, hang up on
                        clients, and generally be hostile.  The option
                        takes a value (1 to 100) for how nasty the server
                        should be.
        --nasty-sleep   In nasty mode (see --nasty), how many seconds to
                        randomly sleep when a random sleep occurs.
        --proxy-base    The url to use as the base for generating internal
                        redirects and content.
        --readonly      Read-only operation; modifying operations disallowed.
                        Cannot be used with --mirror or --rebuild.
        --ssl-cert-file The absolute pathname to a PEM-encoded Certificate file.
                        This option must be used with --ssl-key-file.  Usage of
                        this option will cause the depot to only respond to SSL
                        requests on the provided port.
        --ssl-dialog    Specifies what method should be used to obtain the
                        passphrase needed to decrypt the file specified by
                        --ssl-key-file.  Supported values are: builtin,
                        exec:/path/to/program, smf, or an SMF FMRI.  The
                        default value is builtin.  If smf is specified, an
                        SMF FMRI must be provided using the --cfg option.
        --ssl-key-file  The absolute pathname to a PEM-encoded Private Key file.
                        This option must be used with --ssl-cert-file.  Usage of
                        this option will cause the depot to only respond to SSL
                        requests on the provided port.
        --sort-file-max-size
                        The maximum size of the indexer sort file. Used to
                        limit the amount of RAM the depot uses for indexing,
                        or increase it for speed.
        --writable-root The path to a directory to which the program has write
                        access.  Used with --readonly to allow server to
                        create needed files, such as search indices, without
                        needing write access to the package information.
Options:
        --help or -?

Environment:
        PKG_REPO                Used as default inst_root if -d not provided.
        PKG_DEPOT_CONTENT       Used as default content_root if --content-root
                                not provided."""
        sys.exit(retcode)
Example #37
0
                dconf.set_property("pkg", "socket_timeout",
                    SOCKET_TIMEOUT_DEFAULT)
                socket_timeout = dconf.get_property("pkg", "socket_timeout")

        threads = dconf.get_property("pkg", "threads")
        if not threads:
                dconf.set_property("pkg", "threads", THREADS_DEFAULT)
                threads = dconf.get_property("pkg", "threads")

        # If the program is going to reindex, the port is irrelevant since
        # the program will not bind to a port.
        if not exit_ready:
                try:
                        cherrypy.process.servers.check_port(address, port)
                except Exception, e:
                        emsg("pkg.depotd: unable to bind to the specified "
                            "port: %d. Reason: %s" % (port, e))
                        sys.exit(1)
        else:
                # Not applicable if we're not going to serve content
                dconf.set_property("pkg", "content_root", "")

        # Any relative paths should be made absolute using pkg_root.  'pkg_root'
        # is a special property that was added to enable internal deployment of
        # multiple disparate versions of the pkg.depotd software.
        pkg_root = dconf.get_property("pkg", "pkg_root")

        repo_config_file = dconf.get_property("pkg", "cfg_file")
        if repo_config_file and not os.path.isabs(repo_config_file):
                repo_config_file = os.path.join(pkg_root, repo_config_file)

        if content_root and not os.path.isabs(content_root):
Example #38
0
    def __init__(self, root):
        self.be_name = None
        self.dataset = None
        self.be_name_clone = None
        self.clone_dir = None
        self.img = None
        self.is_live_BE = False
        self.is_valid = False
        self.snapshot_name = None
        self.root = root
        rc = 0

        assert root != None

        # Check for the old beList() API since pkg(1) can be
        # back published and live on a system without the latest libbe.
        beVals = be.beList()
        if isinstance(beVals[0], int):
            rc, self.beList = beVals
        else:
            self.beList = beVals

        # Happens e.g. in zones (at least, for now)
        if not self.beList or rc != 0:
            raise RuntimeError, "nobootenvironments"

        # Need to find the name of the BE we're operating on in order
        # to create a snapshot and/or a clone of the BE.

        for i, beVals in enumerate(self.beList):
            # pkg(1) expects a directory as the target of an
            # operation. BootEnv needs to determine if this target
            # directory maps to a BE. If a bogus directory is
            # provided to pkg(1) via -R, then pkg(1) just updates
            # '/' which also causes BootEnv to manage '/' as well.
            # This should be fixed before this class is ever
            # instantiated.

            be_name = beVals.get("orig_be_name")

            # If we're not looking at a boot env entry or an
            # entry that is not mounted then continue.
            if not be_name or not beVals.get("mounted"):
                continue

            # Check if we're operating on the live BE.
            # If so it must also be active. If we are not
            # operating on the live BE, then verify
            # that the mountpoint of the BE matches
            # the -R argument passed in by the user.
            if root == '/':
                if not beVals.get("active"):
                    continue
                else:
                    self.is_live_BE = True
            else:
                if beVals.get("mountpoint") != root:
                    continue

            # Set the needed BE components so snapshots
            # and clones can be managed.
            self.be_name = be_name

            self.dataset = beVals.get("dataset")

            # Let libbe provide the snapshot name
            err, snapshot_name = be.beCreateSnapshot(self.be_name)
            self.clone_dir = tempfile.mkdtemp()

            # Check first field for failure.
            # 2nd field is the returned snapshot name
            if err == 0:
                self.snapshot_name = snapshot_name
            else:
                emsg(
                    _("pkg: unable to create an auto "
                      "snapshot. pkg recovery is disabled."))
                raise RuntimeError, "recoveryDisabled"
            self.is_valid = True
            break

        else:
            # We will get here if we don't find find any BE's. e.g
            # if were are on UFS.
            raise RuntimeError, "recoveryDisabled"
Example #39
0
                patterns = [
                    pkg.fmri.MatchingPkgFmri(s, "5.11")
                    for s in pfmri_strings
                ]
        except pkg.fmri.FmriError, e:
                abort(err=e)

        matches = catalog.extract_matching_fmris(fmri_list,
            patterns=patterns, constraint=version.CONSTRAINT_AUTO,
            counthash=counthash, matcher=pkg.fmri.glob_match)

        bail = False

        for f in patterns:
                if f not in counthash:
                        emsg(_("No match found for %s") % f.pkg_name)
                        bail = True

        if bail:
                abort()

        return matches

def get_dependencies(src_uri, fmri_list, basedir, tracker):

        old_limit = sys.getrecursionlimit()
        # The user may be recursing 'entire' or 'redistributable'.
        sys.setrecursionlimit(3000)

        s = set()
        for f in fmri_list:
Example #40
0
def usage(text):
        if text:
                emsg(text)

        print """\
Usage: /usr/lib/pkg.depotd [-d repo_dir] [-p port] [-s threads]
           [-t socket_timeout] [--cfg-file] [--content-root] [--debug]
           [--log-access dest] [--log-errors dest] [--mirror] [--nasty]
           [--proxy-base url] [--readonly] [--rebuild] [--ssl-cert-file]
           [--ssl-dialog] [--ssl-key-file] [--writable-root dir]

        --cfg-file      The pathname of the file from which to read and to
                        write configuration information.
        --content-root  The file system path to the directory containing the
                        the static and other web content used by the depot's
                        browser user interface.  The default value is
                        '/usr/share/lib/pkg'.
        --debug         The name of a debug feature to enable; or a whitespace
                        or comma separated list of features to enable.  Possible
                        values are: headers.
        --log-access    The destination for any access related information
                        logged by the depot process.  Possible values are:
                        stderr, stdout, none, or an absolute pathname.  The
                        default value is stdout if stdout is a tty; otherwise
                        the default value is none.
        --log-errors    The destination for any errors or other information
                        logged by the depot process.  Possible values are:
                        stderr, stdout, none, or an absolute pathname.  The
                        default value is stderr.
        --mirror        Package mirror mode; publishing and metadata operations
                        disallowed.  Cannot be used with --readonly or
                        --rebuild.
        --nasty         Instruct the server to misbehave.  At random intervals
                        it will time-out, send bad responses, hang up on
                        clients, and generally be hostile.  The option
                        takes a value (1 to 100) for how nasty the server
                        should be.
        --proxy-base    The url to use as the base for generating internal
                        redirects and content.
        --readonly      Read-only operation; modifying operations disallowed.
                        Cannot be used with --mirror or --rebuild.
        --rebuild       Re-build the catalog from pkgs in depot.  Cannot be
                        used with --mirror or --readonly.
        --ssl-cert-file The absolute pathname to a PEM-encoded Certificate file.
                        This option must be used with --ssl-key-file.  Usage of
                        this option will cause the depot to only respond to SSL
                        requests on the provided port.
        --ssl-dialog    Specifies what method should be used to obtain the
                        passphrase needed to decrypt the file specified by
                        --ssl-key-file.  Supported values are: builtin,
                        exec:/path/to/program, or smf:fmri.  The default value
                        is builtin.
        --ssl-key-file  The absolute pathname to a PEM-encoded Private Key file.
                        This option must be used with --ssl-cert-file.  Usage of
                        this option will cause the depot to only respond to SSL
                        requests on the provided port.
        --writable-root The path to a directory to which the program has write
                        access.  Used with --readonly to allow server to
                        create needed files, such as search indices, without
                        needing write access to the package information.
"""
        sys.exit(2)
Example #41
0
    except pkg.fmri.FmriError, e:
        abort(err=e)

    matches = catalog.extract_matching_fmris(
        fmri_list,
        patterns=patterns,
        constraint=version.CONSTRAINT_AUTO,
        counthash=counthash,
        matcher=pkg.fmri.glob_match,
    )

    bail = False

    for f in patterns:
        if f not in counthash:
            emsg(_("No match found for %s") % f.pkg_name)
            bail = True

    if bail:
        abort()

    return matches


def get_dependencies(src_uri, fmri_list, basedir, tracker):

    old_limit = sys.getrecursionlimit()
    # The user may be recursing 'entire' or 'redistributable'.
    sys.setrecursionlimit(3000)

    s = set()
Example #42
0
        __ret = main_func()
    except api_errors.MissingFileArgumentException as e:
        error("The manifest file {0} could not be found.".format(e.path))
        __ret = 1
    except api_errors.VersionException as __e:
        error(
            _("The {cmd} command appears out of sync with the lib"
              "raries provided\nby pkg:/package/pkg. The client version "
              "is {client} while the library\nAPI version is {api}").format(
                  cmd=PKG_CLIENT_NAME,
                  client=__e.received_version,
                  api=__e.expected_version))
        __ret = 1
    except api_errors.ApiException as e:
        error(e)
        __ret = 1
    except RuntimeError as _e:
        emsg("{0}: {1}".format(PKG_CLIENT_NAME, _e))
        __ret = 1
    except (PipeError, KeyboardInterrupt):
        # We don't want to display any messages here to prevent
        # possible further broken pipe (EPIPE) errors.
        __ret = 1
    except SystemExit as _e:
        raise _e
    except:
        traceback.print_exc()
        error(misc.get_traceback_message())
        __ret = 99
    sys.exit(__ret)
Example #43
0
        if echo_manf:
                fh = open(manf, "rb")
                for l in fh:
                        msg(l.rstrip())
                fh.close()

        for d in sorted(ds):
                msg(d)

        for key, value in pkg_attrs.iteritems():
                msg(actions.attribute.AttributeAction(**{key: value}))

        if show_missing:
                for m in ms:
                        emsg(m)

        for e in es:
                emsg(e)
                retcode = 1
        return retcode

def resolve(args, img_dir):
        """Take a list of manifests and resolve any file dependencies, first
        against the other published manifests and then against what is installed
        on the machine."""
        out_dir = None
        echo_manifest = False
        output_to_screen = False
        suffix = None
        verbose = False
Example #44
0
def resolve(args, img_dir):
    """Take a list of manifests and resolve any file dependencies, first
        against the other published manifests and then against what is installed
        on the machine."""
    out_dir = None
    echo_manifest = False
    output_to_screen = False
    suffix = None
    verbose = False
    use_system_to_resolve = True
    constraint_files = []
    extra_external_info = False
    try:
        opts, pargs = getopt.getopt(args, "d:e:Emos:Sv")
    except getopt.GetoptError as e:
        usage(_("illegal global option -- {0}").format(e.opt))
    for opt, arg in opts:
        if opt == "-d":
            out_dir = arg
        elif opt == "-e":
            constraint_files.append(arg)
        elif opt == "-E":
            extra_external_info = True
        elif opt == "-m":
            echo_manifest = True
        elif opt == "-o":
            output_to_screen = True
        elif opt == "-s":
            suffix = arg
        elif opt == "-S":
            use_system_to_resolve = False
        elif opt == "-v":
            verbose = True

    if (out_dir or suffix) and output_to_screen:
        usage(_("-o cannot be used with -d or -s"))

    manifest_paths = [os.path.abspath(fp) for fp in pargs]

    for manifest in manifest_paths:
        if not os.path.isfile(manifest):
            usage(_("The manifest file {0} could not be found.").format(
                manifest),
                  retcode=2)

    if out_dir:
        out_dir = os.path.abspath(out_dir)
        if not os.path.isdir(out_dir):
            usage(_("The output directory {0} is not a directory.").format(
                out_dir),
                  retcode=2)

    provided_image_dir = True
    pkg_image_used = False
    if img_dir == None:
        orig_cwd = None
        try:
            orig_cwd = os.getcwd()
        except OSError:
            # May be unreadable by user or have other problem.
            pass

        img_dir, provided_image_dir = api.get_default_image_root(
            orig_cwd=orig_cwd)
        if os.environ.get("PKG_IMAGE"):
            # It's assumed that this has been checked by the above
            # function call and hasn't been removed from the
            # environment.
            pkg_image_used = True

    if not img_dir:
        error(
            _("Could not find image.  Use the -R option or set "
              "$PKG_IMAGE to the\nlocation of an image."))
        return 1

    system_patterns = misc.EmptyI
    if constraint_files:
        system_patterns = []
        for f in constraint_files:
            try:
                with open(f, "rb") as fh:
                    for l in fh:
                        l = l.strip()
                        if l and not l.startswith("#"):
                            system_patterns.append(l)
            except EnvironmentError as e:
                if e.errno == errno.ENOENT:
                    error("{0}: '{1}'".format(e.args[1], e.filename),
                          cmd="resolve")
                    return 1
                raise api_errors._convert_error(e)
        if not system_patterns:
            error(
                _("External package list files were provided but "
                  "did not contain any fmri patterns."))
            return 1
    elif use_system_to_resolve:
        system_patterns = ["*"]

    # Becuase building an ImageInterface permanently changes the cwd for
    # python, it's necessary to do this step after resolving the paths to
    # the manifests.
    try:
        api_inst = api.ImageInterface(img_dir,
                                      CLIENT_API_VERSION,
                                      progress.QuietProgressTracker(),
                                      None,
                                      PKG_CLIENT_NAME,
                                      exact_match=provided_image_dir)
    except api_errors.ImageNotFoundException as e:
        if e.user_specified:
            if pkg_image_used:
                error(
                    _("No image rooted at '{0}' "
                      "(set by $PKG_IMAGE)").format(e.user_dir))
            else:
                error(_("No image rooted at '{0}'").format(e.user_dir))
        else:
            error(_("No image found."))
        return 1
    except api_errors.PermissionsException as e:
        error(e)
        return 1
    except api_errors.ImageFormatUpdateNeeded as e:
        # This should be a very rare error case.
        format_update_error(e)
        return 1

    try:
        pkg_deps, errs, unused_fmris, external_deps = \
            dependencies.resolve_deps(manifest_paths, api_inst,
                system_patterns, prune_attrs=not verbose)
    except (actions.MalformedActionError, actions.UnknownActionError) as e:
        error(
            _("Could not parse one or more manifests because of "
              "the following line:\n{0}").format(e.actionstr))
        return 1
    except dependencies.DependencyError as e:
        error(e)
        return 1
    except api_errors.ApiException as e:
        error(e)
        return 1
    ret_code = 0

    if output_to_screen:
        ret_code = pkgdeps_to_screen(pkg_deps, manifest_paths, echo_manifest)
    elif out_dir:
        ret_code = pkgdeps_to_dir(pkg_deps, manifest_paths, out_dir, suffix,
                                  echo_manifest)
    else:
        ret_code = pkgdeps_in_place(pkg_deps, manifest_paths, suffix,
                                    echo_manifest)

    if extra_external_info:
        if constraint_files and unused_fmris:
            msg(
                _("\nThe following fmris matched a pattern in a "
                  "constraint file but were not used in\ndependency "
                  "resolution:"))
            for pfmri in sorted(unused_fmris):
                msg("\t{0}".format(pfmri))
        if not constraint_files and external_deps:
            msg(_("\nThe following fmris had dependencies resolve "
                  "to them:"))
            for pfmri in sorted(external_deps):
                msg("\t{0}".format(pfmri))

    for e in errs:
        if ret_code == 0:
            ret_code = 1
        emsg(e)
    return ret_code
Example #45
0
        proxy_conf = {
            "tools.proxy.on": True,
            "tools.proxy.local": "",
            "tools.proxy.base": proxy_base
        }

        # Now merge or add our proxy configuration information into the
        # existing configuration.
        for entry in proxy_conf:
            conf["/"][entry] = proxy_conf[entry]

    scfg.acquire_in_flight()
    try:
        scfg.acquire_catalog(rebuild=rebuild, verbose=True)
    except (catalog.CatalogPermissionsException, errors.SvrConfigError), _e:
        emsg("pkg.depotd: %s" % _e)
        sys.exit(1)

    try:
        if nasty:
            root = cherrypy.Application(
                depot.NastyDepotHTTP(scfg, repo_config_file))
        else:
            root = cherrypy.Application(depot.DepotHTTP(
                scfg, repo_config_file))
    except rc.InvalidAttributeValueError, _e:
        emsg("pkg.depotd: repository.conf error: %s" % _e)
        sys.exit(1)

    try:
        cherrypy.quickstart(root, config=conf)