api_errors.py revision 2400
1516N/A#!/usr/bin/python
565N/A#
565N/A# CDDL HEADER START
565N/A#
565N/A# The contents of this file are subject to the terms of the
565N/A# Common Development and Distribution License (the "License").
565N/A# You may not use this file except in compliance with the License.
565N/A#
565N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
565N/A# or http://www.opensolaris.org/os/licensing.
565N/A# See the License for the specific language governing permissions
565N/A# and limitations under the License.
565N/A#
565N/A# When distributing Covered Code, include this CDDL HEADER in each
565N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
565N/A# If applicable, add the following below this CDDL HEADER, with the
565N/A# fields enclosed by brackets "[]" replaced with your own identifying
565N/A# information: Portions Copyright [yyyy] [name of copyright owner]
565N/A#
565N/A# CDDL HEADER END
565N/A#
926N/A
926N/A#
1895N/A# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
926N/A#
565N/A
2026N/Aimport errno
1050N/Aimport os
926N/Aimport urlparse
926N/A
926N/A# pkg classes
926N/Aimport pkg.client.pkgdefs as pkgdefs
926N/A
838N/A# EmptyI for argument defaults; can't import from misc due to circular
565N/A# dependency.
2034N/AEmptyI = tuple()
2034N/A
2034N/Aclass ApiException(Exception):
1540N/A def __init__(self, *args):
1540N/A Exception.__init__(self)
1540N/A self.__verbose_info = []
1540N/A
1540N/A def __unicode__(self):
1968N/A # To workaround python issues 6108 and 2517, this provides a
1540N/A # a standard wrapper for this class' exceptions so that they
2034N/A # have a chance of being stringified correctly.
2034N/A return unicode(str(self))
2034N/A
2034N/A def add_verbose_info(self, info):
2034N/A self.__verbose_info.extend(info)
2034N/A
565N/A @property
1710N/A def verbose_info(self):
1710N/A return self.__verbose_info
1710N/A
1710N/Aclass SuidUnsupportedError(ApiException):
1710N/A def __str__(self):
1710N/A return _("""
1710N/AThe pkg client api module can not be invoked from an setuid executable.""")
1710N/A
1710N/Aclass SubprocessError(ApiException):
1710N/A
1710N/A def __init__(self, rv, cmd):
1710N/A if type(cmd) == list:
1710N/A cmd = " ".join(cmd)
1710N/A assert type(cmd) == str
1710N/A self.err = _("The following subprocess returned an "
1710N/A "unexpected exit code of %(rv)d:\n%(cmd)s") % \
1710N/A {"rv": rv, "cmd": cmd}
1710N/A
1710N/A def __str__(self):
1710N/A return self.err
1710N/A
1710N/Aclass ImageLockedError(ApiException):
1710N/A """Used to indicate that the image is currently locked by another thread
1710N/A or process and cannot be modified."""
1710N/A
1710N/A def __init__(self, hostname=None, pid=None, pid_name=None):
1710N/A ApiException.__init__(self)
1710N/A self.hostname = hostname
1710N/A self.pid = pid
1710N/A self.pid_name = pid_name
1710N/A
565N/A def __str__(self):
565N/A if self.pid is not None and self.pid_name is not None and \
565N/A self.hostname is not None:
565N/A return _("The image cannot be modified as it is "
565N/A "currently in use by another package client: "
565N/A "%(pid_name)s on %(host)s, pid %(pid)s.") % {
565N/A "pid_name": self.pid_name, "pid": self.pid,
565N/A "host": self.hostname }
2144N/A if self.pid is not None and self.pid_name is not None:
2158N/A return _("The image cannot be modified as it is "
2158N/A "currently in use by another package client: "
2158N/A "%(pid_name)s on an unknown host, pid %(pid)s.") % {
2158N/A "pid_name": self.pid_name, "pid": self.pid }
2158N/A elif self.pid is not None:
2158N/A return _("The image cannot be modified as it is "
2158N/A "currently in use by another package client: "
2158N/A "pid %(pid)s on %(host)s.") % {
2158N/A "pid": self.pid, "host": self.hostname }
2158N/A return _("The image cannot be modified as it is currently "
2158N/A "in use by another package client.")
2158N/A
2158N/Aclass ImageNotFoundException(ApiException):
2158N/A """Used when an image was not found"""
2158N/A def __init__(self, user_specified, user_dir, root_dir):
2158N/A ApiException.__init__(self)
2158N/A self.user_specified = user_specified
2158N/A self.user_dir = user_dir
2144N/A self.root_dir = root_dir
2144N/A
2144N/A
2144N/Aclass ImageLocationAmbiguous(ApiException):
2144N/A """Used to indicate that an image was found at a location other than
2144N/A '/' on the Solaris platform when requesting automatic image location
2144N/A discovery. Clients should trap this exception and add their own
2144N/A messaging telling the user how to specify an image root explicitly
2144N/A for the location."""
2144N/A
2144N/A def __init__(self, root, live_root="/"):
2144N/A ApiException.__init__(self)
2144N/A self.root = root
2144N/A self.live_root = live_root
565N/A
565N/A def __str__(self):
565N/A return _("pkg(5) image found at '%(found)s' instead of "
565N/A "'%(expected)s'.") % { "found": self.root,
565N/A "expected": self.live_root }
565N/A
2144N/A
565N/Aclass ImageFormatUpdateNeeded(ApiException):
565N/A """Used to indicate that an image cannot be used until its format is
565N/A updated."""
565N/A
565N/A def __init__(self, path):
1618N/A ApiException.__init__(self)
1618N/A self.path = path
1618N/A
1618N/A def __str__(self):
1618N/A return _("The image rooted at %s is written in an older format "
1618N/A "and must be updated before the requested operation can be "
1755N/A "performed.") % self.path
1755N/A
1755N/A
1755N/Aclass VersionException(ApiException):
1755N/A def __init__(self, expected_version, received_version):
1755N/A ApiException.__init__(self)
1755N/A self.expected_version = expected_version
1755N/A self.received_version = received_version
1755N/A
1755N/A
1755N/Aclass PlanExistsException(ApiException):
1755N/A def __init__(self, plan_type):
1755N/A ApiException.__init__(self)
1755N/A self.plan_type = plan_type
1755N/A
1755N/A
1755N/Aclass PlanPrepareException(ApiException):
1618N/A """Base exception class for plan preparation errors."""
1618N/A pass
1618N/A
1618N/A
1618N/Aclass InvalidPackageErrors(ApiException):
1618N/A """Used to indicate that the requested operation could not be completed
1618N/A as one or more packages contained invalid metadata."""
1618N/A
1618N/A def __init__(self, errors):
1618N/A """'errors' should be a list of exceptions or strings
1618N/A indicating what packages had errors and why."""
1618N/A
1618N/A ApiException.__init__(self)
1618N/A self.errors = errors
1618N/A
1618N/A def __str__(self):
1618N/A return _("The requested operation cannot be completed due "
1618N/A "to invalid package metadata. Details follow:\n\n"
1618N/A "%s") % "\n".join(str(e) for e in self.errors)
1618N/A
1618N/A
1618N/Aclass LicenseAcceptanceError(ApiException):
1618N/A """Used to indicate that license-related errors occurred during
1618N/A plan evaluation or execution."""
1618N/A
1618N/A def __init__(self, pfmri, src=None, dest=None, accepted=None,
1618N/A displayed=None):
1618N/A ApiException.__init__(self)
1618N/A self.fmri = pfmri
1618N/A self.src = src
1618N/A self.dest = dest
1618N/A self.accepted = accepted
1618N/A self.displayed = displayed
1618N/A
1618N/A
1618N/Aclass PkgLicenseErrors(PlanPrepareException):
1618N/A """Used to indicate that plan evaluation or execution failed due
1618N/A to license-related errors for a package."""
1618N/A
1618N/A def __init__(self, errors):
1618N/A """'errors' should be a list of LicenseAcceptanceError
1618N/A exceptions."""
1618N/A
1618N/A PlanPrepareException.__init__(self)
1618N/A self.__errors = errors
1618N/A
1618N/A @property
1618N/A def errors(self):
1618N/A """A list of LicenseAcceptanceError exceptions."""
1618N/A return self.__errors
1618N/A
1618N/A
1618N/Aclass PlanLicenseErrors(PlanPrepareException):
1618N/A """Used to indicate that image plan evaluation or execution failed due
1618N/A to license-related errors."""
1618N/A
1618N/A def __init__(self, pp_errors):
1618N/A """'errors' should be a list of PkgLicenseErrors exceptions."""
1618N/A
1618N/A PlanPrepareException.__init__(self)
1618N/A self.__errors = pkgs = {}
1618N/A for pp_err in pp_errors:
1618N/A for e in pp_err.errors:
1618N/A pkgs.setdefault(str(e.fmri), []).append(e)
1618N/A
1618N/A @property
1618N/A def errors(self):
1618N/A """Returns a dictionary indexed by package FMRI string of
1618N/A lists of LicenseAcceptanceError exceptions."""
1618N/A
1019N/A return self.__errors
1019N/A
1019N/A def __str__(self):
1019N/A """Returns a string representation of the license errors."""
1019N/A
1019N/A output = ""
1019N/A for sfmri in self.__errors:
1019N/A output += ("-" * 40) + "\n"
1618N/A output += _("Package: %s\n\n") % sfmri
565N/A for e in self.__errors[sfmri]:
565N/A lic_name = e.dest.attrs["license"]
565N/A output += _("License: %s\n") % lic_name
1618N/A if e.dest.must_accept and not e.accepted:
1618N/A output += _(" License requires "
565N/A "acceptance.")
565N/A if e.dest.must_display and not e.displayed:
1618N/A output += _(" License must be viewed.")
565N/A output += "\n"
565N/A return output
565N/A
1618N/A
565N/Aclass ActuatorException(ApiException):
565N/A def __init__(self, e):
565N/A ApiException.__init__(self)
565N/A self.exception = e
565N/A
1369N/A def __str__(self):
1710N/A return str(self.exception)
1710N/A
1710N/A
1710N/Aclass PrematureExecutionException(ApiException):
1710N/A pass
1710N/A
1710N/A
1710N/Aclass AlreadyPreparedException(PlanPrepareException):
1710N/A pass
1710N/A
1372N/A
1369N/Aclass AlreadyExecutedException(ApiException):
1369N/A pass
1369N/A
1369N/A
1369N/Aclass ImageplanStateException(ApiException):
1369N/A def __init__(self, state):
1369N/A ApiException.__init__(self)
1369N/A self.state = state
1372N/A
1372N/A
1369N/Aclass InvalidPlanError(ApiException):
1369N/A """Used to indicate that the image plan is no longer valid, likely as a
565N/A result of an image state change since the plan was created."""
565N/A
565N/A def __str__(self):
565N/A return _("The plan for the current operation is no longer "
565N/A "valid. The image has likely been modified by another "
565N/A "process or client. Please try the operation again.")
1328N/A
1328N/A
1328N/Aclass ImagePkgStateError(ApiException):
565N/A
565N/A def __init__(self, fmri, states):
565N/A ApiException.__init__(self)
565N/A self.fmri = fmri
565N/A self.states = states
565N/A
565N/A def __str__(self):
565N/A return _("Invalid package state change attempted '%(states)s' "
565N/A "for package '%(fmri)s'.") % { "states": self.states,
685N/A "fmri": self.fmri }
685N/A
685N/A
685N/Aclass IpkgOutOfDateException(ApiException):
685N/A pass
685N/A
685N/Aclass ImageUpdateOnLiveImageException(ApiException):
926N/A pass
2126N/A
2126N/Aclass RebootNeededOnLiveImageException(ApiException):
2126N/A pass
685N/A
685N/Aclass CanceledException(ApiException):
2126N/A pass
2126N/A
685N/Aclass PlanMissingException(ApiException):
685N/A pass
879N/A
879N/Aclass NoPackagesInstalledException(ApiException):
879N/A pass
879N/A
879N/Aclass PermissionsException(ApiException):
879N/A def __init__(self, path):
879N/A ApiException.__init__(self)
879N/A self.path = path
879N/A
879N/A def __str__(self):
1335N/A if self.path:
1335N/A return _("Could not operate on %s\nbecause of "
1945N/A "insufficient permissions. Please try the "
1335N/A "command again as a privileged user.") % \
1335N/A self.path
1335N/A else:
1335N/A return _("""
1335N/ACould not complete the operation because of insufficient permissions.
1335N/APlease try the command again as a privileged user.
1335N/A""")
1335N/A
1335N/Aclass FileInUseException(PermissionsException):
1968N/A def __init__(self, path):
1335N/A PermissionsException.__init__(self, path)
1335N/A assert path
1335N/A
1335N/A def __str__(self):
565N/A return _("Could not operate on %s\nbecause the file is "
1141N/A "in use. Please stop using the file and try the\n"
926N/A "operation again.") % self.path
1945N/A
1945N/A
1505N/Aclass ReadOnlyFileSystemException(PermissionsException):
565N/A """Used to indicate that the operation was attempted on a
1505N/A read-only filesystem"""
1505N/A
1505N/A def __init__(self, path):
1505N/A ApiException.__init__(self)
1505N/A self.path = path
1505N/A
1505N/A def __str__(self):
1461N/A if self.path:
1505N/A return _("Could not complete the operation on %s: "
1505N/A "read-only filesystem.") % self.path
1505N/A return _("Could not complete the operation: read-only "
1505N/A "filesystem.")
838N/A
565N/A
616N/Aclass PackageMatchErrors(ApiException):
1141N/A def __init__(self, unmatched_fmris=EmptyI, multiple_matches=EmptyI,
616N/A illegal=EmptyI, multispec=EmptyI):
988N/A ApiException.__init__(self)
988N/A self.unmatched_fmris = unmatched_fmris
926N/A self.multiple_matches = multiple_matches
1141N/A self.illegal = illegal
565N/A self.multispec = multispec
1505N/A
1505N/A def __str__(self):
1505N/A res = []
1505N/A if self.unmatched_fmris:
1505N/A s = _("The following pattern(s) did not match any "
1505N/A "packages:")
1505N/A
565N/A res += [s]
988N/A res += ["\t%s" % p for p in self.unmatched_fmris]
565N/A
922N/A if self.multiple_matches:
922N/A s = _("'%s' matches multiple packages")
633N/A for p, lst in self.multiple_matches:
616N/A res.append(s % p)
1505N/A for pfmri in lst:
1505N/A res.append("\t%s" % pfmri)
1505N/A
616N/A if self.illegal:
1505N/A s = _("'%s' is an illegal FMRI")
1505N/A res += [ s % p for p in self.illegal ]
1505N/A
655N/A if self.multispec:
838N/A s = _("The following different patterns specify the "
838N/A "same package(s):")
838N/A res += [s]
1027N/A for t in self.multispec:
838N/A res += [
838N/A ", ".join([t[i] for i in range(1, len(t))])
838N/A + ": %s" % t[0]
1461N/A ]
1461N/A
1461N/A return "\n".join(res)
1352N/A
1352N/A
1352N/Aclass PlanCreationException(ApiException):
1352N/A def __init__(self,
1352N/A already_installed=EmptyI,
1352N/A badarch=EmptyI,
1352N/A illegal=EmptyI,
1505N/A installed=EmptyI,
1505N/A linked_pub_error=EmptyI,
1505N/A missing_dependency=EmptyI,
1505N/A missing_matches=EmptyI,
1505N/A multiple_matches=EmptyI,
1505N/A multispec=EmptyI,
1505N/A no_solution=False,
1505N/A no_tmp_origins=False,
1505N/A no_version=EmptyI,
1945N/A nofiles=EmptyI,
1505N/A obsolete=EmptyI,
1505N/A pkg_updates_required=EmptyI,
1505N/A solver_errors=EmptyI,
1505N/A unmatched_fmris=EmptyI,
1505N/A would_install=EmptyI,
1505N/A wrong_publishers=EmptyI,
1505N/A wrong_variants=EmptyI):
1945N/A
1945N/A ApiException.__init__(self)
1945N/A self.already_installed = already_installed
1945N/A self.badarch = badarch
1945N/A self.illegal = illegal
1352N/A self.installed = installed
565N/A self.linked_pub_error = linked_pub_error
1068N/A self.missing_dependency = missing_dependency
1050N/A self.missing_matches = missing_matches
1859N/A self.multiple_matches = multiple_matches
1859N/A self.multispec = multispec
1050N/A self.no_solution = no_solution
1050N/A self.no_tmp_origins = no_tmp_origins
1859N/A self.no_version = no_version
1859N/A self.nofiles = nofiles
1859N/A self.obsolete = obsolete
1859N/A self.pkg_updates_required = pkg_updates_required
1859N/A self.solver_errors = solver_errors
1859N/A self.unmatched_fmris = unmatched_fmris
1859N/A self.would_install = would_install
1859N/A self.wrong_publishers = wrong_publishers
1859N/A self.wrong_variants = wrong_variants
1859N/A
1859N/A def __str__(self):
1859N/A res = []
1859N/A if self.unmatched_fmris:
1859N/A s = _("""\
1859N/AThe following pattern(s) did not match any allowable packages. Try
1050N/Ausing a different matching pattern, or refreshing the image:
1859N/A""")
1859N/A res += [s]
1859N/A res += ["\t%s" % p for p in self.unmatched_fmris]
1859N/A
1859N/A if self.wrong_variants:
1859N/A s = _("""\
1859N/AThe following pattern(s) only matched packages that are not available
1050N/Afor the current image's architecture, zone type, and/or other variant:""")
1859N/A res += [s]
1050N/A res += ["\t%s" % p for p in self.wrong_variants]
1859N/A
1859N/A if self.wrong_publishers:
1859N/A s = _("The following patterns only matched packages "
1859N/A "that are from publishers other than that which "
1859N/A "supplied the already installed version of this package")
1859N/A res += [s]
1859N/A res += ["\t%s: %s" % (p[0], ", ".join(p[1])) for p in self.wrong_publishers]
1859N/A
1050N/A if self.multiple_matches:
1050N/A s = _("'%s' matches multiple packages")
1050N/A for p, lst in self.multiple_matches:
1859N/A res.append(s % p)
1859N/A for pfmri in lst:
1859N/A res.append("\t%s" % pfmri)
1859N/A
1050N/A if self.missing_matches:
1859N/A s = _("'%s' matches no installed packages")
1050N/A res += [ s % p for p in self.missing_matches ]
1050N/A
1050N/A if self.illegal:
1859N/A s = _("'%s' is an illegal fmri")
1859N/A res += [ s % p for p in self.illegal ]
1859N/A
1859N/A if self.badarch:
1859N/A s = _("'%s' supports the following architectures: %s")
1050N/A a = _("Image architecture is defined as: %s")
1859N/A res += [ s % (self.badarch[0],
1859N/A ", ".join(self.badarch[1]))]
1859N/A res += [ a % (self.badarch[2])]
1859N/A
2073N/A s = _("'%(p)s' depends on obsolete package '%(op)s'")
1859N/A res += [ s % {"p": p, "op": op} for p, op in self.obsolete ]
1859N/A
1859N/A if self.installed:
1859N/A s = _("The proposed operation can not be performed for "
1050N/A "the following package(s) as they are already "
1050N/A "installed: ")
1859N/A res += [s]
1050N/A res += ["\t%s" % p for p in self.installed]
1068N/A
565N/A if self.multispec:
1603N/A s = _("The following different patterns specify the "
565N/A "same package(s):")
565N/A res += [s]
565N/A for t in self.multispec:
565N/A res += [
1603N/A ", ".join(
565N/A [t[i] for i in range(1, len(t))])
1068N/A + ": %s" % t[0]
1352N/A ]
1352N/A if self.no_solution:
1352N/A res += [_("No solution was found to satisfy constraints")]
1352N/A if isinstance(self.no_solution, list):
565N/A res.extend(self.no_solution)
1352N/A
1352N/A if self.pkg_updates_required:
1352N/A s = _("""\
1352N/ASyncing this linked image would require the following package updates:
1516N/A""")
1352N/A res += [s]
1352N/A for (oldfmri, newfmri) in self.pkg_updates_required:
1352N/A res += ["%(oldfmri)s -> %(newfmri)s\n" % \
1352N/A {"oldfmri": oldfmri, "newfmri": newfmri}]
1352N/A
1352N/A if self.no_version:
1352N/A res += self.no_version
1352N/A
1352N/A if self.no_tmp_origins:
1352N/A s = _("""
1352N/AThe proposed operation on this parent image can not be performed because
1352N/Atemporary origins were specified and this image has children. Please either
1352N/Aretry the operation again without specifying any temporary origins, or if
1352N/Apackages from additional origins are required, please configure those origins
1352N/Apersistently.""")
1352N/A res = [s]
1352N/A
1352N/A if self.missing_dependency:
1352N/A res += [_("Package %(pkg)s is missing a dependency: "
1352N/A "%(dep)s") %
1352N/A {"pkg": self.missing_dependency[0],
1516N/A "dep": self.missing_dependency[1]}]
1352N/A if self.nofiles:
1352N/A res += [_("The following files are not packaged in this image:")]
1352N/A res += ["\t%s" % f for f in self.nofiles]
1352N/A
1352N/A if self.solver_errors:
1352N/A res += ["\n"]
1352N/A res += [_("Solver dependency errors:")]
1352N/A res.extend(self.solver_errors)
1352N/A
1352N/A if self.already_installed:
1352N/A res += [_("The following packages are already "
1352N/A "installed in this image; use uninstall to "
1352N/A "avoid these:")]
1352N/A res += [ "\t%s" % s for s in self.already_installed]
1352N/A
1352N/A if self.would_install:
1516N/A res += [_("The following packages are a target "
1352N/A "of group dependencies; use install to unavoid "
1352N/A "these:")]
1352N/A res += [ "\t%s" % s for s in self.would_install]
1352N/A
1352N/A def __format_li_pubs(pubs, res):
1352N/A i = 0
1352N/A for pub, sticky in pubs:
1352N/A s = " %s %d: %s" % (_("PUBLISHER"), i, pub)
1352N/A mod = []
1352N/A if not sticky:
1352N/A mod.append(_("non-sticky"))
1352N/A if mod:
1352N/A s += " (%s)" % ",".join(mod)
1352N/A res.append(s)
1352N/A i += 1
1352N/A
1352N/A if self.linked_pub_error:
1352N/A res = []
1352N/A (pubs, parent_pubs) = self.linked_pub_error
1352N/A
1352N/A res.append(_("""
1352N/AInvalid child image publisher configuration. Child image publisher
1352N/Aconfiguration must be a superset of the parent image publisher configuration.
1352N/APlease update the child publisher configuration to match the parent. If the
1352N/Achild image is a zone this can be done automatically by detaching and
1352N/Aattaching the zone.
1352N/A
1352N/AThe parent image has the following enabled publishers:"""))
1352N/A __format_li_pubs(parent_pubs, res)
1352N/A res.append(_("""
1352N/AThe child image has the following enabled publishers:"""))
1352N/A __format_li_pubs(pubs, res)
1352N/A
1516N/A return "\n".join(res)
1516N/A
1352N/A
1352N/Aclass ConflictingActionError(ApiException):
1352N/A """Used to indicate that the imageplan would result in one or more sets
1352N/A of conflicting actions, meaning that more than one action would exist on
1352N/A the system with the same key attribute value in the same namespace.
1352N/A There are three categories, each with its own subclass:
1352N/A
1352N/A - multiple files delivered to the same path or drivers, users, groups,
1352N/A etc, delivered with the same key attribute;
1352N/A
1352N/A - multiple objects delivered to the same path which aren't the same
1352N/A type;
1352N/A
1352N/A - multiple directories, links, or hardlinks delivered to the same path
1352N/A but with conflicting attributes.
1352N/A """
1352N/A
1352N/A def __init__(self, data):
1352N/A self._data = data
2022N/A
2022N/Aclass ConflictingActionErrors(ApiException):
2022N/A """A container for multiple ConflictingActionError exception objects
2022N/A that can be raised as a single exception."""
2022N/A
2022N/A def __init__(self, errors):
2022N/A self.__errors = errors
2022N/A
2022N/A def __str__(self):
2022N/A return "\n\n".join((str(err) for err in self.__errors))
2022N/A
2022N/Aclass DuplicateActionError(ConflictingActionError):
2022N/A """Multiple actions of the same type have been delivered with the same
2022N/A key attribute (when not allowed)."""
1352N/A
1352N/A def __str__(self):
1352N/A pfmris = set((a[1] for a in self._data))
1352N/A kv = self._data[0][0].attrs[self._data[0][0].key_attr]
1352N/A action = self._data[0][0].name
1352N/A if len(pfmris) > 1:
1352N/A s = _("The following packages all deliver %(action)s "
1352N/A "actions to %(kv)s:\n") % locals()
1352N/A for a, p in self._data:
1352N/A s += "\n %s" % p
1352N/A s += _("\n\nThese packages may not be installed together. "
1352N/A "Any non-conflicting set may\nbe, or the packages "
1352N/A "must be corrected before they can be installed.")
1352N/A else:
1352N/A pfmri = pfmris.pop()
1352N/A s = _("The package %(pfmri)s delivers multiple copies "
1352N/A "of %(action)s %(kv)s") % locals()
1352N/A s += _("\nThis package must be corrected before it "
1352N/A "can be installed.")
1352N/A
1352N/A return s
1352N/A
1352N/Aclass InconsistentActionTypeError(ConflictingActionError):
1352N/A """Multiple actions of different types have been delivered with the same
1352N/A 'path' attribute. While this exception could represent other action
1352N/A groups which share a single namespace, none such exist."""
1352N/A
1431N/A def __str__(self):
1431N/A ad = {}
1431N/A pfmris = set()
1431N/A kv = self._data[0][0].attrs[self._data[0][0].key_attr]
1431N/A for a, p in self._data:
1431N/A ad.setdefault(a.name, []).append(p)
1431N/A pfmris.add(p)
1431N/A
1431N/A if len(pfmris) > 1:
1352N/A s = _("The following packages deliver conflicting "
1352N/A "action types to %s:\n") % kv
1970N/A for name, pl in ad.iteritems():
1970N/A s += "\n %s:" % name
1352N/A s += "".join("\n %s" % p for p in pl)
1352N/A s += _("\n\nThese packages may not be installed together. "
1352N/A "Any non-conflicting set may\nbe, or the packages "
1352N/A "must be corrected before they can be installed.")
838N/A else:
1352N/A pfmri = pfmris.pop()
1352N/A types = list_to_lang(ad.keys())
1352N/A s = _("The package %(pfmri)s delivers conflicting "
1352N/A "action types (%(types)s) to %(kv)s") % locals()
1352N/A s += _("\nThis package must be corrected before it "
1352N/A "can be installed.")
1352N/A return s
1352N/A
1352N/Aclass InconsistentActionAttributeError(ConflictingActionError):
1352N/A """Multiple actions of the same type representing the same object have
1945N/A have been delivered, but with conflicting attributes, such as two
565N/A directories at /usr with groups 'root' and 'sys', or two 'root' users
596N/A with uids '0' and '7'."""
596N/A
596N/A def __str__(self):
596N/A actions = self._data
596N/A keyattr = actions[0][0].attrs[actions[0][0].key_attr]
614N/A actname = actions[0][0].name
1352N/A
614N/A # Trim the action's attributes to only those required to be
614N/A # unique.
926N/A def ou(action):
614N/A ua = dict(
1352N/A (k, v)
1352N/A for k, v in action.attrs.iteritems()
1352N/A if k in action.unique_attrs and
1352N/A not (k == "preserve" and "overlay" in action.attrs)
1352N/A )
1352N/A action.attrs = ua
1352N/A return action
596N/A
565N/A d = {}
1027N/A for a in actions:
1191N/A if a[0].attrs.get("implicit", "false") == "false":
1191N/A d.setdefault(str(ou(a[0])), set()).add(a[1])
1027N/A l = sorted([
1027N/A (len(pkglist), action, pkglist)
1027N/A for action, pkglist in d.iteritems()
1027N/A ])
1027N/A
1191N/A s = _("The requested change to the system attempts to install "
1191N/A "multiple actions\nfor %(a)s '%(k)s' with conflicting "
1191N/A "attributes:\n\n") % {"a": actname, "k": keyattr}
1191N/A allpkgs = set()
1191N/A for num, action, pkglist in l:
1191N/A allpkgs.update(pkglist)
1191N/A if num <= 5:
1191N/A if num == 1:
1191N/A t = _(" %(n)d package delivers '%(a)s':\n")
1191N/A else:
1191N/A t = _(" %(n)d packages deliver '%(a)s':\n")
1191N/A s += t % {"n": num, "a": action}
1191N/A for pkg in sorted(pkglist):
1191N/A s += _(" %s\n") % pkg
1191N/A else:
1191N/A t = _(" %d packages deliver '%s', including:\n")
1191N/A s += t % (num, action)
1191N/A for pkg in sorted(pkglist)[:5]:
1191N/A s += _(" %s\n") % pkg
1191N/A
1191N/A if len(allpkgs) == 1:
1191N/A s += _("\nThis package must be corrected before it "
1191N/A "can be installed.")
1191N/A else:
1191N/A s += _("\nThese packages may not be installed together."
1191N/A " Any non-conflicting set may\nbe, or the packages "
1191N/A "must be corrected before they can be installed.")
1191N/A
1191N/A return s
1191N/A
1191N/Adef list_to_lang(l):
1191N/A """Takes a list of items and puts them into a string, with commas in
1191N/A between items, and an "and" between the last two items. Special cases
1191N/A for lists of two or fewer items, and uses the Oxford comma."""
1895N/A
1191N/A if not l:
1191N/A return ""
1191N/A if len(l) == 1:
1191N/A return l[0]
1191N/A if len(l) == 2:
1191N/A # Used for a two-element list
1191N/A return _("%(penultimate)s and %(ultimate)s") % {
1895N/A "penultimate": l[0],
1895N/A "ultimate": l[1]
1191N/A }
1191N/A # In order to properly i18n this construct, we create two templates:
1191N/A # one for each element save the last, and one that tacks on the last
1191N/A # element.
1191N/A # 'elementtemplate' is for each element through the penultimate
1191N/A elementtemplate = _("%s, ")
1191N/A # 'listtemplate' concatenates the concatenation of non-ultimate elements
1191N/A # and the ultimate element.
1191N/A listtemplate = _("%(list)sand %(tail)s")
1191N/A return listtemplate % {
1191N/A "list": "".join(elementtemplate % i for i in l[:-1]),
1191N/A "tail": l[-1]
1191N/A }
1191N/A
1191N/Aclass ActionExecutionError(ApiException):
1191N/A """Used to indicate that action execution (such as install, remove,
1191N/A etc.) failed even though the action is valid.
1191N/A
1191N/A In particular, this exception indicates that something went wrong in the
1191N/A application (or unapplication) of the action to the system, and is most
1191N/A likely not an error in the pkg(5) code."""
1191N/A
1191N/A def __init__(self, action, details=None, error=None, fmri=None,
1191N/A use_errno=None):
1191N/A """'action' is the object for the action that failed during the
1191N/A requested operation.
1895N/A
1895N/A 'details' is an optional message explaining what operation
1191N/A failed, why it failed, and why it cannot continue. It should
1895N/A also include a suggestion as to how to resolve the situation
1191N/A if possible.
1191N/A
1191N/A 'error' is an optional exception object that may have been
1191N/A raised when the operation failed.
1191N/A
1191N/A 'fmri' is an optional package FMRI indicating what package
1945N/A was being operated on at the time the error occurred.
1191N/A
1191N/A 'use_errno' is an optional boolean value indicating whether
1191N/A the strerror() text of the exception should be used. If
1191N/A 'details' is provided, the default value is False, otherwise
1191N/A True."""
1191N/A
1191N/A assert (details or error)
1191N/A self.action = action
1027N/A self.details = details
565N/A self.error = error
1027N/A self.fmri = fmri
565N/A if use_errno == None:
1027N/A # If details were provided, don't use errno unless
565N/A # explicitly requested.
565N/A use_errno = not details
1027N/A self.use_errno = use_errno
565N/A
565N/A def __str__(self):
565N/A errno = ""
565N/A if self.use_errno and self.error and \
1027N/A hasattr(self.error, "errno"):
1191N/A errno = "[errno %d: %s]" % (self.error.errno,
1191N/A os.strerror(self.error.errno))
1191N/A
1191N/A details = self.details or ""
1191N/A
1191N/A # Fall back on the wrapped exception if we don't have anything
1191N/A # useful.
1191N/A if not errno and not details:
1191N/A return str(self.error)
1191N/A
1191N/A if errno and details:
2028N/A details = "%s: %s" % (errno, details)
2028N/A
2028N/A if details and not self.fmri:
2028N/A details = _("Requested operation failed for action "
2028N/A "%(action)s:\n%(details)s") % {
2028N/A "action": self.action,
2028N/A "details": details }
2028N/A elif details:
2028N/A details = _("Requested operation failed for package "
2028N/A "%(fmri)s:\n%(details)s") % { "fmri": self.fmri,
2028N/A "details": details }
2028N/A
565N/A # If we only have one of the two, no need for the colon.
565N/A return "%s%s" % (errno, details)
565N/A
565N/A
565N/Aclass CatalogRefreshException(ApiException):
565N/A def __init__(self, failed, total, succeeded, errmessage=None):
565N/A ApiException.__init__(self)
565N/A self.failed = failed
941N/A self.total = total
1286N/A self.succeeded = succeeded
1286N/A self.errmessage = errmessage
2089N/A
2089N/A
1286N/Aclass CatalogError(ApiException):
1286N/A """Base exception class for all catalog exceptions."""
1286N/A
1286N/A def __init__(self, *args, **kwargs):
1286N/A ApiException.__init__(self)
1286N/A if args:
1286N/A self.data = args[0]
1286N/A else:
1286N/A self.data = None
1286N/A self._args = kwargs
1286N/A
1286N/A def __str__(self):
1286N/A return str(self.data)
1286N/A
1286N/A
2089N/Aclass AnarchicalCatalogFMRI(CatalogError):
2089N/A """Used to indicate that the specified FMRI is not valid for catalog
1286N/A operations because it is missing publisher information."""
1286N/A
1286N/A def __str__(self):
1191N/A return _("The FMRI '%s' does not contain publisher information "
1191N/A "and cannot be used for catalog operations.") % self.data
1191N/A
1191N/A
1191N/Aclass BadCatalogMetaRoot(CatalogError):
941N/A """Used to indicate an operation on the catalog's meta_root failed
941N/A because the meta_root is invalid."""
1191N/A
1191N/A def __str__(self):
1191N/A return _("Catalog meta_root '%(root)s' is invalid; unable "
1191N/A "to complete operation: '%(op)s'.") % { "root": self.data,
1191N/A "op": self._args.get("operation", None) }
1191N/A
1191N/A
1191N/Aclass BadCatalogPermissions(CatalogError):
1191N/A """Used to indicate the server catalog files do not have the expected
1191N/A permissions."""
941N/A
941N/A def __init__(self, files):
941N/A """files should contain a list object with each entry consisting
1027N/A of a tuple of filename, expected_mode, received_mode."""
1027N/A if not files:
565N/A files = []
565N/A CatalogError.__init__(self, files)
565N/A
1027N/A def __str__(self):
565N/A msg = _("The following catalog files have incorrect "
565N/A "permissions:\n")
565N/A for f in self._args:
565N/A fname, emode, fmode = f
565N/A msg += _("\t%(fname)s: expected mode: %(emode)s, found "
565N/A "mode: %(fmode)s\n") % { "fname": fname,
565N/A "emode": emode, "fmode": fmode }
565N/A return msg
565N/A
565N/A
565N/Aclass BadCatalogSignatures(CatalogError):
835N/A """Used to indicate that the Catalog signatures are not valid."""
835N/A
835N/A def __str__(self):
835N/A return _("The signature data for the '%s' catalog file is not "
835N/A "valid.") % self.data
926N/A
835N/A
835N/Aclass BadCatalogUpdateIdentity(CatalogError):
835N/A """Used to indicate that the requested catalog updates could not be
835N/A applied as the new catalog data is significantly different such that
1895N/A the old catalog cannot be updated to match it."""
835N/A
835N/A def __str__(self):
835N/A return _("Unable to determine the updates needed for "
835N/A "the current catalog using the provided catalog "
835N/A "update data in '%s'.") % self.data
835N/A
884N/A
926N/Aclass DuplicateCatalogEntry(CatalogError):
926N/A """Used to indicate that the specified catalog operation could not be
926N/A performed since it would result in a duplicate catalog entry."""
926N/A
926N/A def __str__(self):
926N/A return _("Unable to perform '%(op)s' operation for catalog "
926N/A "%(name)s; completion would result in a duplicate entry "
926N/A "for package '%(fmri)s'.") % { "op": self._args.get(
926N/A "operation", None), "name": self._args.get("catalog_name",
1516N/A None), "fmri": self.data }
926N/A
926N/A
926N/Aclass CatalogUpdateRequirements(CatalogError):
926N/A """Used to indicate that an update request for the catalog could not
926N/A be performed because update requirements were not satisfied."""
926N/A
926N/A def __str__(self):
926N/A return _("Catalog updates can only be applied to an on-disk "
1736N/A "catalog.")
926N/A
926N/A
1736N/Aclass InvalidCatalogFile(CatalogError):
1736N/A """Used to indicate a Catalog file could not be loaded."""
926N/A
926N/A def __str__(self):
926N/A return _("Catalog file '%s' is invalid.") % self.data
926N/A
926N/A
926N/Aclass MismatchedCatalog(CatalogError):
926N/A """Used to indicate that a Catalog's attributes and parts do not
926N/A match. This is likely the result of an attributes file being
926N/A retrieved which doesn't match the parts that were retrieved such
926N/A as in a misconfigured or stale cache case."""
926N/A
926N/A def __str__(self):
1191N/A return _("The content of the catalog for publisher '%s' "
1191N/A "doesn't match the catalog's attributes. This is "
1191N/A "likely the result of a mix of older and newer "
1191N/A "catalog files being provided for the publisher.") % \
1191N/A self.data
926N/A
926N/A
1540N/Aclass ObsoleteCatalogUpdate(CatalogError):
926N/A """Used to indicate that the specified catalog updates are for an older
926N/A version of the catalog and cannot be applied."""
1191N/A
926N/A def __str__(self):
926N/A return _("Unable to determine the updates needed for the "
926N/A "catalog using the provided catalog update data in '%s'. "
1191N/A "The specified catalog updates are for an older version "
1191N/A "of the catalog and cannot be used.") % self.data
1191N/A
1191N/A
1191N/Aclass UnknownCatalogEntry(CatalogError):
926N/A """Used to indicate that an entry for the specified package FMRI or
1191N/A pattern could not be found in the catalog."""
926N/A
1191N/A def __str__(self):
926N/A return _("'%s' could not be found in the catalog.") % self.data
926N/A
926N/A
926N/Aclass UnknownUpdateType(CatalogError):
1191N/A """Used to indicate that the specified CatalogUpdate operation is
926N/A unknown."""
926N/A
1191N/A def __str__(self):
1191N/A return _("Unknown catalog update type '%s'") % self.data
1191N/A
1191N/A
926N/Aclass UnrecognizedCatalogPart(CatalogError):
926N/A """Raised when the catalog finds a CatalogPart that is unrecognized
926N/A or invalid."""
941N/A
941N/A def __str__(self):
941N/A return _("Unrecognized, unknown, or invalid CatalogPart '%s'") \
926N/A % self.data
884N/A
884N/A
884N/Aclass InventoryException(ApiException):
884N/A """Used to indicate that some of the specified patterns to a catalog
884N/A matching function did not match any catalog entries, or were invalid
884N/A patterns."""
1076N/A
1076N/A def __init__(self, illegal=EmptyI, matcher=EmptyI, notfound=EmptyI,
1076N/A publisher=EmptyI, version=EmptyI):
1076N/A ApiException.__init__(self)
1945N/A self.illegal = illegal
1076N/A self.matcher = matcher
1076N/A self.notfound = set(notfound)
1076N/A self.publisher = publisher
1076N/A self.version = version
1076N/A
1076N/A self.notfound.update(matcher)
1076N/A self.notfound.update(publisher)
1076N/A self.notfound.update(version)
1076N/A self.notfound = list(self.notfound)
884N/A
884N/A assert self.illegal or self.notfound
884N/A
884N/A def __str__(self):
884N/A outstr = ""
884N/A for x in self.illegal:
884N/A # Illegal FMRIs have their own __str__ method
884N/A outstr += "%s\n" % x
884N/A
2089N/A if self.matcher or self.publisher or self.version:
884N/A outstr += _("No matching package could be found for "
884N/A "the following FMRIs in any of the catalogs for "
884N/A "the current publishers:\n")
884N/A
884N/A for x in self.matcher:
884N/A outstr += _("%s (pattern did not match)\n") % x
884N/A for x in self.publisher:
884N/A outstr += _("%s (publisher did not "
884N/A "match)\n") % x
884N/A for x in self.version:
884N/A outstr += _("%s (version did not match)\n") % x
884N/A return outstr
884N/A
884N/A
884N/A# SearchExceptions
884N/A
884N/Aclass SearchException(ApiException):
884N/A """Based class used for all search-related api exceptions."""
884N/A pass
884N/A
884N/A
884N/Aclass MalformedSearchRequest(SearchException):
884N/A """Raised when the server cannot understand the format of the
884N/A search request."""
884N/A
884N/A def __init__(self, url):
884N/A SearchException.__init__(self)
884N/A self.url = url
884N/A
884N/A def __str__(self):
884N/A return str(self.url)
884N/A
884N/A
884N/Aclass NegativeSearchResult(SearchException):
884N/A """Returned when the search cannot find any matches."""
884N/A
884N/A def __init__(self, url):
884N/A SearchException.__init__(self)
884N/A self.url = url
926N/A
926N/A def __str__(self):
917N/A return _("The search at url %s returned no results.") % self.url
917N/A
917N/A
917N/Aclass ProblematicSearchServers(SearchException):
917N/A """This class wraps exceptions which could appear while trying to
917N/A do a search request."""
917N/A
917N/A def __init__(self, failed=EmptyI, invalid=EmptyI, unsupported=EmptyI):
917N/A SearchException.__init__(self)
917N/A self.failed_servers = failed
926N/A self.invalid_servers = invalid
941N/A self.unsupported_servers = unsupported
941N/A
941N/A def __str__(self):
941N/A s = _("Some repositories failed to respond appropriately:\n")
941N/A for pub, err in self.failed_servers:
941N/A s += _("%(o)s:\n%(msg)s\n") % \
926N/A { "o": pub, "msg": err}
926N/A for pub in self.invalid_servers:
926N/A s += _("%s did not return a valid response.\n" \
926N/A % pub)
926N/A if len(self.unsupported_servers) > 0:
926N/A s += _("Some repositories don't support requested "
926N/A "search operation:\n")
926N/A for pub, err in self.unsupported_servers:
926N/A s += _("%(o)s:\n%(msg)s\n") % \
1516N/A { "o": pub, "msg": err}
926N/A
926N/A return s
926N/A
926N/A
926N/Aclass SlowSearchUsed(SearchException):
1087N/A """This exception is thrown when a local search is performed without
1087N/A an index. It's raised after all results have been yielded."""
1087N/A
1087N/A def __str__(self):
1087N/A return _("Search performance is degraded.\n"
1087N/A "Run 'pkg rebuild-index' to improve search speed.")
1087N/A
1516N/A
1087N/Aclass UnsupportedSearchError(SearchException):
1087N/A """Returned when a search protocol is not supported by the
2028N/A remote server."""
2028N/A
2028N/A def __init__(self, url=None, proto=None):
2028N/A SearchException.__init__(self)
2028N/A self.url = url
2028N/A self.proto = proto
2028N/A
926N/A def __str__(self):
926N/A s = _("Search repository does not support the requested "
926N/A "protocol:")
926N/A if self.url:
926N/A s += "\nRepository URL: %s" % self.url
926N/A if self.proto:
926N/A s += "\nRequested operation: %s" % self.proto
926N/A return s
926N/A
926N/A def __cmp__(self, other):
926N/A if not isinstance(other, UnsupportedSearchError):
926N/A return -1
926N/A r = cmp(self.url, other.url)
926N/A if r != 0:
1516N/A return r
926N/A return cmp(self.proto, other.proto)
926N/A
926N/A
926N/A# IndexingExceptions.
926N/A
926N/Aclass IndexingException(SearchException):
926N/A """ The base class for all exceptions that can occur while indexing. """
926N/A
926N/A def __init__(self, private_exception):
926N/A SearchException.__init__(self)
926N/A self.cause = private_exception.cause
926N/A
926N/A
926N/Aclass CorruptedIndexException(IndexingException):
926N/A """This is used when the index is not in a correct state."""
926N/A pass
926N/A
926N/A
926N/Aclass InconsistentIndexException(IndexingException):
926N/A """This is used when the existing index is found to have inconsistent
926N/A versions."""
926N/A def __init__(self, e):
926N/A IndexingException.__init__(self, e)
926N/A self.exception = e
926N/A
926N/A def __str__(self):
926N/A return str(self.exception)
926N/A
926N/A
926N/Aclass IndexLockedException(IndexingException):
926N/A """This is used when an attempt to modify an index locked by another
926N/A process or thread is made."""
926N/A
926N/A def __init__(self, e):
926N/A IndexingException.__init__(self, e)
926N/A self.exception = e
926N/A
926N/A def __str__(self):
926N/A return str(self.exception)
926N/A
926N/A
926N/Aclass ProblematicPermissionsIndexException(IndexingException):
926N/A """ This is used when the indexer is unable to create, move, or remove
926N/A files or directories it should be able to. """
926N/A def __str__(self):
926N/A return "Could not remove or create " \
926N/A "%s because of incorrect " \
926N/A "permissions. Please correct this issue then " \
926N/A "rebuild the index." % self.cause
926N/A
926N/Aclass WrapIndexingException(ApiException):
926N/A """This exception is used to wrap an indexing exception during install,
926N/A uninstall, or update so that a more appropriate error message can be
926N/A displayed to the user."""
926N/A
926N/A def __init__(self, e, tb, stack):
926N/A ApiException.__init__(self)
926N/A self.wrapped = e
926N/A self.tb = tb
926N/A self.stack = stack
926N/A
926N/A def __str__(self):
926N/A tmp = self.tb.split("\n")
926N/A res = tmp[:1] + [s.rstrip("\n") for s in self.stack] + tmp[1:]
926N/A return "\n".join(res)
926N/A
926N/A
926N/Aclass WrapSuccessfulIndexingException(WrapIndexingException):
926N/A """This exception is used to wrap an indexing exception during install,
926N/A uninstall, or update which was recovered from by performing a full
926N/A reindex."""
926N/A pass
926N/A
926N/A
926N/A# Query Parsing Exceptions
1504N/Aclass BooleanQueryException(ApiException):
926N/A """This exception is used when the children of a boolean operation
926N/A have different return types. The command 'pkg search foo AND <bar>'
926N/A is the simplest example of this."""
926N/A
926N/A def __init__(self, e):
926N/A ApiException.__init__(self)
926N/A self.e = e
926N/A
1504N/A def __str__(self):
1504N/A return str(self.e)
1504N/A
1504N/A
1504N/Aclass ParseError(ApiException):
1504N/A def __init__(self, e):
1504N/A ApiException.__init__(self)
1504N/A self.e = e
1504N/A
1504N/A def __str__(self):
1504N/A return str(self.e)
926N/A
926N/A
926N/Aclass NonLeafPackageException(ApiException):
926N/A """Removal of a package which satisfies dependencies has been attempted.
926N/A
926N/A The first argument to the constructor is the FMRI which we tried to
926N/A remove, and is available as the "fmri" member of the exception. The
926N/A second argument is the list of dependent packages that prevent the
926N/A removal of the package, and is available as the "dependents" member.
926N/A """
1505N/A
1505N/A def __init__(self, *args):
1505N/A ApiException.__init__(self, *args)
1505N/A
1505N/A self.fmri = args[0]
1505N/A self.dependents = args[1]
1505N/A
926N/Adef _str_autofix(self):
926N/A
926N/A if getattr(self, "_autofix_pkgs", []):
926N/A s = _("\nThis is happening because the following "
926N/A "packages needed to be repaired as\npart of this "
926N/A "operation:\n\n ")
926N/A s += "\n ".join(str(f) for f in self._autofix_pkgs)
926N/A s += _("\n\nYou will need to reestablish your access to the "
926N/A "repository or remove the\npackages in the list above.")
1256N/A return s
926N/A return ""
926N/A
926N/Aclass InvalidDepotResponseException(ApiException):
926N/A """Raised when the depot doesn't have versions of operations
996N/A that the client needs to operate successfully."""
996N/A def __init__(self, url, data):
926N/A ApiException.__init__(self)
926N/A self.url = url
1256N/A self.data = data
1256N/A
1256N/A def __str__(self):
1256N/A s = _("Unable to contact valid package repository")
1256N/A if self.url:
1256N/A s += _(": %s") % self.url
1256N/A if self.data:
1256N/A s += ("\nEncountered the following error(s):\n%s") % \
1256N/A self.data
1256N/A
926N/A s += _str_autofix(self)
926N/A
926N/A return s
926N/A
926N/Aclass DataError(ApiException):
926N/A """Base exception class used for all data related errors."""
926N/A
926N/A def __init__(self, *args, **kwargs):
926N/A ApiException.__init__(self, *args)
926N/A if args:
926N/A self.data = args[0]
926N/A else:
926N/A self.data = None
926N/A self._args = kwargs
926N/A
926N/A
1736N/Aclass InvalidP5IFile(DataError):
1736N/A """Used to indicate that the specified location does not contain a
1736N/A valid p5i-formatted file."""
1736N/A
1736N/A def __str__(self):
1736N/A if self.data:
1736N/A return _("The provided p5i data is in an unrecognized "
1736N/A "format or does not contain valid publisher "
1736N/A "information: %s") % self.data
1736N/A return _("The provided p5i data is in an unrecognized format "
1736N/A "or does not contain valid publisher information.")
1736N/A
1736N/A
1736N/Aclass InvalidP5SFile(DataError):
1736N/A """Used to indicate that the specified location does not contain a
1736N/A valid p5i-formatted file."""
1736N/A
1736N/A def __str__(self):
1736N/A if self.data:
1736N/A return _("The provided p5s data is in an unrecognized "
1736N/A "format or does not contain valid publisher "
1736N/A "information: %s") % self.data
1736N/A return _("The provided p5s data is in an unrecognized format "
1736N/A "or does not contain valid publisher information.")
1736N/A
1736N/A
1736N/Aclass UnsupportedP5IFile(DataError):
1736N/A """Used to indicate that an attempt to read an unsupported version
1736N/A of pkg(5) info file was attempted."""
1736N/A
1736N/A def __str__(self):
1736N/A return _("Unsupported pkg(5) publisher information data "
1736N/A "format.")
1736N/A
1736N/A
1736N/Aclass UnsupportedP5SFile(DataError):
1736N/A """Used to indicate that an attempt to read an unsupported version
1736N/A of pkg(5) info file was attempted."""
1736N/A
1736N/A def __str__(self):
926N/A return _("Unsupported pkg(5) publisher and image information "
926N/A "data format.")
926N/A
926N/A
926N/Aclass UnsupportedP5SVersion(ApiException):
926N/A """Used to indicate that an attempt to read an unsupported version
926N/A of pkg(5) info file was attempted."""
926N/A
926N/A def __init__(self, v):
926N/A self.version = v
926N/A
926N/A def __str__(self):
926N/A return _("%s is not a supported version for creating a "
926N/A "syspub response.") % self.version
926N/A
926N/A
926N/Aclass TransportError(ApiException):
926N/A """Abstract exception class for all transport exceptions.
926N/A Specific transport exceptions should be implemented in the
926N/A transport code. Callers wishing to catch transport exceptions
926N/A should use this class. Subclasses must implement all methods
926N/A defined here that raise NotImplementedError."""
926N/A
1431N/A def __str__(self):
1431N/A raise NotImplementedError()
1431N/A
1431N/A def _str_autofix(self):
1431N/A return _str_autofix(self)
1431N/A
1431N/A
1431N/Aclass RetrievalError(ApiException):
1431N/A """Used to indicate that a a requested resource could not be
1431N/A retrieved."""
1431N/A
1431N/A def __init__(self, data, location=None):
1431N/A ApiException.__init__(self)
1736N/A self.data = data
1736N/A self.location = location
1736N/A
1736N/A def __str__(self):
1736N/A if self.location:
1736N/A return _("Error encountered while retrieving data from "
1736N/A "'%s':\n%s") % (self.location, self.data)
1736N/A return _("Error encountered while retrieving data from: %s") % \
1736N/A self.data
1736N/A
1736N/A
1736N/Aclass InvalidResourceLocation(ApiException):
1736N/A """Used to indicate that an invalid transport location was provided."""
1736N/A
1736N/A def __init__(self, data):
1736N/A ApiException.__init__(self)
1736N/A self.data = data
1736N/A
1736N/A def __str__(self):
1736N/A return _("'%s' is not a valid location.") % self.data
1736N/A
1736N/Aclass BEException(ApiException):
1736N/A def __init__(self):
1736N/A ApiException.__init__(self)
1736N/A
926N/Aclass InvalidBENameException(BEException):
926N/A def __init__(self, be_name):
926N/A BEException.__init__(self)
926N/A self.be_name = be_name
926N/A
926N/A def __str__(self):
926N/A return _("'%s' is not a valid boot environment name.") % \
926N/A self.be_name
926N/A
926N/Aclass DuplicateBEName(BEException):
926N/A """Used to indicate that there is an existing boot environment
926N/A with this name"""
926N/A
926N/A def __init__(self, be_name):
926N/A BEException.__init__(self)
926N/A self.be_name = be_name
926N/A
2144N/A def __str__(self):
2144N/A return _("The boot environment '%s' already exists.") % \
2144N/A self.be_name
2144N/A
2144N/Aclass BENamingNotSupported(BEException):
2144N/A def __init__(self, be_name):
926N/A BEException.__init__(self)
926N/A self.be_name = be_name
926N/A
926N/A def __str__(self):
926N/A return _("""\
926N/ABoot environment naming during package install is not supported on this
926N/Aversion of OpenSolaris. Please update without the --be-name option.""")
926N/A
1516N/Aclass UnableToCopyBE(BEException):
926N/A def __str__(self):
926N/A return _("Unable to clone the current boot environment.")
2026N/A
2026N/Aclass UnableToRenameBE(BEException):
2026N/A def __init__(self, orig, dest):
2026N/A BEException.__init__(self)
2026N/A self.original_name = orig
2026N/A self.destination_name = dest
2026N/A
2026N/A def __str__(self):
2026N/A d = {
2026N/A "orig": self.original_name,
2026N/A "dest": self.destination_name
2026N/A }
2026N/A return _("""\
2026N/AA problem occurred while attempting to rename the boot environment
2026N/Acurrently named %(orig)s to %(dest)s.""") % d
2026N/A
2026N/Aclass UnableToMountBE(BEException):
2026N/A def __init__(self, be_name, be_dir):
2026N/A BEException.__init__(self)
2026N/A self.name = be_name
2026N/A self.mountpoint = be_dir
2026N/A
2026N/A def __str__(self):
2026N/A return _("Unable to mount %(name)s at %(mt)s") % \
2026N/A {"name": self.name, "mt": self.mountpoint}
2026N/A
2026N/Aclass BENameGivenOnDeadBE(BEException):
2026N/A def __init__(self, be_name):
2026N/A BEException.__init__(self)
2026N/A self.name = be_name
2026N/A
2026N/A def __str__(self):
2026N/A return _("""\
2026N/ANaming a boot environment when operating on a non-live image is
2026N/Anot allowed.""")
2026N/A
2026N/A
2026N/Aclass UnrecognizedOptionsToInfo(ApiException):
2026N/A def __init__(self, opts):
2026N/A ApiException.__init__(self)
2026N/A self._opts = opts
2026N/A
2026N/A def __str__(self):
2026N/A s = _("Info does not recognize the following options:")
2026N/A for o in self._opts:
2026N/A s += _(" '") + str(o) + _("'")
2026N/A return s
2026N/A
2026N/Aclass IncorrectIndexFileHash(ApiException):
2026N/A """This is used when the index hash value doesn't match the hash of the
2026N/A packages installed in the image."""
2026N/A pass
2026N/A
2026N/A
2026N/Aclass PublisherError(ApiException):
2026N/A """Base exception class for all publisher exceptions."""
2026N/A
2026N/A def __init__(self, *args, **kwargs):
2026N/A ApiException.__init__(self, *args)
2026N/A if args:
2026N/A self.data = args[0]
2026N/A else:
2026N/A self.data = None
2026N/A self._args = kwargs
2026N/A
2026N/A def __str__(self):
2026N/A return str(self.data)
2026N/A
2026N/A
2026N/Aclass BadPublisherMetaRoot(PublisherError):
2026N/A """Used to indicate an operation on the publisher's meta_root failed
2026N/A because the meta_root is invalid."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("Publisher meta_root '%(root)s' is invalid; unable "
2026N/A "to complete operation: '%(op)s'.") % { "root": self.data,
2026N/A "op": self._args.get("operation", None) }
2026N/A
2026N/A
2026N/Aclass BadPublisherAlias(PublisherError):
2026N/A """Used to indicate that a publisher alias is not valid."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("'%s' is not a valid publisher alias.") % self.data
2026N/A
2026N/A
2026N/Aclass BadPublisherPrefix(PublisherError):
2026N/A """Used to indicate that a publisher name is not valid."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("'%s' is not a valid publisher name.") % self.data
2026N/A
2026N/A
2026N/Aclass ReservedPublisherPrefix(PublisherError):
2026N/A """Used to indicate that a publisher name is not valid."""
2026N/A
2026N/A def __str__(self):
2026N/A fmri = self._args["fmri"]
2026N/A return _("'%(pkg_pub)s' is a reserved publisher and does not "
2026N/A "contain the requested package: pkg:/%(pkg_name)s") % \
2026N/A {"pkg_pub": fmri.publisher, "pkg_name": fmri.pkg_name}
2026N/A
2026N/A
2026N/Aclass BadRepositoryAttributeValue(PublisherError):
2026N/A """Used to indicate that the specified repository attribute value is
2026N/A invalid."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("'%(value)s' is not a valid value for repository "
2026N/A "attribute '%(attribute)s'.") % {
2026N/A "value": self._args["value"], "attribute": self.data }
2026N/A
2026N/A
2026N/Aclass BadRepositoryCollectionType(PublisherError):
2026N/A """Used to indicate that the specified repository collection type is
2026N/A invalid."""
2026N/A
2026N/A def __init__(self, *args, **kwargs):
2026N/A PublisherError.__init__(self, *args, **kwargs)
2026N/A
2026N/A def __str__(self):
2026N/A return _("'%s' is not a valid repository collection type.") % \
2026N/A self.data
2026N/A
2026N/A
2026N/Aclass BadRepositoryURI(PublisherError):
2026N/A """Used to indicate that a repository URI is not syntactically valid."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("'%s' is not a valid URI.") % self.data
2026N/A
2026N/A
2026N/Aclass BadRepositoryURIPriority(PublisherError):
2026N/A """Used to indicate that the priority specified for a repository URI is
2026N/A not valid."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("'%s' is not a valid URI priority; integer value "
2026N/A "expected.") % self.data
2026N/A
2026N/A
2026N/Aclass BadRepositoryURISortPolicy(PublisherError):
2026N/A """Used to indicate that the specified repository URI sort policy is
2026N/A invalid."""
2026N/A
2026N/A def __init__(self, *args, **kwargs):
2026N/A PublisherError.__init__(self, *args, **kwargs)
2026N/A
2026N/A def __str__(self):
2026N/A return _("'%s' is not a valid repository URI sort policy.") % \
2026N/A self.data
2026N/A
2026N/A
2026N/Aclass DisabledPublisher(PublisherError):
2026N/A """Used to indicate that an attempt to use a disabled publisher occurred
2026N/A during an operation."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("Publisher '%s' is disabled and cannot be used for "
2026N/A "packaging operations.") % self.data
2026N/A
2026N/A
2026N/Aclass DuplicatePublisher(PublisherError):
2026N/A """Used to indicate that a publisher with the same name or alias already
2026N/A exists for an image."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("A publisher with the same name or alias as '%s' "
2026N/A "already exists.") % self.data
2026N/A
2026N/A
2026N/Aclass DuplicateRepository(PublisherError):
2026N/A """Used to indicate that a repository with the same origin uris
2026N/A already exists for a publisher."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("A repository with the same name or origin URIs "
2026N/A "already exists for publisher '%s'.") % self.data
2026N/A
2026N/A
2026N/Aclass DuplicateRepositoryMirror(PublisherError):
2026N/A """Used to indicate that a repository URI is already in use by another
2026N/A repository mirror."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("Mirror '%s' already exists for the specified "
2026N/A "publisher.") % self.data
2026N/A
2026N/A
2026N/Aclass DuplicateRepositoryOrigin(PublisherError):
2026N/A """Used to indicate that a repository URI is already in use by another
2026N/A repository origin."""
2026N/A
2026N/A def __str__(self):
2026N/A return _("Origin '%s' already exists for the specified "
2026N/A "publisher.") % self.data
2026N/A
2026N/A
2026N/Aclass NoPublisherRepositories(TransportError):
2026N/A """Used to indicate that a Publisher has no repository information
2026N/A configured and so transport operations cannot be performed."""
2026N/A
2026N/A def __init__(self, prefix):
2026N/A TransportError.__init__(self)
2026N/A self.publisher = prefix
2026N/A
2026N/A def __str__(self):
926N/A return _("Unable to retrieve requested package data for "
926N/A "publisher %s; no repositories are currently configured "
926N/A "for use with this publisher.") % self.publisher
926N/A
926N/A
926N/Aclass MoveRelativeToSelf(PublisherError):
926N/A """Used to indicate an attempt to search a repo before or after itself"""
926N/A
926N/A def __str__(self):
1516N/A return _("Cannot search a repository before or after itself")
926N/A
926N/A
926N/Aclass SelectedRepositoryRemoval(PublisherError):
926N/A """Used to indicate that an attempt to remove the selected repository
926N/A for a publisher was made."""
926N/A
926N/A def __str__(self):
926N/A return _("Cannot remove the selected repository for a "
926N/A "publisher.")
1516N/A
1516N/A
926N/Aclass UnknownLegalURI(PublisherError):
926N/A """Used to indicate that no matching legal URI could be found using the
926N/A provided criteria."""
926N/A
926N/A def __str__(self):
926N/A return _("Unknown legal URI '%s'.") % self.data
1130N/A
926N/A
926N/Aclass UnknownPublisher(PublisherError):
926N/A """Used to indicate that no matching publisher could be found using the
926N/A provided criteria."""
926N/A
926N/A def __str__(self):
926N/A return _("Unknown publisher '%s'.") % self.data
926N/A
926N/A
926N/Aclass UnknownRepositoryPublishers(PublisherError):
926N/A """Used to indicate that one or more publisher prefixes are unknown by
926N/A the specified repository."""
926N/A
926N/A def __init__(self, known=EmptyI, unknown=EmptyI, location=None,
926N/A origins=EmptyI):
926N/A ApiException.__init__(self)
1516N/A self.known = known
1516N/A self.location = location
1516N/A self.origins = origins
926N/A self.unknown = unknown
926N/A
926N/A def __str__(self):
926N/A if self.location:
926N/A return _("The repository at %(location)s does not "
926N/A "contain package data for %(unknown)s; only "
926N/A "%(known)s.\n\nThis is either because the "
926N/A "repository location is not valid, or because the "
926N/A "provided publisher does not match those known by "
926N/A "the repository.") % {
926N/A "unknown": ", ".join(self.unknown),
926N/A "location": self.location,
926N/A "known": ", ".join(self.known) }
926N/A if self.origins:
926N/A return _("One or more of the repository origin(s) "
926N/A "listed below contains package data for "
926N/A "%(known)s; not %(unknown)s:\n\n%(origins)s\n\n"
926N/A "This is either because one of the repository "
926N/A "origins is not valid for this publisher, or "
926N/A "because the list of known publishers retrieved "
926N/A "from the repository origin does not match the "
926N/A "client.") % { "unknown": ", ".join(self.unknown),
1516N/A "known": ", ".join(self.known),
1516N/A "origins": "\n".join(str(o) for o in self.origins) }
926N/A return _("The specified publisher repository does not "
926N/A "contain any package data for %(unknown)s; only "
926N/A "%(known)s.") % { "unknown": ", ".join(self.unknown),
926N/A "known": ", ".join(self.known) }
926N/A
926N/A
926N/Aclass UnknownRelatedURI(PublisherError):
926N/A """Used to indicate that no matching related URI could be found using
926N/A the provided criteria."""
926N/A
926N/A def __str__(self):
926N/A return _("Unknown related URI '%s'.") % self.data
926N/A
926N/A
926N/Aclass UnknownRepository(PublisherError):
926N/A """Used to indicate that no matching repository could be found using the
1254N/A provided criteria."""
1254N/A
1254N/A def __str__(self):
1254N/A return _("Unknown repository '%s'.") % self.data
1516N/A
1516N/A
1254N/Aclass UnknownRepositoryMirror(PublisherError):
1254N/A """Used to indicate that a repository URI could not be found in the
1254N/A list of repository mirrors."""
1254N/A
1254N/A def __str__(self):
1254N/A return _("Unknown repository mirror '%s'.") % self.data
1254N/A
1254N/Aclass UnsupportedRepositoryOperation(TransportError):
1254N/A """The publisher has no active repositories that support the
1254N/A requested operation."""
1254N/A
1254N/A def __init__(self, pub, operation):
1254N/A ApiException.__init__(self)
1254N/A self.data = None
1254N/A self.kwargs = None
1254N/A self.pub = pub
926N/A self.op = operation
926N/A
926N/A def __str__(self):
926N/A return _("Publisher '%(pub)s' has no repositories that support "
1516N/A "the '%(op)s' operation.") % self.__dict__
1516N/A
926N/A
926N/Aclass RepoPubConfigUnavailable(PublisherError):
926N/A """Used to indicate that the specified repository does not provide
926N/A publisher configuration information."""
926N/A
926N/A def __init__(self, location=None, pub=None):
926N/A ApiException.__init__(self)
926N/A self.location = location
926N/A self.pub = pub
926N/A
926N/A def __str__(self):
926N/A if not self.location and not self.pub:
926N/A return _("The specified package repository does not "
926N/A "provide publisher configuration information.")
926N/A if self.location:
926N/A return _("The package repository at %s does not "
926N/A "provide publisher configuration information or "
926N/A "the information provided is incomplete.") % \
926N/A self.location
926N/A return _("One of the package repository origins for %s does "
926N/A "not provide publisher configuration information or the "
926N/A "information provided is incomplete.") % self.pub
1516N/A
1516N/A
926N/Aclass UnknownRepositoryOrigin(PublisherError):
926N/A """Used to indicate that a repository URI could not be found in the
926N/A list of repository origins."""
926N/A
926N/A def __str__(self):
926N/A return _("Unknown repository origin '%s'") % self.data
926N/A
926N/A
926N/Aclass UnsupportedRepositoryURI(PublisherError):
926N/A """Used to indicate that the specified repository URI uses an
926N/A unsupported scheme."""
926N/A
926N/A def __str__(self):
926N/A if self.data:
926N/A scheme = urlparse.urlsplit(self.data,
926N/A allow_fragments=0)[0]
941N/A return _("The URI '%(uri)s' uses the unsupported "
941N/A "scheme '%(scheme)s'. Supported schemes are "
941N/A "file://, http://, and https://.") % {
2028N/A "uri": self.data, "scheme": scheme }
1100N/A return _("The specified URI uses an unsupported scheme."
1100N/A " Supported schemes are: file://, http://, and https://.")
941N/A
941N/A
941N/Aclass UnsupportedRepositoryURIAttribute(PublisherError):
941N/A """Used to indicate that the specified repository URI attribute is not
941N/A supported for the URI's scheme."""
1027N/A
1337N/A def __str__(self):
1352N/A return _("'%(attr)s' is not supported for '%(scheme)s'.") % {
1337N/A "attr": self.data, "scheme": self._args["scheme"] }
1337N/A
1337N/A
1337N/Aclass UnknownSysrepoConfiguration(ApiException):
1337N/A """Used when a pkg client needs to communicate with the system
1337N/A repository but can't find the configuration for it."""
1337N/A
1337N/A def __str__(self):
1337N/A return _("""\
1352N/Apkg is configured to use the system repository (via the use-system-repo
1352N/Aproperty) but it could not get the host and port from
1352N/Asvc:/application/pkg/zones-proxy-client nor svc:/application/pkg/system-repository, and
1352N/Athe PKG_SYSREPO_URL environment variable was not set. Please try enabling one
1352N/Aof those services or setting the PKG_SYSREPO_URL environment variable.
1352N/A""")
1352N/A
1352N/A
1352N/Aclass ModifyingSyspubException(ApiException):
1352N/A """This exception is raised when a user attempts to modify a system
1352N/A publisher."""
1516N/A
1352N/A def __init__(self, s):
1352N/A self.s = s
1352N/A
1352N/A def __str__(self):
1352N/A return self.s
1352N/A
1352N/A
1352N/Aclass SigningException(ApiException):
1352N/A """The base class for exceptions related to manifest signing."""
1352N/A
1352N/A def __init__(self, pfmri=None, sig=None):
1352N/A self.pfmri = pfmri
1352N/A self.sig = sig
1370N/A
1736N/A # This string method is used by subclasses to fill in the details
1736N/A # about the package and signature involved.
1736N/A def __str__(self):
1736N/A if self.pfmri:
1736N/A if self.sig:
1736N/A return _("The relevant signature action is "
1736N/A "found in %(pfmri)s and has a hash of "
1736N/A "%(hsh)s") % \
1736N/A {"pfmri": self.pfmri, "hsh": self.sig.hash}
1736N/A return _("The package involved is:%s") % self.pfmri
1736N/A if self.sig:
1736N/A return _("The relevant signature action's value "
1736N/A "attribute is %s") % self.sig.attrs["value"]
1736N/A return ""
1736N/A
1736N/A
1370N/Aclass BadFileFormat(SigningException):
1370N/A """Exception used when a key, certificate or CRL file is not in a
1370N/A recognized format."""
1736N/A
1370N/A def __init__(self, txt):
1370N/A self.txt = txt
1370N/A
1370N/A def __str__(self):
1370N/A return self.txt
1370N/A
1370N/A
1370N/Aclass UnsupportedSignatureVersion(SigningException):
1370N/A """Exception used when a signature reports a version which this version
1370N/A of pkg(5) doesn't support."""
1370N/A
1370N/A def __init__(self, version, *args, **kwargs):
2097N/A SigningException.__init__(self, *args, **kwargs)
2097N/A self.version = version
2097N/A
2097N/A def __str__(self):
2144N/A return _("The signature action %(act)s was made using a "
2144N/A "version (%(ver)s) this version of pkg(5) doesn't "
2144N/A "understand.") % {"act":self.sig, "ver":self.version}
2144N/A
2144N/A
2144N/Aclass CertificateException(SigningException):
2144N/A """Base class for exceptions encountered while establishing the chain
2144N/A of trust."""
2144N/A
2144N/A def __init__(self, cert, pfmri=None):
2144N/A SigningException.__init__(self, pfmri)
2144N/A self.cert = cert
2144N/A
2144N/A
2144N/Aclass ModifiedCertificateException(CertificateException):
2144N/A """Exception used when a certificate does not match its expected hash
2097N/A value."""
2097N/A
1370N/A def __init__(self, cert, path, pfmri=None):
1370N/A CertificateException.__init__(self, cert, pfmri)
1370N/A self.path = path
1370N/A
2026N/A def __str__(self):
2026N/A return _("Certificate %s has been modified on disk. Its hash "
2073N/A "value is not what was expected.") % self.path
2073N/A
2073N/A
2073N/Aclass UntrustedSelfSignedCert(CertificateException):
2073N/A """Exception used when a chain of trust is rooted in an untrusted
2073N/A self-signed certificate."""
2073N/A
2073N/A def __str__(self):
2073N/A return _("Chain was rooted in an untrusted self-signed "
2073N/A "certificate.\n") + CertificateException.__str__(self)
2073N/A
2026N/A
2026N/Aclass BrokenChain(CertificateException):
2026N/A """Exception used when a chain of trust can not be established between
2026N/A the leaf certificate and a trust anchor."""
2026N/A
2026N/A def __init__(self, cert, cert_exceptions, *args, **kwargs):
2026N/A CertificateException.__init__(self, cert, *args, **kwargs)
self.ext_exs = cert_exceptions
def __str__(self):
s = ""
if self.ext_exs:
s = _("The following problems were encountered:\n") + \
"\n".join([str(e) for e in self.ext_exs])
return _("The certificate which issued this "
"certificate:%(subj)s could not be found. The issuer "
"is:%(issuer)s\n") % {"subj":self.cert.get_subject(),
"issuer":self.cert.get_issuer()} + s + \
CertificateException.__str__(self)
class RevokedCertificate(CertificateException):
"""Exception used when a chain of trust contains a revoked certificate.
"""
def __init__(self, cert, reason, *args, **kwargs):
CertificateException.__init__(self, cert, *args, **kwargs)
self.reason = reason
def __str__(self):
return _("This certificate was revoked:%(cert)s for this "
"reason:\n%(reason)s") % {"cert":self.cert.get_subject(),
"reason":self.reason} + CertificateException.__str__(self)
class UnverifiedSignature(SigningException):
"""Exception used when a signature could not be verified by the
expected certificate."""
def __init__(self, sig, reason, pfmri=None):
SigningException.__init__(self, pfmri)
self.sig = sig
self.reason = reason
def __str__(self):
if self.pfmri:
return _("A signature in %(pfmri)s could not be "
"verified for "
"this reason:\n%(reason)s\nThe signature's hash is "
"%(hash)s") % {"pfmri": self.pfmri,
"reason": self.reason,
"hash": self.sig.hash}
return _("The signature with this signature value:\n"
"%(sigval)s\n could not be verified for this reason:\n"
"%(reason)s\n") % {"reason": self.reason,
"sigval": self.sig.attrs["value"]}
class RequiredSignaturePolicyException(SigningException):
"""Exception used when signatures were required but none were found."""
def __init__(self, pub, pfmri=None):
SigningException.__init__(self, pfmri)
self.pub = pub
def __str__(self):
pub_str = self.pub.prefix
if self.pfmri:
return _("The policy for %(pub_str)s requires "
"signatures to be present but no signature was "
"found in %(fmri_str)s.") % \
{"pub_str": pub_str, "fmri_str": self.pfmri}
return _("The policy for %(pub_str)s requires signatures to be "
"present but no signature was found.") % {
"pub_str": pub_str}
class MissingRequiredNamesException(SigningException):
"""Exception used when a signature policy required names to be seen
which weren't seen."""
def __init__(self, pub, missing_names, pfmri=None):
SigningException.__init__(self, pfmri)
self.pub = pub
self.missing_names = missing_names
def __str__(self):
pub_str = self.pub.prefix
if self.pfmri:
return _("The policy for %(pub_str)s requires certain "
"CNs to be seen in a chain of trust. The following "
"required names couldn't be found for this "
"package:%(fmri_str)s.\n%(missing)s") % \
{"pub_str": pub_str, "fmri_str": self.pfmri,
"missing": "\n".join(self.missing_names)}
return _("The policy for %(pub_str)s requires certain CNs to "
"be seen in a chain of trust. The following required names "
"couldn't be found.\n%(missing)s") % {"pub_str": pub_str,
"missing": "\n".join(self.missing_names)}
class UnsupportedCriticalExtension(SigningException):
"""Exception used when a certificate in the chain of trust uses a
critical extension pkg5 doesn't understand."""
def __init__(self, cert, ext):
SigningException.__init__(self)
self.cert = cert
self.ext = ext
def __str__(self):
return _("The certificate whose subject is %(cert)s could not "
"be verified "
"because it uses a critical extension that pkg5 cannot "
"handle yet.\nExtension name:%(name)s\nExtension "
"value:%(val)s") % {"cert": self.cert.get_subject(),
"name":self.ext.get_name(), "val":self.ext.get_value()}
class UnsupportedExtensionValue(SigningException):
"""Exception used when a certificate in the chain of trust has an
extension with a value pkg5 doesn't understand."""
def __init__(self, cert, ext, bad_val=None):
SigningException.__init__(self)
self.cert = cert
self.ext = ext
self.bad_val = bad_val
def __str__(self):
s = _("The certificate whose subject is %(cert)s could not be "
"verified because it has an extension with a value that "
"pkg(5) does not understand."
"\nExtension name:%(name)s\nExtension value:%(val)s") % \
{"cert": self.cert.get_subject(),
"name":self.ext.get_name(), "val":self.ext.get_value()}
if self.bad_val:
s += _("\nProblematic Value:%s") % (self.bad_val,)
return s
class InappropriateCertificateUse(SigningException):
"""Exception used when a certificate in the chain of trust has been used
inappropriately. An example would be a certificate which was only
supposed to be used to sign code being used to sign other certificates.
"""
def __init__(self, cert, ext, use):
SigningException.__init__(self)
self.cert = cert
self.ext = ext
self.use = use
def __str__(self):
return _("The certificate whose subject is %(cert)s could not "
"be verified because it has been used inappropriately. "
"The way it is used means that the value for extension "
"%(name)s must include '%(use)s' but the value was "
"'%(val)s'.") % {"cert": self.cert.get_subject(),
"use": self.use, "name":self.ext.get_name(),
"val":self.ext.get_value()}
class PathlenTooShort(InappropriateCertificateUse):
"""Exception used when a certificate in the chain of trust has been used
inappropriately. An example would be a certificate which was only
supposed to be used to sign code being used to sign other certificates.
"""
def __init__(self, cert, actual_length, cert_length):
SigningException.__init__(self)
self.cert = cert
self.al = actual_length
self.cl = cert_length
def __str__(self):
return _("The certificate whose subject is %(cert)s could not "
"be verified because it has been used inappropriately. "
"There can only be %(cl)s certificates between this "
"certificate and the leaf certificate. There are %(al)s "
"certificates between this certificate and the leaf in "
"this chain.") % {
"cert": self.cert.get_subject(),
"al": self.al,
"cl": self.cl
}
class AlmostIdentical(ApiException):
"""Exception used when a package already has a signature action which is
nearly identical to the one being added but differs on some
attributes."""
def __init__(self, hsh, algorithm, version, pkg=None):
self.hsh = hsh
self.algorithm = algorithm
self.version = version
self.pkg = pkg
def __str__(self):
s = _("The signature to be added to the package has the same "
"hash (%(hash)s), algorithm (%(algorithm)s), and "
"version (%(version)s) as an existing signature, but "
"doesn't match the signature exactly. For this signature "
"to be added, the existing signature must be removed.") % {
"hash": self.hsh,
"algorithm": self.algorithm,
"version": self.version
}
if self.pkg:
s += _("The package being signed was %(pkg)s") % \
{"pkg": self.pkg}
return s
class DuplicateSignaturesAlreadyExist(ApiException):
"""Exception used when a package already has a signature action which is
nearly identical to the one being added but differs on some
attributes."""
def __init__(self, pfmri):
self.pfmri = pfmri
def __str__(self):
return _("%s could not be signed because it already has two "
"copies of this signature in it. One of those signature "
"actions must be removed before the package is given to "
"users.") % self.pfmri
class InvalidPropertyValue(ApiException):
"""Exception used when a property was set to an invalid value."""
def __init__(self, s):
ApiException.__init__(self)
self.str = s
def __str__(self):
return self.str
class CertificateError(ApiException):
"""Base exception class for all certificate exceptions."""
def __init__(self, *args, **kwargs):
ApiException.__init__(self, *args)
if args:
self.data = args[0]
else:
self.data = None
self._args = kwargs
def __str__(self):
return str(self.data)
class ExpiredCertificate(CertificateError):
"""Used to indicate that a certificate has expired."""
def __str__(self):
publisher = self._args.get("publisher", None)
uri = self._args.get("uri", None)
if publisher:
if uri:
return _("Certificate '%(cert)s' for publisher "
"'%(pub)s' needed to access '%(uri)s', "
"has expired. Please install a valid "
"certificate.") % { "cert": self.data,
"pub": publisher, "uri": uri }
return _("Certificate '%(cert)s' for publisher "
"'%(pub)s', has expired. Please install a valid "
"certificate.") % { "cert": self.data,
"pub": publisher }
if uri:
return _("Certificate '%(cert)s', needed to access "
"'%(uri)s', has expired. Please install a valid "
"certificate.") % { "cert": self.data, "uri": uri }
return _("Certificate '%s' has expired. Please install a "
"valid certificate.") % self.data
class ExpiringCertificate(CertificateError):
"""Used to indicate that a certificate has expired."""
def __str__(self):
publisher = self._args.get("publisher", None)
uri = self._args.get("uri", None)
days = self._args.get("days", 0)
if publisher:
if uri:
return _("Certificate '%(cert)s' for publisher "
"'%(pub)s', needed to access '%(uri)s', "
"will expire in '%(days)s' days.") % {
"cert": self.data, "pub": publisher,
"uri": uri, "days": days }
return _("Certificate '%(cert)s' for publisher "
"'%(pub)s' will expire in '%(days)s' days.") % {
"cert": self.data, "pub": publisher, "days": days }
if uri:
return _("Certificate '%(cert)s', needed to access "
"'%(uri)s', will expire in '%(days)s' days.") % {
"cert": self.data, "uri": uri, "days": days }
return _("Certificate '%(cert)s' will expire in "
"'%(days)s' days.") % { "cert": self.data, "days": days }
class InvalidCertificate(CertificateError):
"""Used to indicate that a certificate is invalid."""
def __str__(self):
publisher = self._args.get("publisher", None)
uri = self._args.get("uri", None)
if publisher:
if uri:
return _("Certificate '%(cert)s' for publisher "
"'%(pub)s', needed to access '%(uri)s', is "
"invalid.") % { "cert": self.data,
"pub": publisher, "uri": uri }
return _("Certificate '%(cert)s' for publisher "
"'%(pub)s' is invalid.") % { "cert": self.data,
"pub": publisher }
if uri:
return _("Certificate '%(cert)s' needed to access "
"'%(uri)s' is invalid.") % { "cert": self.data,
"uri": uri }
return _("Invalid certificate '%s'.") % self.data
class NoSuchKey(CertificateError):
"""Used to indicate that a key could not be found."""
def __str__(self):
publisher = self._args.get("publisher", None)
uri = self._args.get("uri", None)
if publisher:
if uri:
return _("Unable to locate key '%(key)s' for "
"publisher '%(pub)s' needed to access "
"'%(uri)s'.") % { "key": self.data,
"pub": publisher, "uri": uri }
return _("Unable to locate key '%(key)s' for publisher "
"'%(pub)s'.") % { "key": self.data, "pub": publisher
}
if uri:
return _("Unable to locate key '%(key)s' needed to "
"access '%(uri)s'.") % { "key": self.data,
"uri": uri }
return _("Unable to locate key '%s'.") % self.data
class NoSuchCertificate(CertificateError):
"""Used to indicate that a certificate could not be found."""
def __str__(self):
publisher = self._args.get("publisher", None)
uri = self._args.get("uri", None)
if publisher:
if uri:
return _("Unable to locate certificate "
"'%(cert)s' for publisher '%(pub)s' needed "
"to access '%(uri)s'.") % {
"cert": self.data, "pub": publisher,
"uri": uri }
return _("Unable to locate certificate '%(cert)s' for "
"publisher '%(pub)s'.") % { "cert": self.data,
"pub": publisher }
if uri:
return _("Unable to locate certificate '%(cert)s' "
"needed to access '%(uri)s'.") % {
"cert": self.data, "uri": uri }
return _("Unable to locate certificate '%s'.") % self.data
class NotYetValidCertificate(CertificateError):
"""Used to indicate that a certificate is not yet valid (future
effective date)."""
def __str__(self):
publisher = self._args.get("publisher", None)
uri = self._args.get("uri", None)
if publisher:
if uri:
return _("Certificate '%(cert)s' for publisher "
"'%(pub)s', needed to access '%(uri)s', "
"has a future effective date.") % {
"cert": self.data, "pub": publisher,
"uri": uri }
return _("Certificate '%(cert)s' for publisher "
"'%(pub)s' has a future effective date.") % {
"cert": self.data, "pub": publisher }
if uri:
return _("Certificate '%(cert)s' needed to access "
"'%(uri)s' has a future effective date.") % {
"cert": self.data, "uri": uri }
return _("Certificate '%s' has a future effective date.") % \
self.data
class ServerReturnError(ApiException):
"""This exception is used when the server returns a line which the
client cannot parse correctly."""
def __init__(self, line):
ApiException.__init__(self)
self.line = line
def __str__(self):
return _("Gave a bad response:%s") % self.line
class MissingFileArgumentException(ApiException):
"""This exception is used when a file was given as an argument but
no such file could be found."""
def __init__(self, path):
ApiException.__init__(self)
self.path = path
def __str__(self):
return _("Could not find %s") % self.path
class ManifestError(ApiException):
"""Base exception class for all manifest exceptions."""
def __init__(self, *args, **kwargs):
ApiException.__init__(self, *args, **kwargs)
if args:
self.data = args[0]
else:
self.data = None
self._args = kwargs
def __str__(self):
return str(self.data)
class BadManifestSignatures(ManifestError):
"""Used to indicate that the Manifest signatures are not valid."""
def __str__(self):
if self.data:
return _("The signature data for the manifest of the "
"'%s' package is not valid.") % self.data
return _("The signature data for the manifest is not valid.")
class UnknownErrors(ApiException):
"""Used to indicate that one or more exceptions were encountered.
This is intended for use with where multiple exceptions for multiple
files are encountered and the errors have been condensed into a
single exception and re-raised. One example case would be rmtree()
with shutil.Error."""
def __init__(self, msg):
ApiException.__init__(self)
self.__msg = msg
def __str__(self):
return self.__msg
# Image creation exceptions
class ImageCreationException(ApiException):
def __init__(self, path):
ApiException.__init__(self)
self.path = path
def __str__(self):
raise NotImplementedError()
class ImageAlreadyExists(ImageCreationException):
def __str__(self):
return _("there is already an image at: %s.\nTo override, use "
"the -f (force) option.") % self.path
class ImageCfgEmptyError(ApiException):
"""Used to indicate that the image configuration is invalid."""
def __str__(self):
return _("The configuration data for the image rooted at "
"%s is empty or missing.") % self.data
class UnsupportedImageError(ApiException):
"""Used to indicate that the image at a specific location is in a format
not supported by this version of the pkg(5) API."""
def __init__(self, path):
ApiException.__init__(self)
self.path = path
def __str__(self):
return _("The image rooted at %s is invalid or is not "
"supported by this version of the packaging system.") % \
self.path
class CreatingImageInNonEmptyDir(ImageCreationException):
def __str__(self):
return _("the specified image path is not empty: %s.\nTo "
"override, use the -f (force) option.") % self.path
def _convert_error(e, ignored_errors=EmptyI):
"""Converts the provided exception into an ApiException equivalent if
possible. Returns a new exception object if converted or the original
if not.
'ignored_errors' is an optional list of errno values for which None
should be returned.
"""
if not hasattr(e, "errno"):
return e
if e.errno in ignored_errors:
return None
if e.errno in (errno.EACCES, errno.EPERM):
return PermissionsException(e.filename)
if e.errno == errno.EROFS:
return ReadOnlyFileSystemException(e.filename)
return e
class LinkedImageException(ApiException):
def __init__(self, bundle=None, lin=None, exitrv=None,
attach_bad_prop=None,
attach_bad_prop_value=None,
attach_child_notsup=None,
attach_parent_notsup=None,
attach_root_as_child=None,
child_bad_img=None,
child_diverged=None,
child_dup=None,
child_nested=None,
child_not_in_altroot=None,
child_not_nested=None,
child_op_failed=None,
child_path_eaccess=None,
child_path_notabs=None,
child_unknown=None,
detach_child_notsup=None,
detach_from_parent=None,
detach_parent_notsup=None,
img_linked=None,
lin_malformed=False,
link_to_self=False,
parent_bad_img=None,
parent_bad_notabs=None,
parent_bad_path=None,
parent_not_in_altroot=None,
recursive_cmd_fail=None,
self_linked=None,
self_not_child=None):
self.attach_bad_prop = attach_bad_prop
self.attach_bad_prop_value = attach_bad_prop_value
self.attach_child_notsup = attach_child_notsup
self.attach_parent_notsup = attach_parent_notsup
self.attach_root_as_child = attach_root_as_child
self.child_bad_img = child_bad_img
self.child_diverged = child_diverged
self.child_dup = child_dup
self.child_nested = child_nested
self.child_not_in_altroot = child_not_in_altroot
self.child_not_nested = child_not_nested
self.child_op_failed = child_op_failed
self.child_path_eaccess = child_path_eaccess
self.child_path_notabs = child_path_notabs
self.child_unknown = child_unknown
self.detach_child_notsup = detach_child_notsup
self.detach_from_parent = detach_from_parent
self.detach_parent_notsup = detach_parent_notsup
self.img_linked = img_linked
self.lin_malformed = lin_malformed
self.link_to_self = link_to_self
self.parent_bad_img = parent_bad_img
self.parent_bad_notabs = parent_bad_notabs
self.parent_bad_path = parent_bad_path
self.parent_not_in_altroot = parent_not_in_altroot
self.recursive_cmd_fail = recursive_cmd_fail
self.self_linked = self_linked
self.self_not_child = self_not_child
# first deal with an error bundle
if bundle:
assert type(bundle) in [tuple, list, set]
for e in bundle:
assert isinstance(e, LinkedImageException)
# set default error return value
if exitrv == None:
exitrv = pkgdefs.EXIT_OOPS
self.lix_err = None
self.lix_bundle = bundle
self.lix_exitrv = exitrv
return
err = None
if attach_bad_prop:
err = _("Invalid linked image attach property: %s") % \
attach_bad_prop
if attach_bad_prop_value:
assert type(attach_bad_prop_value) in [tuple, list]
assert len(attach_bad_prop_value) == 2
err = _("Invalid linked image attach property "
"value: %s") % "=".join(attach_bad_prop_value)
if attach_child_notsup:
err = _("Linked image type does not support child "
"attach: %s") % attach_child_notsup
if attach_parent_notsup:
err = _("Linked image type does not support parent "
"attach: %s") % attach_parent_notsup
if attach_root_as_child:
err = _("Cannot attach root image as child")
if child_bad_img:
if exitrv == None:
exitrv = pkgdefs.EXIT_EACCESS
if lin:
err = _("Can't initialize child image "
"(%(lin)s) at path: %(path)s") % {
"lin": lin,
"path": child_bad_img
}
else:
err = _("Can't initialize child image "
"at path: %s") % child_bad_img
if child_diverged:
if exitrv == None:
exitrv = pkgdefs.EXIT_DIVERGED
err = _("Linked image is diverged: %s") % \
child_diverged
if child_dup:
err = _("A linked child image with this name "
"already exists: %s") % child_dup
if child_nested:
cpath, ipath = child_nested
err = _("Child image '%(cpath)s' is nested "
"within another image: '%(ipath)s'") % {
"cpath": cpath,
"ipath": ipath,
}
if child_not_in_altroot:
path, altroot = child_not_in_altroot
err = _("Child image '%(path)s' is not located "
"within the parent's altroot '%(altroot)s'") % {
"path": path,
"altroot": altroot
}
if child_not_nested:
cpath, ppath = child_not_nested
err = _("Child image '%(cpath)s' is not nested "
"within the parent image '%(ppath)s'") % {
"cpath": cpath,
"ppath": ppath,
}
if child_op_failed:
assert lin
err = _("Linked image %(op)s failed for: %(lin)s") % \
{"op": child_op_failed, "lin": lin}
if child_path_eaccess:
if exitrv == None:
exitrv = pkgdefs.EXIT_EACCESS
if lin:
err = _("Can't access child image "
"(%(lin)s) at path: %(path)s") % {
"lin": lin,
"path": child_path_eaccess
}
else:
err = _("Can't access child image "
"at path: %s") % child_path_eaccess
if child_path_notabs:
err = _("Child path not absolute: %s") % \
child_path_notabs
if child_unknown:
err = _("Unknown child linked image: %s") % \
child_unknown
if detach_child_notsup:
err = _("Linked image type does not support "
"child detach: %s") % detach_child_notsup
if detach_from_parent:
if exitrv == None:
exitrv = pkgdefs.EXIT_PARENTOP
err = _("Parent linked to child, can not detach "
"child: %s") % detach_from_parent
if detach_parent_notsup:
err = _("Linked image type does not support "
"parent detach: %s") % detach_parent_notsup
if img_linked:
err = _("Image already a linked child: %s") % \
img_linked
if lin_malformed:
err = _("Invalid linked image name: %s") % \
lin_malformed
if link_to_self:
err = _("Can't link image to itself.")
if parent_bad_img:
if exitrv == None:
exitrv = pkgdefs.EXIT_EACCESS
err = _("Can't initialize parent image at path: %s") % \
parent_bad_img
if parent_bad_notabs:
err = _("Parent path not absolute: %s") % \
parent_bad_notabs
if parent_bad_path:
if exitrv == None:
exitrv = pkgdefs.EXIT_EACCESS
err = _("Can't access parent image at path: %s") % \
parent_bad_path
if parent_not_in_altroot:
path, altroot = parent_not_in_altroot
err = _("Parent image '%(path)s' is not located "
"within the child's altroot '%(altroot)s'") % {
"path": path,
"altroot": altroot
}
if recursive_cmd_fail:
if type(recursive_cmd_fail) == list:
recursive_cmd_fail = \
" ".join(recursive_cmd_fail)
assert type(recursive_cmd_fail) == str
err = _("""
Recursive linked image operation failed for child '%(lin)s'.
The following subprocess returned an unexpected exit code of %(exitrv)d:
%(recursive_cmd_fail)s"""
) % {
"lin": lin,
"exitrv": exitrv,
"recursive_cmd_fail": recursive_cmd_fail,
}
if self_linked:
err = _("Current image already a linked child: %s") % \
self_linked
if self_not_child:
if exitrv == None:
exitrv = pkgdefs.EXIT_NOPARENT
err = _("Current image is not a linked child: %s") % \
self_not_child
# set default error return value
if exitrv == None:
exitrv = pkgdefs.EXIT_OOPS
self.lix_err = err
self.lix_bundle = None
self.lix_exitrv = exitrv
def __str__(self):
assert self.lix_err or self.lix_bundle
assert not (self.lix_err and self.lix_bundle), \
"self.lix_err = %s, self.lix_bundle = %s" % \
(str(self.lix_err), str(self.lix_bundle))
# single error
if self.lix_err:
return self.lix_err
# concatenate multiple errors
bundle_str = []
for e in self.lix_bundle:
bundle_str.append(str(e))
return "\n".join(bundle_str)