def evaluate(self, old_excludes=EmptyI, new_excludes=EmptyI): """Determine the actions required to transition the package.""" # if origin unset, determine if we're dealing with an previously # installed version or if we're dealing with the null package # # XXX Perhaps make the pkgplan creator make this explicit, so we # don't have to check? f = None if not self.origin_fmri: f = self.image.older_version_installed(self.destination_fmri) if f: self.origin_fmri = f self.__origin_mfst = \ self.image.get_manifest(f) # Assume that origin actions are unique, but make sure that # destination ones are. ddups = self.__destination_mfst.duplicates(new_excludes) if ddups: raise RuntimeError, ["Duplicate actions", ddups] self.actions = self.__destination_mfst.difference( self.__origin_mfst, old_excludes, new_excludes) # figure out how many implicit directories disappear in this # transition and add directory remove actions. These won't # do anything unless no pkgs reference that directory in # new state.... # Retrieving origin_dirs first and then checking it for any # entries allows avoiding an unnecessary expanddirs for the # destination manifest when it isn't needed. origin_dirs = expanddirs( self.__origin_mfst.get_directories(old_excludes)) if origin_dirs: absent_dirs = origin_dirs - \ expanddirs(self.__destination_mfst.get_directories( new_excludes)) for a in absent_dirs: self.actions[2].append( [directory.DirectoryAction(path=a), None]) # Stash information needed by legacy actions. self.__legacy_info["description"] = \ self.__destination_mfst.get("pkg.summary", self.__destination_mfst.get("description", "none provided")) # Add any repair actions to the update list self.actions[1].extend(self.__repair_actions) # # We cross a point of no return here, and throw away the origin # and destination manifests; we also delete them from the # image cache. self.__origin_mfst = None self.__destination_mfst = None
def evaluate(self, old_excludes=EmptyI, new_excludes=EmptyI): """Determine the actions required to transition the package.""" # Assume that origin actions are unique, but make sure that # destination ones are. ddups = self.__destination_mfst.duplicates(new_excludes) if ddups: raise RuntimeError(["Duplicate actions", ddups]) self.actions = self.__destination_mfst.difference( self.__origin_mfst, old_excludes, new_excludes) # figure out how many implicit directories disappear in this # transition and add directory remove actions. These won't # do anything unless no pkgs reference that directory in # new state.... # Retrieving origin_dirs first and then checking it for any # entries allows avoiding an unnecessary expanddirs for the # destination manifest when it isn't needed. origin_dirs = expanddirs( self.__origin_mfst.get_directories(old_excludes)) # No longer needed. self.__origin_mfst = None if origin_dirs: absent_dirs = origin_dirs - \ expanddirs(self.__destination_mfst.get_directories( new_excludes)) for a in absent_dirs: self.actions.removed.append( [directory.DirectoryAction(path=a), None]) # Stash information needed by legacy actions. self.pkg_summary = \ self.__destination_mfst.get("pkg.summary", self.__destination_mfst.get("description", "none provided")) # No longer needed. self.__destination_mfst = None # Add any repair actions to the update list self.actions.changed.extend(self.__repair_actions) for src, dest in itertools.chain(self.gen_update_actions(), self.gen_install_actions()): if dest.name == "license": self.__add_license(src, dest)
def evaluate(self, old_excludes=EmptyI, new_excludes=EmptyI, can_exclude=False): """Determine the actions required to transition the package.""" # If new actions are being installed, check the destination # manifest for signatures. if self.destination_fmri is not None: try: dest_pub = self.image.get_publisher( prefix=self.destination_fmri.publisher) except apx.UnknownPublisher: # Since user removed publisher, assume this is # the same as if they had set signature-policy # ignore for the publisher. sig_pol = None else: sig_pol = self.image.signature_policy.combine( dest_pub.signature_policy) if self.destination_fmri in self._autofix_pkgs: # Repaired packages use a manifest synthesized # from the installed one; so retrieve the # installed one for our signature checks. sigman = self.image.get_manifest(self.destination_fmri, ignore_excludes=True) else: sigman = self.__destination_mfst sigs = list( sigman.gen_actions_by_type("signature", excludes=new_excludes)) if sig_pol and (sigs or sig_pol.name != "ignore"): # Only perform signature verification logic if # there are signatures or if signature-policy # is not 'ignore'. try: sig_pol.process_signatures( sigs, sigman.gen_actions(), dest_pub, self.image.trust_anchors, self.image.cfg.get_policy( "check-certificate-revocation")) except apx.SigningException as e: e.pfmri = self.destination_fmri if isinstance(e, apx.BrokenChain): e.ext_exs.extend(self.image.bad_trust_anchors) raise if can_exclude: if self.__destination_mfst is not None: self.__destination_mfst.exclude_content(new_excludes) if self.__origin_mfst is not None and \ self.__destination_mfst != self.__origin_mfst: self.__origin_mfst.exclude_content(old_excludes) old_excludes = EmptyI new_excludes = EmptyI self.actions = self.__destination_mfst.difference(self.__origin_mfst, old_excludes, new_excludes, pkgplan=self) # figure out how many implicit directories disappear in this # transition and add directory remove actions. These won't # do anything unless no pkgs reference that directory in # new state.... # Retrieving origin_dirs first and then checking it for any # entries allows avoiding an unnecessary expanddirs for the # destination manifest when it isn't needed. origin_dirs = expanddirs( self.__origin_mfst.get_directories(old_excludes)) # Manifest.get_directories() returns implicit directories, which # means that this computation ends up re-adding all the explicit # directories getting removed to the removed list. This is # ugly, but safe. if origin_dirs: absent_dirs = origin_dirs - \ expanddirs(self.__destination_mfst.get_directories( new_excludes)) for a in absent_dirs: self.actions.removed.append( (directory.DirectoryAction(path=a, implicit="True"), None)) # Stash information needed by legacy actions. self.pkg_summary = \ self.__destination_mfst.get("pkg.summary", self.__destination_mfst.get("description", "none provided")) # Add any install repair actions to the update list self.actions.changed.extend( self.__repair_actions.get("install", EmptyI)) self.actions.removed.extend(self.__repair_actions.get( "remove", EmptyI)) # No longer needed. self.__repair_actions = {} for src, dest in itertools.chain(self.gen_update_actions(), self.gen_install_actions()): if dest.name == "license": self.__add_license(src, dest) if not src: # Initial installs require acceptance. continue src_ma = src.attrs.get("must-accept", False) dest_ma = dest.attrs.get("must-accept", False) if (dest_ma and src_ma) and \ src.hash == dest.hash: # If src action required acceptance, # then license was already accepted # before, and if the hashes are the # same for the license payload, then # it doesn't need to be accepted again. self.set_license_status(dest.attrs["license"], accepted=True) # Keep a cache of dir actions with salvage-from attrs. # Since directories are installed in top-down order, # we need this list to make sure we salvage contents # as accurately as possible. For example, where: # # /var/user gets salvaged to /var/.migrate/user # and # /var/user/myuser/.ssh to /var/.migrate/user/myuser/.ssh # # We must ensure that we don't try to salvage # var/user/myuser/.ssh when installing # /var/.migrate/user, # but instead wait till /var/.migrate/user/myuser/.ssh # is being installed, otherwise that content will # the salvaged to the wrong place. if (dest.name == "dir" and "salvage-from" in dest.attrs): for p in dest.attrlist("salvage-from"): self.__salvage_actions[p] = dest