def error(text, exitcode=1): """Emit an error message prefixed by the command name """ emsg("pkgmerge: %s" % text) if exitcode != None: sys.exit(exitcode)
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)
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))
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
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."))
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
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))
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)
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))
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) })
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)
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)
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)
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)
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)
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)
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)
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)
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
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."))
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)
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
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
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
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
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
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))
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
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))
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)
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)
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):
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)
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)
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):
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"
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:
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()
__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)
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
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
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)