18867978 pkg firmware revision dep mechanism should be expanded for platform-specifics
--- a/src/modules/actions/depend.py Mon Apr 04 16:35:45 2016 +1000
+++ b/src/modules/actions/depend.py Fri Apr 01 17:41:13 2016 -0700
@@ -21,7 +21,7 @@
#
#
-# Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
#
@@ -40,7 +40,7 @@
import pkg.fmri
import pkg.version
-from pkg.client.firmware import Firmware
+from pkg.client.firmware import Driver, Cpu
known_types = (
"conditional",
@@ -60,6 +60,7 @@
#
DEPEND_SELF = "feature/package/dependency/self"
+
class DependencyAction(generic.Action):
"""Class representing a dependency packaging object. The fmri attribute
is expected to be the pkg FMRI that this package depends on. The type
@@ -106,9 +107,10 @@
generic.Action.__init__(self, data, **attrs)
try:
if self.attrs["type"] not in known_types:
- raise pkg.actions.InvalidActionError(str(self),
- _("Unknown type ({0}) in depend action").format(
- self.attrs["type"]))
+ raise pkg.actions.InvalidActionError(
+ str(self),
+ _("Unknown type ({0}) in depend action").
+ format(self.attrs["type"]))
except KeyError:
raise pkg.actions.InvalidActionError(
str(self), _("Missing type attribute"))
@@ -128,64 +130,67 @@
errors = []
if fmri.pkg_name not in ppkgs_dict:
- errors.append(_("Package is not installed in "
- "parent image {0}").format(fmri.pkg_name))
+ errors.append(
+ _("Package is not installed in "
+ "parent image {0}").format(fmri.pkg_name))
return errors
pf = ppkgs_dict[fmri.pkg_name]
if fmri.publisher and fmri.publisher != pf.publisher:
# package is from a different publisher
errors.append(_("Package in parent is from a "
- "different publisher: {0}").format(pf))
+ "different publisher: {0}").
+ format(pf))
return errors
if pf.version == fmri.version or pf.version.is_successor(
- fmri.version, pkg.version.CONSTRAINT_AUTO):
+ fmri.version, pkg.version.CONSTRAINT_AUTO):
# parent dependency is satisfied
return []
if pf.version.is_successor(fmri.version,
- pkg.version.CONSTRAINT_NONE):
+ pkg.version.CONSTRAINT_NONE):
errors.append(_("Parent image has a newer "
- "version of package {0}").format(pf))
+ "version of package {0}").format(pf))
else:
errors.append(_("Parent image has an older "
- "version of package {0}").format(pf))
+ "version of package {0}").format(pf))
return errors
def __check_installed(self, image, installed_version, min_fmri,
- max_fmri, required, ctype):
+ max_fmri, required, ctype):
errors = []
if not installed_version:
return errors
vi = installed_version.version
if min_fmri and min_fmri.version and \
- min_fmri.version.is_successor(vi,
- pkg.version.CONSTRAINT_NONE):
+ min_fmri.version.is_successor(
+ vi, pkg.version.CONSTRAINT_NONE):
errors.append(
_("{dep_type} dependency {dep_val} "
- "is downrev ({inst_ver})").format(
- dep_type=ctype, dep_val=min_fmri,
- inst_ver=installed_version))
+ "is downrev ({inst_ver})").format(
+ dep_type=ctype, dep_val=min_fmri,
+ inst_ver=installed_version))
return errors
if max_fmri and max_fmri.version and \
vi > max_fmri.version and \
not vi.is_successor(max_fmri.version,
- pkg.version.CONSTRAINT_AUTO):
+ pkg.version.CONSTRAINT_AUTO):
errors.append(
_("{dep_type} dependency {dep_val} "
- "is uprev ({inst_ver})").format(
- dep_type=ctype, dep_val=max_fmri,
- inst_ver=installed_version))
+ "is uprev ({inst_ver})").format(
+ dep_type=ctype, dep_val=max_fmri,
+ inst_ver=installed_version))
return errors
if required and pkgdefs.PKG_STATE_OBSOLETE in \
- image.get_pkg_state(installed_version):
+ image.get_pkg_state(installed_version):
errors.append(
- _("{dep_type} dependency on an obsolete package "
- "({obs_pkg}); this package must be uninstalled "
- "manually").format(
- dep_type=ctype, obs_pkg=installed_version))
+ _("{dep_type} dependency on an obsolete "
+ "package ({obs_pkg}); this package must "
+ "be uninstalled manually").format(
+ dep_type=ctype,
+ obs_pkg=installed_version))
return errors
return errors
@@ -210,8 +215,8 @@
if ctype not in known_types:
errors.append(
- _("Unknown type ({0}) in depend action").format(
- ctype))
+ _("Unknown type ({0}) in depend action").
+ format(ctype))
return errors, warnings, info
# get a list of fmris and do fmri token substitution
@@ -225,8 +230,8 @@
if ctype == "parent":
# handle "parent" dependencies here
assert len(pfmris) == 1
- errors.extend(self.__check_parent_installed(image,
- pfmris[0]))
+ errors.extend(self.__check_parent_installed(
+ image, pfmris[0]))
return errors, warnings, info
installed_versions = [
@@ -257,45 +262,55 @@
cfmri = pkg.fmri.PkgFmri(self.attrs["predicate"])
installed_cversion = image.get_version_installed(cfmri)
if installed_cversion is not None and \
- installed_cversion.is_successor(cfmri):
+ installed_cversion.is_successor(cfmri):
min_fmri = pfmri
required = True
elif ctype == "group":
if pfmri.pkg_name not in \
- (image.avoid_set_get() | image.obsolete_set_get()):
+ (image.avoid_set_get() | image.obsolete_set_get()):
required = True
elif ctype == "require-any":
for ifmri, rpfmri in zip(installed_versions, pfmris):
- e = self.__check_installed(image, ifmri, rpfmri,
- None, True, ctype)
+ e = self.__check_installed(image, ifmri,
+ rpfmri, None, True,
+ ctype)
if ifmri and not e:
# this one is present and happy
return [], [], []
else:
errors.extend(e)
- if not errors: # none was installed
- errors.append(_("Required dependency on one of "
- "{0} not met").format(
- ", ".join((str(p) for p in pfmris))))
+ if not errors: # none was installed
+ errors.append(
+ _("Required dependency on one of "
+ "{0} not met").
+ format(", ".join((str(p)
+ for p in pfmris))))
return errors, warnings, info
elif ctype == "origin" and pfmri.pkg_name.startswith(
- "feature/firmware/"):
- ok, reason = Firmware().check_firmware(self, pfmri.pkg_name)
+ "feature/firmware/"):
+ ok, reason = Driver().check(self, pfmri.pkg_name)
+ if ok:
+ return [], [], []
+ else:
+ errors.append(reason)
+ elif ctype == "origin" and pfmri.pkg_name.startswith(
+ "feature/cpu"):
+ ok, reason = Cpu().check(self, pfmri.pkg_name)
if ok:
return [], [], []
else:
errors.append(reason)
- # can only check origin firmware dependencies
-
# do checking for other dependency types
- errors.extend(self.__check_installed(image, installed_version,
- min_fmri, max_fmri, required, ctype))
+ errors.extend(self.__check_installed(image,
+ installed_version,
+ min_fmri, max_fmri,
+ required, ctype))
if required and not installed_version:
errors.append(_("Required dependency {0} is not "
- "installed").format(pfmri))
+ "installed").format(pfmri))
# cannot verify origin since it applys to upgrade
# operation, not final state
@@ -313,11 +328,11 @@
return []
#
- # XXX Ideally, we'd turn the string into a PkgFmri, and separate
- # the stem from the version, or use get_dir_path, but we can't
- # create a PkgFmri without supplying a build release and without
- # it creating a dummy timestamp. So we have to split it apart
- # manually.
+ # XXX Ideally, we'd turn the string into a PkgFmri, and
+ # separate the stem from the version, or use get_dir_path,
+ # but we can't create a PkgFmri without supplying a build
+ # release and without it creating a dummy timestamp.
+ # Instead we have to split it apart manually.
#
if isinstance(pfmris, six.string_types):
pfmris = [pfmris]
@@ -382,6 +397,7 @@
return (kvord(a), a[0])
JOIN_TOK = " \\\n " + base_indent
+
def grow(a, b, rem_values, force_nl=False):
if not force_nl:
lastnl = a.rfind("\n")
@@ -394,8 +410,8 @@
max_len = 80
else:
# If V1 format, or there are more
- # attributes to output, then account for
- # line-continuation marker.
+ # attributes to output, then account
+ # for the line-continuation marker.
max_len = 78
# Note this length comparison doesn't include
@@ -411,16 +427,17 @@
first_line = True
# Total number of remaining attribute values to output.
- rem_count = sum(len(act.attrlist(k)) for k in act.attrs)
+ rem_count = sum(len(act.attrlist(k))
+ for k in act.attrs)
# Now build the action output string an attribute at a
# time.
for k, v in sorted(six.iteritems(act.attrs),
- key=key_func):
+ key=key_func):
# Newline breaks are only forced when there is
# more than one value for an attribute.
if not (isinstance(v, list) or
- isinstance(v, set)):
+ isinstance(v, set)):
nv = [v]
use_force_nl = False
else:
@@ -430,11 +447,12 @@
for lmt in sorted(nv):
force_nl = use_force_nl and \
k.startswith("pkg.debug")
- aout = grow(aout,
- "=".join((k,
- generic.quote_attr_value(lmt))),
- rem_count,
- force_nl=force_nl)
+ aout = grow(aout, "=".join(
+ (k,
+ generic.quote_attr_value(
+ lmt))),
+ rem_count,
+ force_nl=force_nl)
# Must be done for each value.
if first_line and JOIN_TOK in aout:
first_line = False
@@ -450,24 +468,28 @@
This is primarily intended for use during publication or during
error handling to provide additional diagonostics.
- 'fmri' is an optional package FMRI (object or string) indicating
- what package contained this action."""
+ 'fmri' is an optional package FMRI (object or string)
+ indicating what package contained this action."""
required_attrs = ["type"]
dtype = self.attrs.get("type")
if dtype == "conditional":
required_attrs.append("predicate")
- errors = generic.Action._validate(self, fmri=fmri,
- raise_errors=False, required_attrs=required_attrs,
- single_attrs=("predicate", "root-image", "ignore-check"))
+ errors = generic.Action._validate(
+ self, fmri=fmri, raise_errors=False,
+ required_attrs=required_attrs,
+ single_attrs=("predicate", "root-image",
+ "ignore-check"))
if "predicate" in self.attrs and dtype != "conditional":
- errors.append(("predicate", _("a predicate may only be "
- "specified for conditional dependencies")))
+ errors.append(("predicate",
+ _("a predicate may only be specified "
+ "for conditional dependencies")))
if "root-image" in self.attrs and dtype != "origin":
- errors.append(("root-image", _("the root-image "
- "attribute is only valid for origin dependencies")))
+ errors.append(("root-image",
+ _("the root-image attribute is only "
+ "valid for origin dependencies")))
# Logic here intentionally treats 'predicate' and 'fmri' as
# having multiple values for simplicity.
@@ -476,16 +498,20 @@
try:
pkg.fmri.PkgFmri(f)
except (pkg.version.VersionError,
- pkg.fmri.FmriError) as e:
+ pkg.fmri.FmriError) as e:
if attr == "fmri" and f == "__TBD":
# pkgdepend uses this special
# value.
continue
- errors.append((attr, _("invalid "
- "{attr} value '{value}': "
- "{error}").format(attr=attr,
- value=f, error=str(e))))
+ errors.append((
+ attr,
+ _("invalid {attr} value "
+ "'{value}': {error}").
+ format(attr=attr,
+ value=f,
+ error=str(e))))
if errors:
- raise pkg.actions.InvalidActionAttributesError(self,
- errors, fmri=fmri)
+ raise pkg.actions.InvalidActionAttributesError(
+ self,
+ errors, fmri=fmri)
--- a/src/modules/client/firmware.py Mon Apr 04 16:35:45 2016 +1000
+++ b/src/modules/client/firmware.py Fri Apr 01 17:41:13 2016 -0700
@@ -21,8 +21,9 @@
#
#
-# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
#
+
import os.path
import six
import sys
@@ -37,92 +38,161 @@
class Firmware(object):
def __init__(self):
- self.__firmware = {} # cache of things we've checked already
+ self._cache = {} # cache of things we've checked already
- def check_firmware(self, dep_action, firmware_name):
- """Check firmware dependency.
- returns ((true, false, none (internal error)),
- error text)"""
+ def _check(self, dep_action, which):
+ """Performs the subprocess invocation and returns
+ (status, outputbuffer) to the caller"""
- firmware_dir = "/usr/lib/fwenum"
# leverage smf test infrastructure
cmds_dir = DebugValues["smf_cmds_dir"]
if DebugValues["firmware-dependency-bypass"]:
return (True, None)
- if cmds_dir: # we're testing;
+ if cmds_dir: # we're testing;
firmware_dir = cmds_dir
+ else:
+ firmware_dir = "/usr/lib/fwenum"
- args = [os.path.join(firmware_dir, firmware_name[len("feature/firmware/"):])]
+ args = [os.path.join(firmware_dir, which)]
args.extend([
- "{0}={1}".format(k, quote_attr_value(v))
- for k,v in sorted(six.iteritems(dep_action.attrs))
- if k not in ["type", "root-image", "fmri"]
+ "{0}={1}".format(k, quote_attr_value(v))
+ for k, v in sorted(six.iteritems(dep_action.attrs))
])
- key = str(args)
+ # Set up the default return values
+ ret = 0
+ buf = ""
# use a cache since each check may be expensive and each
# pkg version may have the same dependency.
# ignore non-solaris systems here
- if portable.osname != "sunos" and key not in self.firmware:
- self.__firmware[key] = (True, None)
+ if portable.osname != "sunos" and key not in self._cache:
+ self._cache[key] = (True, None)
- if key not in self.__firmware:
+ if str(args) not in self._cache:
try:
- proc = subprocess.Popen(args, stdout=subprocess.PIPE,
+ proc = subprocess.Popen(
+ args,
+ stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
buf = proc.stdout.readlines()
ret = proc.wait()
- # if there was output, something went wrong.
- # Since generic errors are often exit(1),
- # map this to an internal error.
- if ret == 1 and len(buf) > 0:
- ret = 255
- if ret == 0:
- ans = (True, None)
- elif 0 < ret <= 239:
- ans = (False, (_("There are {0} instances"
- " of downrev firmware for the '{1}' "
- " devices present on this system. "
- "Update each to version {2} or better."
- ).format(ret, args[1],
- dep_action.attrs.get("minimum-version",
- _("UNSPECIFIED")))))
- elif ret == 240:
- ans = (False, (_("There are 240 or more "
- "instances of downrev firmware for the"
- "'{0}' devices present on this system. "
- "Update each to version {1} or better."
- ).format(args[1],
- dep_action.attrs.get("minimum-version",
- _("UNSPECIFIED")))))
- elif ret < 0:
- ans = (None,
- (_("Firmware dependency error: {0} "
- " exited due to signal {1}").format(
- " ".join(args), misc.signame(-ret))))
- else:
- ans = (None,
- (_("Firmware dependency error: General "
- "internal error {0} running '{1}': '{2}'"
- ).format(str(ret), " ".join(args),
- "\n".join(buf))))
except OSError as e:
# we have no enumerator installed. This can
- # occur if this driver is being installed
- # for the first time or, more likely, we
- # just added enumerators & a firmware dependency
- # for the first time. For now, drive on and
- # ignore this to permit the addition of such
- # dependencies concurrently with their
- # enumerarators.
- # ans = (None, (_("Firmware dependency error:"
- # " Cannot exec {0}: {1}").format(" ".join(args)
- # , str(e))))
- ans = (True, 0)
+ # occur if this driver is being installed for
+ # the first time or, more likely, we just added
+ # enumerators and a firmware dependency for the
+ # first time. For now, drive on and ignore this
+ # to permit the addition of such dependencies
+ # concurrently with their enumerarators.
+ buf = (_("Firmware dependency error:"
+ " Cannot exec {0}: {1}").format(
+ " ".join(args), str(e)))
+ ret = -1
+ return (ret, buf, args)
+
+
+class Cpu(Firmware):
+ """Check cpu dependency.
+ returns ((true, false, none (internal error)), error text)"""
+
+ def check(self, dep_action, enumerator):
+ (ret, buf, args) = self._check(dep_action, which="cpu")
+ if ret == 0:
+ ans = (True, None)
+ elif ret == -1:
+ ans = (True, 0)
+ elif ret == 1:
+ # the cpu version enumerator returns 1 and
+ # prints the appropriate string if the system
+ # we're running this on does not match the
+ # required (include/exclude) condition.
+ # We're not checking for valid args here since
+ # since that's already been done by the enumerator
+ checkargs = dict([j.split("=") for j in
+ args if j.startswith("check.")])
+ pvtype = checkargs["check.version-type"]
+ if pvtype == "iset":
+ vtype = "Instruction Set Element(s)"
+ elif pvtype == "plat":
+ vtype = "Platform Name(s)"
+ else:
+ vtype = "CPU Name(s)"
+ try:
+ innit = checkargs["check.include"] or None
+ mesg = "include: {0}".format(innit)
+ except KeyError, ke:
+ pass
+ try:
+ notit = checkargs["check.exclude"] or None
+ mesg = "exclude: {0}".format(notit)
+ except KeyError, ke:
+ pass
- self.__firmware[key] = ans
+ ans = (False,
+ (_("cpu dependency error: '{0}' does "
+ "not meet the the minimum "
+ "requirement for {1} {2}\n").
+ format("".join(buf).rstrip(),
+ vtype, mesg)))
+ else:
+ # enumerator error
+ ans = (False,
+ (_("cpu dependency error: "
+ "Unable to verify cpu type\n")))
+ key = str(args)
+ self._cache[key] = ans
+ return self._cache[key]
+
+
+class Driver(Firmware):
+ """Check driver firmware dependency.
+ returns ((true, false, none (internal error)), error text)"""
+
+ def check(self, dep_action, enumerator):
+ which = enumerator[len("feature/firmware/"):]
+ (ret, buf, args) = self._check(dep_action, which=which)
+ # if there was output, something went wrong.
- return self.__firmware[key]
+ min_ver = dep_action.attrs.get(
+ "check.minimum-version",
+ dep_action.attrs.get("minimum-version", _("UNSPECIFIED")))
+ # Since generic errors are often exit(1),
+ # map this to an internal error.
+ if ret == 1 and len(buf) > 0:
+ ret = 255
+ if ret == 0:
+ ans = (True, None)
+ elif ret == -1:
+ ans = (True, 0)
+ elif 0 < ret <= 239:
+ ans = (False,
+ (_("There are {0} instances of downrev "
+ "firmware for the '{1}' devices present "
+ "on this system. Update each to version "
+ "{2} or newer.").
+ format(ret, ret, min_ver)))
+ elif ret == 240:
+ ans = (False,
+ (_("There are 240 or more "
+ "instances of downrev firmware for the"
+ "'{0}' devices present on this system. "
+ "Update each to version {1} or better.").
+ format(ret, min_ver)))
+ elif ret < 0:
+ ans = (None,
+ (_("Firmware dependency error: {0} "
+ "exited due to signal {1}").format(
+ " ".join(buf), misc.signame(-ret))))
+ else:
+ ans = (None,
+ (_("Firmware dependency error: General "
+ "internal error {0} running '{1}': '{2}'").
+ format(str(ret),
+ " ".join(buf),
+ "\n".join(buf))))
+ key = str(args)
+ self._cache[key] = ans
+ return self._cache[key]
--- a/src/modules/client/pkg_solver.py Mon Apr 04 16:35:45 2016 +1000
+++ b/src/modules/client/pkg_solver.py Fri Apr 01 17:41:13 2016 -0700
@@ -46,7 +46,7 @@
from functools import reduce
from itertools import chain
from pkg.client.debugvalues import DebugValues
-from pkg.client.firmware import Firmware
+from pkg.client.firmware import Driver, Cpu
from pkg.client.pkgdefs import PKG_OP_UNINSTALL, PKG_OP_UPDATE
from pkg.misc import EmptyI, EmptyDict, N_
# Unable to import; pylint: disable=F0401
@@ -87,7 +87,8 @@
_TRIM_VARIANT = 21 # unsupported variant (e.g. i386 on sparc)
_TRIM_EXPLICIT_INSTALL = 22 # pkg.depend.explicit-install is true.
_TRIM_SYNCED_INC = 23 # incorporation must be in sync with parent
-_TRIM_MAX = 24 # number of trim constants
+_TRIM_CPU = 24 # cpu version requirement
+_TRIM_MAX = 25 # number of trim constants
class DependencyException(Exception):
@@ -219,8 +220,9 @@
for f in self.__parent_pkgs
])
- # cache of firmware dependencies
- self.__firmware = Firmware()
+ # cache of firmware and cpu dependencies
+ self.__firmware = Driver()
+ self.__cpu = Cpu()
self.__triggered_ops = {
PKG_OP_UNINSTALL : {
@@ -287,6 +289,7 @@
self.__dependents = None
self.__fmridict = {}
self.__firmware = None
+ self.__cpu = None
self.__allowed_downgrades = None
self.__dg_incorp_cache = None
self.__linked_pkgs = set()
@@ -3093,11 +3096,11 @@
req_fmri = pkg.fmri.PkgFmri(da.attrs["fmri"])
if da.attrs.get("root-image", "").lower() == "true":
+ # Are firmware (driver) updates needed?
if req_fmri.pkg_name.startswith(
"feature/firmware/"):
- # this is a firmware dependency
fw_ok, reason = \
- self.__firmware.check_firmware(da,
+ self.__firmware.check(da,
req_fmri.pkg_name)
if not fw_ok:
self.__trim((fmri,),
@@ -3105,6 +3108,20 @@
return False
continue
+ # Check that the CPU is supported in the
+ # new root-image
+ if req_fmri.pkg_name.startswith(
+ "feature/cpu"):
+ cpu_ok, reason = \
+ self.__cpu.check(da,
+ req_fmri.pkg_name)
+ if not cpu_ok:
+ self.__trim((fmri,),
+ _TRIM_CPU,
+ reason)
+ return False
+ continue
+
if self.__root_fmris is None:
img = pkg.client.image.Image(
misc.liveroot(),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/tests/cli/t_origin_cpu.py Fri Apr 01 17:41:13 2016 -0700
@@ -0,0 +1,152 @@
+#!/usr/bin/python
+# -*- coding: utf-8
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+
+import testutils
+if __name__ == "__main__":
+ testutils.setup_environment("../../../proto")
+
+import os
+import pkg5unittest
+import sys
+import unittest
+
+import pkg.portable as portable
+
+
+class TestPkgCpuDependencies(pkg5unittest.SingleDepotTestCase):
+ # Only start/stop the depot once (instead of for every test)
+ persistent_setup = True
+ # leverage smf test infrastructure here
+ smf_cmds = {
+ "cpu": """#!/usr/bin/python
+from __future__ import print_function
+import os
+import resource
+import sys
+
+
+def main():
+ installed_version = os.environ.get("PKG_INSTALLED_VERSION", None)
+ if not installed_version:
+ return 0
+ for n in range(1, len(sys.argv)):
+ key, value = sys.argv[n].split("=", 1)
+ if key == "check.include":
+ if installed_version > value is True:
+ print("{0}".format(key), file=sys.stderr)
+ return 1
+ return 0
+ if key == "check.exclude":
+ if value > installed_version is True:
+ print("{0}".format(key), file=sys.stderr)
+ return 1
+ return 0
+ if key == "dump_core":
+ # avoid creating a core file
+ resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
+ os.abort()
+ print("Neither check.include nor check.exclude specified in dependency")
+ return 242
+
+if __name__ == "__main__":
+ # Make all warnings be errors.
+ import warnings
+ warnings.simplefilter('error')
+
+ sys.exit(main())
+"""}
+
+ def setUp(self):
+
+ pkg5unittest.SingleDepotTestCase.setUp(self)
+
+ self.pkg_list = []
+
+ for t in (
+ ("1.0", "cpu", "argo"),
+ ("1.1", "cpu", "babinda"),
+ ("1.2", "cpu", "coolabah"),
+ ("1.3", "cpu", "drongo"),
+ ("2.0", "platform", "dropbear"),
+ ("2.1", "platform", "hoopsnake"),
+ ("2.2", "platform", "oodnadatta"),
+ ("3.0", "iset", "absinthe"),
+ ("3.1", "iset", "bolli"),
+ ("3.4", "iset", "limoncello")
+ ):
+ self.pkg_list += ["""
+ open A@{0},5.11-0
+ add depend type=origin root-image=true fmri=pkg:/feature/cpu check.version-type={1} check.include={2}
+ close
+ open B@{3},5.12-0
+ add depend type=origin root-image=true fmri=pkg:/feature/cpu check.version-type={4} check.exclude={5}
+ close """.format(*(t + t))]
+
+ self.pkg_list += ["""
+ open [email protected],5.11-0
+ add depend type=origin root-image=true fmri=pkg:/feature/cpu
+ close """]
+
+ self.pkg_list += ["""
+ open [email protected],5.12-0
+ add depend type=origin root-image=true fmri=pkg:/feature/cpu dump_core=1
+ close"""]
+
+ self.pkg_list += ["""
+ open [email protected],5.11-0
+ add depend type=origin root-image=true fmri=pkg:/feature/cpu
+ close"""]
+
+ def test_cpu_dependency(self):
+ """test origin cpu dependency
+ cpu test simulator uses alphabetic comparison"""
+
+ if portable.osname != "sunos":
+ raise pkg5unittest.TestSkippedException(
+ "cpu check unsupported on this platform.")
+
+ rurl = self.dc.get_repo_url()
+ plist = self.pkgsend_bulk(rurl, self.pkg_list)
+ self.image_create(rurl)
+ os.environ["PKG_INSTALLED_VERSION"] = "hoopsnake"
+ # trim some of the versions out; note that pkgs w/ cpu
+ # errors/problems are silently ignored.
+ self.pkg("install -v [email protected] [email protected]")
+ self.pkg("list -v")
+ os.environ["PKG_INSTALLED_VERSION"] = "dropbear"
+ self.pkg("install [email protected]", 1)
+ # exercise general error codes
+ self.pkg("install [email protected]", 1)
+ # verify that upreving the cpu lets us install more
+ self.pkg("list")
+ os.environ["PKG_INSTALLED_VERSION"] = "coolabah"
+ self.pkg("update *@latest")
+ self.pkg("list")
+ self.pkg("verify [email protected]", 1)
+ del os.environ["PKG_INSTALLED_VERSION"]
+ self.pkg("list")
+ # this is a trick, there is no v1.6
+ self.pkg("verify [email protected]", 1)
+ # check that we ignore dependencies w/ missing enumerators
+ self.pkg("install [email protected]")
+ self.pkg("list")
--- a/src/tests/cli/t_origin_fw.py Mon Apr 04 16:35:45 2016 +1000
+++ b/src/tests/cli/t_origin_fw.py Fri Apr 01 17:41:13 2016 -0700
@@ -20,8 +20,8 @@
# CDDL HEADER END
#
# Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+from __future__ import print_function
-from __future__ import print_function
import testutils
if __name__ == "__main__":
testutils.setup_environment("../../../proto")
@@ -29,16 +29,16 @@
import os
import pkg5unittest
import unittest
+import sys
+import pkg.portable as portable
-import pkg.portable as portable
class TestPkgFWDependencies(pkg5unittest.SingleDepotTestCase):
# Only start/stop the depot once (instead of for every test)
persistent_setup = True
# leverage smf test infrastructure here
smf_cmds = {
- "testdriver" :
-"""#!/usr/bin/python
+ "fwenum": """#!/usr/bin/python
import os
import resource
import sys
@@ -48,21 +48,20 @@
devs_present = os.environ.get("PKG_NUM_FAKE_DEVICES", "1")
if not installed_version:
return 0
- for arg in sys.argv[1:]:
- if arg.startswith("minimum-version="):
- a = installed_version
- b = arg[len("minimum-version="):]
- c = (a > b) - (a < b)
- if c < 0:
+ for n in range(1, len(sys.argv)):
+ key, value = sys.argv[n].split("=", 1)
+ c = installed_version < value
+ if key == "check.minimum-version" or key == "minimum-version":
+ if c is False:
if int(devs_present) > 240:
devs_present = "240"
return int(devs_present)
return 0
- if arg.startswith("dump_core="):
+ if key == "dump_core":
# avoid creating a core file
resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
os.abort()
- print("attribute minimum-version not specified in dependency")
+ print("attribute check.minimum-version not specified in dependency")
return 241
if __name__ == "__main__":
@@ -84,71 +83,70 @@
("1.1", "elf"),
("1.2", "hobbit"),
("1.3", "wizard")
- ):
- self.pkg_list+= ["""
+ ):
+ self.pkg_list += ["""
open A@{0},5.11-0
- add depend type=origin root-image=true fmri=pkg:/feature/firmware/testdriver minimum-version={1}
+ add depend type=origin root-image=true fmri=pkg:/feature/firmware/fwenum check.minimum-version={1}
close
open B@{2},5.11-0
- add depend type=origin root-image=true fmri=pkg:/feature/firmware/testdriver minimum-version={3}
- close """.format(*(t + t)) ]
+ add depend type=origin root-image=true fmri=pkg:/feature/firmware/fwenum check.minimum-version={3}
+ close """.format(*(t + t))]
- self.pkg_list += ["""
+ self.pkg_list += ["""
open [email protected],5.11-0
- add depend type=origin root-image=true fmri=pkg:/feature/firmware/testdriver
+ add depend type=origin root-image=true fmri=pkg:/feature/firmware/fwenum
close """]
- self.pkg_list += ["""
+ self.pkg_list += ["""
open [email protected],5.11-0
- add depend type=origin root-image=true fmri=pkg:/feature/firmware/testdriver dump_core=1
+ add depend type=origin root-image=true fmri=pkg:/feature/firmware/fwenum dump_core=1
close"""]
- self.pkg_list += ["""
+ self.pkg_list += ["""
open [email protected],5.11-0
add depend type=origin root-image=true fmri=pkg:/feature/firmware/no-such-enumerator
close"""]
def test_fw_dependency(self):
"""test origin firmware dependency"""
- """firmware test simulator uses alphabetic comparison"""
+ """firmware test simulator uses alphabetic comparison"""
- if portable.osname != "sunos":
- raise pkg5unittest.TestSkippedException(
- "Firmware check unsupported on this platform.")
+ if portable.osname != "sunos":
+ raise pkg5unittest.TestSkippedException(
+ "Firmware check unsupported on this platform.")
rurl = self.dc.get_repo_url()
plist = self.pkgsend_bulk(rurl, self.pkg_list)
self.image_create(rurl)
os.environ["PKG_INSTALLED_VERSION"] = "elf"
- # trim some of the versions out; note that pkgs w/ firmware
- # errors/problems are silently ignored.
+ # trim some of the versions out; note that pkgs w/ firmware
+ # errors/problems are silently ignored.
self.pkg("install A B")
- self.pkg("list")
- self.pkg("verify [email protected]")
- # test verify by changing device version
- os.environ["PKG_INSTALLED_VERSION"] = "dwarf"
- self.pkg("verify [email protected]", 1)
+ self.pkg("list -v [email protected] [email protected]")
+ # test verify by changing device version
+ os.environ["PKG_INSTALLED_VERSION"] = "dwarf"
+ self.pkg("verify [email protected]", 1)
os.environ["PKG_INSTALLED_VERSION"] = "elf"
- # exercise large number of devices code
+ # exercise large number of devices code
os.environ["PKG_NUM_FAKE_DEVICES"] = "500"
- self.pkg("install [email protected]", 1)
- # exercise general error codes
- self.pkg("install [email protected]", 1)
- self.pkg("install [email protected]", 1)
- # verify that upreving the firmware lets us install more
+ self.pkg("install [email protected]", 4)
+ # exercise general error codes
+ self.pkg("install [email protected]", 1)
+ self.pkg("install [email protected]", 1)
+ # verify that upreving the firmware lets us install more
os.environ["PKG_INSTALLED_VERSION"] = "hobbit"
- self.pkg("update")
- self.pkg("verify [email protected]")
- # simulate removing device
- del os.environ["PKG_INSTALLED_VERSION"]
- self.pkg("update")
- self.pkg("list")
- self.pkg("verify [email protected]")
- # ok since we never drop core
- # here as device
- # doesn't exist.
+ del os.environ["PKG_NUM_FAKE_DEVICES"]
+ self.pkg("update -nv", 4)
+ self.pkg("verify [email protected]", 1)
+ # simulate removing device
+ del os.environ["PKG_INSTALLED_VERSION"]
+ self.pkg("list -v")
+ self.pkg("update")
+ self.pkg("list -v")
+ self.pkg("verify [email protected]")
+ # ok since we never drop core here since device
+ # doesn't exist.
- # check that we ignore dependencies w/ missing enumerators for now
- self.pkg("install [email protected]")
-
+ # check that we ignore dependencies w/ missing enumerators
+ self.pkg("install [email protected]")