manifest.py revision 3312
39N/A# The contents of this file are subject to the terms of the 39N/A# Common Development and Distribution License (the "License"). 39N/A# You may not use this file except in compliance with the License. 39N/A# See the License for the specific language governing permissions 39N/A# and limitations under the License. 39N/A# When distributing Covered Code, include this CDDL HEADER in each 39N/A# If applicable, add the following below this CDDL HEADER, with the 39N/A# fields enclosed by brackets "[]" replaced with your own identifying 39N/A# information: Portions Copyright [yyyy] [name of copyright owner] 2608N/A# Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. 39N/A """Private helper function that returns a compiled version of a 39N/A dictionary of fnmatch patterns.""" 39N/A """Private helper function: given an action, return True if any of its 39N/A attributes' values matches the pattern for the same attribute in the 39N/A attr_match dictionary, and False otherwise. Note that the patterns must 39N/A be pre-comiled using re.compile() or _compile_fnpats.""" 315N/A """Returns the serialized state of this object in a format 39N/A that that can be easily stored using JSON, pickle, etc.""" 1352N/A """Allocate a new object using previously serialized state 429N/A obtained via getstate().""" 1352N/A # decode serialized state into python objects 72N/A """A Manifest is the representation of the actions composing a specific 72N/A package version on both the client and the repository. Both purposes 59N/A utilize the same storage format. 1045N/A The serialized structure of a manifest is an unordered list of actions. 1045N/A The special action, "set", represents a package attribute. 1713N/A The reserved attribute, "fmri", represents the package and version 1045N/A described by this manifest. It is available as a string via the 1045N/A attributes dictionary, and as an FMRI object from the fmri member. 2084N/A The list of manifest-wide reserved attributes is 2084N/A base_directory Default base directory, for non-user images. 2084N/A isa Package is intended for a list of ISAs. 2084N/A platform Package is intended for a list of platforms. 2084N/A relocatable Suitable for User Image. 2084N/A All non-prefixed attributes are reserved to the framework. Third 838N/A parties may prefix their attributes with a reversed domain name, domain 72N/A name, or stock symbol. An example might be 72N/A as an indicator that a specific package version is supported by the 59N/A vendor, example.com. 72N/A manifest.null is provided as the null manifest. Differences against the 59N/A null manifest result in the complete set of attributes and actions of 72N/A the non-null manifest, meaning that all operations can be viewed as 72N/A tranitions between the manifest being installed and the manifest already 72N/A present in the image (which may be the null manifest). 2284N/A """A generator function that returns the unsorted manifest 2240N/A contents as lines of text.""" 2240N/A """Return three lists of action pairs representing origin and 2240N/A destination actions. The first list contains the pairs 2240N/A representing additions, the second list contains the pairs 2240N/A representing updates, and the third list contains the pairs 2240N/A representing removals. All three lists are in the order in 2240N/A which they should be executed.""" 2240N/A # XXX Do we need to find some way to assert that the keys are 2284N/A # No origin was provided, so nothing has been changed or 2284N/A # removed; only added. In addition, this doesn't need 2284N/A # to be sorted since the caller likely already does 838N/A """handle key values that may be lists""" 838N/A # Transform list of actions into a dictionary keyed by 926N/A # action key attribute, key attribute and mediator, or 838N/A # id if there is no key attribute. 838N/A # XXX Do changed actions need to be sorted at all? This is 203N/A # likely to be the largest list, so we might save significant 48N/A # time by not sorting. Should we sort above? Insert into a 181N/A # singlesort = lambda x: x[0] or x[1] 2339N/A """Like the unix utility comm, except that this function 2453N/A takes an arbitrary number of manifests and compares them, 2453N/A returning a tuple consisting of each manifest's actions 2453N/A that are not the same for all manifests, followed by a 2453N/A list of actions that are the same in each manifest.""" 2339N/A # Must specify at least one manifest. 2339N/A # construct list of dictionaries of actions in each 2339N/A # manifest, indexed by unique key and variant combination 2453N/A # The unique key for each action is based on its 2453N/A # type, key attribute, and unique variants set 2339N/A for v
in (
"mediator-version",
2453N/A "mediator-implementation"):
2453N/A # If there is no key attribute for the 2453N/A # action, then fallback to the object 2453N/A # id for the action as its identifier. 2453N/A # catch duplicate actions here... 2453N/A # construct list of key sets in each dict 2453N/A # determine which common_keys have common actions 2339N/A """Where difference() returns three lists, combined_difference() 2339N/A returns a single list of the concatenation of the three.""" 2339N/A """Output expects that self is newer than other. Use of sets 2453N/A requires that we convert the action objects into some marshalled 2453N/A form, otherwise set member identities are derived from the 2339N/A object pointers, rather than the contents.""" 2453N/A """Generate contents of dircache file containing all dirctories 2453N/A referenced explicitly or implicitly from self.actions. Include 2453N/A variants as values; collapse variants where possible.""" 2453N/A """Generate contents of mediatorcache file containing all 2540N/A mediators referenced explicitly or implicitly from self.actions. 2453N/A Include variants as values; collapse variants where possible.""" 2453N/A a =
"set name=pkg.mediator " \
838N/A """Generate set action supplemental data containing all facets 838N/A and variants from self.actions and size information. Each 838N/A returned line must be newline-terminated.""" 838N/A # Package already has these attributes. 2608N/A # List of possible variants and possible values for them. 838N/A # Seed with declared set of variants as actions may be common to 838N/A # both and so will not be tagged with variant. 2453N/A # List of possible facets and under what variant combinations 2453N/A # Unique (facet, value) (variant, value) combinations. 111N/A # Facet applicable to this particular variant 113N/A # This *must* be sorted to ensure reproducible set 113N/A # action generation for sizes and to ensure each 113N/A # combination is actually unique. 2073N/A # Unnecessary if we can guarantee all variants will be 2073N/A # declared at package level. Omit the "variant." prefix 2073N/A # from attribute values since that's implicit and can be 2073N/A # added back when the action is parsed. 1432N/A # Emit a set action for every variant used with possible values 1432N/A # if one does not already exist. 1432N/A # merge_facets needs the variant values sorted and this 1432N/A # is desirable when generating the variant attr anyway. 1500N/A # Get unvarianted facet set. 1970N/A # For each variant combination, remove unvarianted 1970N/A # facets since they are common to all variants. 1970N/A # No facets unique to this combo; 2073N/A # If all possible variant combinations supported by the 2073N/A # package have at least one facet, then the intersection 1713N/A # of facets for all variants can be merged with the 2073N/A # Determine unique set of variant combinations 1713N/A # seen for faceted actions. 2073N/A # For each unique variant combination, determine 2073N/A # if the cartesian product of all variant values 1713N/A # supported by the package for the combination 1713N/A # has been seen. In other words, if the 2073N/A # combination is ((variant.arch,)) and the 2073N/A # package supports (i386, sparc), then both 2073N/A # (variant.arch, i386) and (variant.arch, sparc) 1500N/A # must exist. This code assumes variant values 1500N/A # for each variant are already sorted. 1500N/A # If any combination the package 1500N/A # supports has not been seen for 1500N/A # one or more facets, then some 2073N/A # facets are unique to one or 1890N/A # Merge the facets common to all variants if safe; 1500N/A # if we always merged them, then facets only 2073N/A # used by a single variant (think i386-only or 2073N/A # sparc-only content) would be seen unvarianted 926N/A # At least one facet is shared between 1500N/A # all variant combinations; move the 2026N/A # common ones to the unvarianted set. 2608N/A # Remove facets common to all combos. 2026N/A # Omit the "facet." prefix from attribute values since 2026N/A # that's implicit and can be added back when the action 1500N/A # If we don't do this, action stringify will 1500N/A # emit this as "set name=pkg.facet" which is 123N/A # then transformed to "set name=name 1500N/A # value=pkg.facet". Not what we wanted, but is 1500N/A # expected for historical reasons. 1500N/A # Always emit an action enumerating the list of facets 1500N/A # common to all variants, even if there aren't any. 1500N/A # That way if there are also no variant-specific facets, 1500N/A # package operations will know that no facets are used 1500N/A # by the package instead of having to scan the whole 1500N/A # Now emit a pkg.facet action for each variant 1500N/A # combination containing the list of facets unique to 39N/A # A unique key for each combination is needed, 1500N/A # and using a hash obfuscates that interface 1500N/A # while giving us a reliable way to generate 1500N/A # a reproducible, unique identifier. The key 1500N/A # string below looks like this before hashing: 1500N/A # variant.archi386variant.debug.osnetTrue... 1500N/A # Omit the "facet." prefix from attribute values 1500N/A # since that's implicit and can be added back 1500N/A # when the action is parsed. 1500N/A # Tag action with variants. 2238N/A # Emit pkg.[c]size attribute for [compressed] size of package 956N/A # running total so a single [c]size action can 1007N/A # Only emit if > 0; actions may be 1007N/A # A unique key for each combination is needed, 1007N/A # and using a hash obfuscates that interface 1007N/A # while giving us a reliable way to generate 1007N/A # a reproducible, unique identifier. The key 1007N/A # string below looks like this before hashing: 1007N/A # facet.docTruevariant.archi386... 1007N/A # The sizes are abbreviated in the name of byte 941N/A """create dictionary of all actions referenced explicitly or 941N/A implicitly from self.actions... include variants as values; 941N/A collapse variants where possible""" 941N/A # build a dictionary containing all actions tagged w/ 941N/A # remove any tags if any entries are always delivered (NULL) 941N/A # could collapse refs where all variants are present 941N/A # (the current logic only collapses them if at least 941N/A # one reference is delivered without a facet or 1234N/A """ return a list of directories implicitly or 1007N/A explicitly referenced by this object""" 1007N/A # generate actions that contain directories 1007N/A """A generator function that returns the supported facet 1007N/A attributes (strings) for this package based on the specified (or 1007N/A current) excludes that also match at least one of the patterns 1007N/A provided. Facets must be true or false so a list of possible 941N/A facet values is not returned.""" 1890N/A # No excludes? Then use the pre-determined set of 1352N/A # If different excludes were specified, then look for pkg.facet 1352N/A # actions containing the list of facets. 1352N/A # Either a pkg.facet.common action or a 2073N/A # pkg.facet.X variant-specific action. 1636N/A # possible a given facet may be 2073N/A # valid for more than one unique 1636N/A # variant combination that's 1636N/A # allowed by current excludes. 2073N/A # Fallback to sifting actions to yield possible. 1386N/A """A generator function that yields a list of tuples of the form 315N/A (variant, [values]). Where 'variant' is the variant attribute 315N/A name (e.g. 'variant.arch') and '[values]' is a list of the 315N/A variant values supported by this package. Variants returned are 315N/A those allowed by the specified (or current) excludes that also 315N/A match at least one of the patterns provided.""" 2073N/A # No excludes? Then use the pre-determined set of 926N/A # If different excludes were specified, then look for 926N/A # pkg.variant action containing the list of variants. 205N/A # Ensure variant entries exist (debug 257N/A # variants may not) via defaultdict. 1461N/A # Fallback to sifting actions to get possible. 1461N/A """A generator function that yields tuples of the form (mediator, 1461N/A mediations) expressing the set of possible mediations for this 1044N/A package, where 'mediations' is a set() of possible mediations for 1044N/A the mediator. Each mediation is a tuple of the form (priority, 1044N/A # generate actions that contain mediators 1461N/A # Consider this mediation unavailable 296N/A # if it can't be parsed for whatever 2073N/A """Generate actions in manifest through ordered callable list""" 2608N/A # These conditions are split by performance. 2144N/A """Generate actions in the manifest of type "type" 2144N/A through ordered callable list""" 956N/A # These conditions are split by performance. 967N/A """Generate actions in the manifest of types "atypes" 2631N/A through ordered callable list.""" 956N/A """Generate the value of the key attribute for each action 956N/A of type "type" in the manifest.""" 2631N/A """Find actions in the manifest which are duplicates (i.e., 956N/A represent the same object) but which are not identical (i.e., 2073N/A have all the same attributes).""" 956N/A """Return a key on which actions can be sorted.""" 956N/A """Parse manifest content, stripping line-continuation 956N/A characters from the input as it is read; this results in actions 956N/A with values across multiple lines being passed to the 956N/A action parsing code whitespace-separated instead. 967N/A set name=pkg.description value="foo " \ 1672N/A ...will each be passed to action parsing as: 956N/A set name=pkg.summary value="foo" 956N/A set name=pkg.description value="foo " "bar baz" 1386N/A # Get an iterable for the string. 956N/A if not l
or l[
0] ==
"#":
# ignore blank lines & comments 2453N/A # Accumulate errors and continue so that as 2453N/A # much of the action data as possible can be 2453N/A """Populate the manifest with actions. 1352N/A 'content' is an optional value containing either the text 2073N/A representation of the manifest or an iterable of 2073N/A 'excludes' is optional. If provided it must be a length two 2035N/A list with the variants to be excluded as the first element and 2035N/A the facets to be excluded as the second element. 2035N/A 'pathname' is an optional filename containing the location of 2035N/A 'signatures' is an optional boolean value that indicates whether 2073N/A a manifest signature should be generated. This is only possible 2035N/A when 'content' is a string or 'pathname' is provided. 1507N/A # sdict and odict in difference() above, and have that be our 2453N/A # main datastore, rather than the simple list we have now. If 956N/A # we do that here, we can even assert that the "same" action 956N/A # can't be in a manifest twice. (The problem of having the same 956N/A # action more than once in packages that can be installed 956N/A # together has to be solved somewhere else, though.) 2613N/A # Generate manifest signature based upon 2613N/A # input content, but only if signatures 2613N/A # were requested. In order to interoperate with 2613N/A # older clients, we must use sha-1 here. 2453N/A # Make sure that either no excludes were provided or that both 2453N/A # variants and facet excludes were or that variant, facet and 956N/A """Remove any actions from the manifest which should be 1507N/A """Performs any needed transformations on the action then adds 956N/A The "action" parameter is the action object that should be 2205N/A The "excludes" parameter is the variants to exclude from the 956N/A # XXX handle legacy transition issues; not needed once support 956N/A # for upgrading images from older releases (< build 151) has 2613N/A # Translate old action to new. 956N/A # add any set actions to attributes 2453N/A """Fill attribute array w/ set action contents.""" 2453N/A # To reduce manifest bloat, size and csize 956N/A # are set on a single action so need splitting 956N/A # into separate attributes. 956N/A # ignore broken set actions 956N/A # Ensure facet and variant attributes are always lists. 2054N/A # Possible facets list is spread over multiple actions. 956N/A # Prevent duplicates; it's possible a 956N/A # given facet may be valid for more than 956N/A # one unique variant combination that's 956N/A # allowed by current excludes. 956N/A # Ancient manifest compatibility. 956N/A """Produces the search dictionary for a specific manifest. 956N/A A dictionary is constructed which maps a tuple of token, 956N/A action type, key, and the value that matched the token to 956N/A the byte offset into the manifest file. file_path is the 1352N/A path to the manifest file. excludes is the variants which 1352N/A should be allowed in this image. return_line is a debugging 956N/A flag which makes the function map the information to the 956N/A string of the line, rather than the byte offset to allow 964N/A """Translates what actions.generate_indices produces 2073N/A into a dictionary mapping token, action_name, key, and 964N/A the value that should be displayed for matching that 964N/A token to byte offsets into the manifest file. 1045N/A The "lst" parameter is the data to be converted. 1045N/A The "cp" parameter is the byte offset into the file 1045N/A for the action which produced lst.""" """This method takes a string representing the on-disk manifest content, and returns a hash value.""" # This must be an SHA-1 hash in order to interoperate with # Byte stream expected, so pass encoded. """Verifies whether the signatures for the contents of the manifest match the specified signature data. Raises the 'BadManifestSignatures' exception on failure.""" """Store the manifest contents to disk.""" # We specifically avoid sorting manifests before writing # them to disk-- there's really no point in doing so, since # we'll sort actions globally during packaging operations. """Return a dictionary mapping variant tags to their values.""" """Returns the boolean of the value of the attribute 'key'.""" raise ValueError(_(
"Attribute value '{0}' not 'true' or " """Returns an integer tuple of the form (size, csize), where 'size' represents the total uncompressed size, in bytes, of the Manifest's data payload, and 'csize' represents the compressed 'excludes' is a list of a list of variants and facets which should be allowed when calculating the total.""" if (
"pkg.size" in attrs and "pkg.csize" in attrs)
and \
# If specified excludes match loaded excludes, then use # cached attributes; this is safe as manifest attributes # are reset or updated every time exclude_content, # set_content, or add_action is called. # Cache for future calls. # Facet filtering should never be applied when excluding # actions; only variant filtering. This is ugly, but # allow you to be selective and various bits in # pkg.manifest assume you always filter on both so we # have to fake up a filter for facets. # Excludes list must always have zero or 2+ items; so # append any variants and facets to manifest dict # While variants are package level (you # can't install a package without # setting the variant first), facets # from the current action should only be # included if the action is not # Lists can't be set elements. _(
"{forv} '{v}' specified multiple times").
format(
"""Return the value for the package attribute 'key'.""" """Set the value for the package attribute 'key' to 'value'.""" """This class serves as a wrapper for the Manifest class for callers that need efficient access to package data on a per-action type basis. It achieves this by partitioning the manifest into multiple files (one per action type) and then storing an on-disk cache of the directories explictly and implicitly referenced by the manifest each tagged with """Raises KeyError exception if factored manifest is not present and contents are None; delays reading of manifest until required if cache file is present. 'fmri' is a PkgFmri object representing the identity of the 'cache_root' is the pathname of the directory where the manifest and cache files should be stored or loaded from. 'contents' is an optional string to use as the contents of the manifest if a cached copy does not already exist. 'excludes' is optional. If provided it must be a length two list with the variants to be excluded as the first element and the facets to be exclduded as the second element. 'pathname' is an optional string containing the pathname of a manifest. If not provided, it is assumed that the manifest is stored in a file named 'manifest' in the directory indicated by 'cache_root'. If provided, and contents is also provided, then 'contents' will be stored in 'pathname' if it does not already # Make sure that either no excludes were provided or 2+ excludes # Do we have a cached copy? # we have no cached copy; save one # don't specify excludes so on-disk copy has # we have a cached copy of the manifest # have we computed the dircache? """Load all manifest contents from on-disk copy of manifest""" """Unload manifest; used to reduce peak memory comsumption when downloading new manifests""" """Finish loading.... this part of initialization is common to multiple code paths""" """ store the current action set; also create per-type caches. Return True if data was saved, False if not""" # this allows us to try to cache new manifests # when non-root w/o failures. """ create manifest.<typename> files to accelerate partial parsing of manifests. Separate from __storeback code to allow upgrade to reuse existing on disk manifests""" # Ensure target cache directory and intermediates exist. # create per-action type cache; use rename to avoid corrupt # files if ^C'd in the middle. All action types are considered # so that empty cache files are created if no action of that # type exists for the package (avoids full manifest loads # Add supplemental action data; yes this # does mean the cache is not the same as # retrieved manifest, but that's ok. # Signature verification is done using """Remove all manifest cache files found in the given directory (excluding the manifest itself) and the cache_root if it is # Ensure cache dir is removed if the last cache file is # removed; we don't care if it fails. # Only raise error if failure wasn't due to # cache directory not existing. """Private helper function for loading arbitrary cached manifest # we have cached copy on disk; use it # Cache file is malformed; hopefully due to bugs # that have been resolved (as opposed to actual # corruption). Assume we should just ignore the # cache and load action data. # Ignore errors encountered during cache # dump for this specific case. """ return a list of directories implicitly or explicitly referenced by this object """ generate actions of the specified type; use already in-memory stuff if already loaded, otherwise use per-action types files""" if self.
loaded:
#if already loaded, use in-memory cached version # invoke subclass method to generate action by action # This checks if we've already written out the factored # manifest files. If so, we'll use it, and if not, then # we'll load the full manifest. # invoke subclass method to generate action by action # No such action in the manifest; must be done *after* # asserting excludes are correct to avoid hiding # Assume a cached copy exists; if not, tag the action type to # avoid pointless I/O later. # These conditions are split by return # no such action in this manifest """A generator function that returns the supported facet attributes (strings) for this package based on the specified (or current) excludes that also match at least one of the patterns provided. Facets must be true or false so a list of possible facet values is not returned.""" """A generator function that yields a list of tuples of the form (variant, [values]). Where 'variant' is the variant attribute name (e.g. 'variant.arch') and '[values]' is a list of the variant values supported by this package. Variants returned are those allowed by the specified (or current) excludes that also match at least one of the patterns provided.""" """A generator function that yields set actions expressing the set of possible mediations for this package. """Load attributes dictionary from cached set actions; this speeds up pkg info a lot""" """Returns an integer tuple of the form (size, csize), where 'size' represents the total uncompressed size, in bytes, of the Manifest's data payload, and 'csize' represents the compressed 'excludes' is a list of a list of variants and facets which should be allowed when calculating the total.""" """No assignments to factored manifests allowed.""" assert "FactoredManifests are not dicts" """Store the manifest contents to disk.""" """The absolute pathname of the file containing the manifest.""" """Special class for pkgplan's need for a empty manifest; the regular null manifest doesn't support get_directories and making the factored manifest code handle this case is """Return three lists of action pairs representing origin and destination actions. The first list contains the pairs representing additions, the second list contains the pairs representing updates, and the third list contains the pairs representing removals. All three lists are in the order in which they should be executed.""" # The difference for this case is simply everything in the # origin has been removed. This is an optimization for # This method is overridden so that self.excludes is never set # on the singleton NullFactoredManifest. """Simple Exception class to handle manifest specific errors"""