plandesc.py revision 2828
2690N/A#!/usr/bin/python
2690N/A#
2690N/A# CDDL HEADER START
2690N/A#
2690N/A# The contents of this file are subject to the terms of the
2690N/A# Common Development and Distribution License (the "License").
2690N/A# You may not use this file except in compliance with the License.
2690N/A#
2690N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2690N/A# or http://www.opensolaris.org/os/licensing.
2690N/A# See the License for the specific language governing permissions
2690N/A# and limitations under the License.
2690N/A#
2690N/A# When distributing Covered Code, include this CDDL HEADER in each
2690N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2690N/A# If applicable, add the following below this CDDL HEADER, with the
2690N/A# fields enclosed by brackets "[]" replaced with your own identifying
2690N/A# information: Portions Copyright [yyyy] [name of copyright owner]
2690N/A#
2690N/A# CDDL HEADER END
2690N/A#
2690N/A
2690N/A#
2690N/A# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
2690N/A#
2690N/A
2690N/A"""
2690N/APlanDescription and _ActionPlan classes
2690N/A
2690N/AThese classes are part of the public API, and any changes here may require
2690N/Abumping CURRENT_API_VERSION in pkg.api
2690N/A
2690N/AThe PlanDescription class is a public interface which contains all the data
2690N/Aassociated with an image-modifying operation.
2690N/A
2690N/AThe _ActionPlan class is a private interface used to keep track of actions
2690N/Amodified within an image during an image-modifying operation.
2690N/A"""
2690N/A
2690N/Aimport collections
2690N/Aimport itertools
2690N/Aimport operator
2690N/Aimport simplejson as json
2690N/A
2690N/Aimport pkg.actions
2690N/Aimport pkg.client.actuator
2690N/Aimport pkg.client.api_errors as apx
2690N/Aimport pkg.client.linkedimage as li
2690N/Aimport pkg.client.pkgplan
2690N/Aimport pkg.client.pkgplan
2690N/Aimport pkg.facet
2690N/Aimport pkg.fmri
2690N/Aimport pkg.misc
2690N/Aimport pkg.version
2690N/A
2690N/Afrom pkg.api_common import (PackageInfo, LicenseInfo)
2690N/A
2690N/AUNEVALUATED = 0 # nothing done yet
2690N/AEVALUATED_PKGS = 1 # established fmri changes
2690N/AMERGED_OK = 2 # created single merged plan
2690N/AEVALUATED_OK = 3 # ready to execute
2690N/APREEXECUTED_OK = 4 # finished w/ preexecute
2690N/APREEXECUTED_ERROR = 5 # whoops
2690N/AEXECUTED_OK = 6 # finished execution
2690N/AEXECUTED_ERROR = 7 # failed
2690N/A
2690N/Aclass _ActionPlan(collections.namedtuple("_ActionPlan", "p src dst")):
2690N/A """A named tuple used to keep track of all the actions that will be
2690N/A executed during an image-modifying procecure."""
2828N/A # Class has no __init__ method; pylint: disable=W0232
2828N/A # Use __slots__ on an old style class; pylint: disable=E1001
2690N/A
2690N/A __slots__ = []
2690N/A
2690N/A __state__desc = tuple([
2690N/A pkg.client.pkgplan.PkgPlan,
2690N/A pkg.actions.generic.NSG,
2690N/A pkg.actions.generic.NSG,
2690N/A ])
2690N/A
2690N/A @staticmethod
2690N/A def getstate(obj, je_state=None):
2690N/A """Returns the serialized state of this object in a format
2690N/A that that can be easily stored using JSON, pickle, etc."""
2690N/A return pkg.misc.json_encode(_ActionPlan.__name__, tuple(obj),
2690N/A _ActionPlan.__state__desc, je_state=je_state)
2690N/A
2690N/A @staticmethod
2690N/A def fromstate(state, jd_state=None):
2690N/A """Allocate a new object using previously serialized state
2690N/A obtained via getstate()."""
2828N/A # Access to protected member; pylint: disable=W0212
2690N/A
2690N/A # get the name of the object we're dealing with
2690N/A name = _ActionPlan.__name__
2690N/A
2690N/A # decode serialized state into python objects
2690N/A state = pkg.misc.json_decode(name, state,
2690N/A _ActionPlan.__state__desc, jd_state=jd_state)
2690N/A
2690N/A return _ActionPlan(*state)
2690N/A
2690N/A
2690N/Aclass PlanDescription(object):
2690N/A """A class which describes the changes the plan will make."""
2690N/A
2690N/A __state__desc = {
2690N/A "_actuators": pkg.client.actuator.Actuator,
2690N/A "_cfg_mediators": {
2690N/A str: {
2690N/A "version": pkg.version.Version,
2690N/A "implementation-version": pkg.version.Version,
2690N/A }
2690N/A },
2690N/A "_changed_facets": pkg.facet.Facets,
2690N/A "_fmri_changes": [ ( pkg.fmri.PkgFmri, pkg.fmri.PkgFmri ) ],
2690N/A "_new_avoid_obs": ( set(), set() ),
2690N/A "_new_facets": pkg.facet.Facets,
2690N/A "_new_mediators": collections.defaultdict(set, {
2690N/A str: {
2690N/A "version": pkg.version.Version,
2690N/A "implementation-version": pkg.version.Version,
2690N/A }
2690N/A }),
2690N/A "_removed_facets": set(),
2690N/A "_rm_aliases": { str: set() },
2690N/A "added_groups": { str: pkg.fmri.PkgFmri },
2690N/A "added_users": { str: pkg.fmri.PkgFmri },
2690N/A "children_ignored": [ li.LinkedImageName ],
2690N/A "children_nop": [ li.LinkedImageName ],
2690N/A "children_planned": [ li.LinkedImageName ],
2690N/A "install_actions": [ _ActionPlan ],
2690N/A "li_ppkgs": frozenset([ pkg.fmri.PkgFmri ]),
2690N/A "li_props": { li.PROP_NAME: li.LinkedImageName },
2690N/A "pkg_plans": [ pkg.client.pkgplan.PkgPlan ],
2708N/A "release_notes": (bool, []),
2690N/A "removal_actions": [ _ActionPlan ],
2690N/A "removed_groups": { str: pkg.fmri.PkgFmri },
2690N/A "removed_users": { str: pkg.fmri.PkgFmri },
2690N/A "update_actions": [ _ActionPlan ],
2690N/A }
2690N/A
2690N/A __state__commonize = frozenset([
2690N/A pkg.actions.generic.NSG,
2690N/A pkg.client.pkgplan.PkgPlan,
2690N/A pkg.fmri.PkgFmri,
2690N/A ])
2690N/A
2690N/A def __init__(self, op=None):
2690N/A self.state = UNEVALUATED
2690N/A self._op = op
2690N/A
2690N/A #
2690N/A # Properties set when state >= EVALUATED_PKGS
2690N/A #
2690N/A self._image_lm = None
2690N/A self._cfg_mediators = {}
2690N/A self._varcets_change = False
2690N/A self._new_variants = None
2690N/A self._changed_facets = pkg.facet.Facets()
2690N/A self._removed_facets = set()
2690N/A self._new_facets = None
2690N/A self._new_mediators = collections.defaultdict(set)
2690N/A self._mediators_change = False
2690N/A self._new_avoid_obs = (set(), set())
2690N/A self._fmri_changes = [] # install (None, fmri)
2690N/A # remove (oldfmri, None)
2690N/A # update (oldfmri, newfmri|oldfmri)
2690N/A self._solver_summary = []
2690N/A self._solver_errors = None
2690N/A self.li_attach = False
2690N/A self.li_ppkgs = frozenset()
2690N/A self.li_ppubs = None
2690N/A self.li_props = {}
2690N/A
2690N/A #
2690N/A # Properties set when state >= EVALUATED_OK
2690N/A #
2690N/A # raw actions
2690N/A self.pkg_plans = []
2690N/A # merged actions
2690N/A self.removal_actions = []
2690N/A self.update_actions = []
2690N/A self.install_actions = []
2690N/A # smf and other actuators (driver actions get added during
2690N/A # execution stage).
2690N/A self._actuators = pkg.client.actuator.Actuator()
2690N/A # Used to track users and groups that are part of operation.
2690N/A self.added_groups = {}
2690N/A self.added_users = {}
2690N/A self.removed_groups = {}
2690N/A self.removed_users = {}
2708N/A # release notes that are part of this operation
2708N/A self.release_notes = (False, [])
2690N/A # plan properties
2690N/A self._cbytes_added = 0 # size of compressed files
2690N/A self._bytes_added = 0 # size of files added
2690N/A self._need_boot_archive = None
2690N/A # child properties
2690N/A self.child_op = None
2690N/A self.child_kwargs = {}
2690N/A self.children_ignored = None
2690N/A self.children_planned = []
2690N/A self.children_nop = []
2690N/A # driver aliases to remove
2690N/A self._rm_aliases = {}
2690N/A
2690N/A #
2690N/A # Properties set when state >= EXECUTED_OK
2690N/A #
2690N/A self._salvaged = []
2708N/A self.release_notes_name = None
2690N/A
2690N/A #
2690N/A # Set by imageplan.set_be_options()
2690N/A #
2690N/A self._backup_be = None
2690N/A self._backup_be_name = None
2690N/A self._new_be = None
2690N/A self._be_name = None
2690N/A self._be_activate = False
2690N/A
2690N/A # Accessed via imageplan.update_index
2690N/A self._update_index = True
2690N/A
2690N/A # stats about the current image
2690N/A self._cbytes_avail = 0 # avail space for downloads
2690N/A self._bytes_avail = 0 # avail space for fs
2690N/A
2690N/A @staticmethod
2690N/A def getstate(obj, je_state=None, reset_volatiles=False):
2690N/A """Returns the serialized state of this object in a format
2690N/A that that can be easily stored using JSON, pickle, etc."""
2828N/A # Access to protected member; pylint: disable=W0212
2690N/A
2690N/A if reset_volatiles:
2690N/A # backup and clear volatiles
2690N/A _bytes_avail = obj._bytes_avail
2690N/A _cbytes_avail = obj._cbytes_avail
2690N/A obj._bytes_avail = obj._cbytes_avail = 0
2690N/A
2690N/A name = PlanDescription.__name__
2690N/A state = pkg.misc.json_encode(name, obj.__dict__,
2690N/A PlanDescription.__state__desc,
2690N/A commonize=PlanDescription.__state__commonize,
2690N/A je_state=je_state)
2690N/A
2690N/A # add a state version encoding identifier
2690N/A state[name] = 0
2690N/A
2690N/A if reset_volatiles:
2690N/A obj._bytes_avail = obj._bytes_avail
2690N/A obj._cbytes_avail = obj._cbytes_avail
2690N/A
2690N/A return state
2690N/A
2690N/A @staticmethod
2690N/A def setstate(obj, state, jd_state=None):
2690N/A """Update the state of this object using previously serialized
2690N/A state obtained via getstate()."""
2828N/A # Access to protected member; pylint: disable=W0212
2690N/A
2690N/A # get the name of the object we're dealing with
2690N/A name = PlanDescription.__name__
2690N/A
2690N/A # version check and delete the encoding identifier
2690N/A assert state[name] == 0
2690N/A del state[name]
2690N/A
2690N/A # decode serialized state into python objects
2690N/A state = pkg.misc.json_decode(name, state,
2690N/A PlanDescription.__state__desc,
2690N/A commonize=PlanDescription.__state__commonize,
2690N/A jd_state=jd_state)
2690N/A
2690N/A # bulk update
2690N/A obj.__dict__.update(state)
2690N/A
2690N/A # clear volatiles
2690N/A obj._cbytes_avail = 0
2690N/A obj._bytes_avail = 0
2690N/A
2690N/A @staticmethod
2690N/A def fromstate(state, jd_state=None):
2690N/A """Allocate a new object using previously serialized state
2690N/A obtained via getstate()."""
2690N/A rv = PlanDescription()
2690N/A PlanDescription.setstate(rv, state, jd_state)
2690N/A return rv
2690N/A
2690N/A def _save(self, fobj, reset_volatiles=False):
2690N/A """Save a json encoded representation of this plan
2690N/A description objects into the specified file object."""
2690N/A
2690N/A state = PlanDescription.getstate(self,
2690N/A reset_volatiles=reset_volatiles)
2690N/A try:
2690N/A fobj.truncate()
2690N/A json.dump(state, fobj, encoding="utf-8")
2690N/A fobj.flush()
2690N/A except OSError, e:
2828N/A # Access to protected member; pylint: disable=W0212
2690N/A raise apx._convert_error(e)
2690N/A
2690N/A del state
2690N/A
2690N/A def _load(self, fobj):
2690N/A """Load a json encoded representation of a plan description
2690N/A from the specified file object."""
2690N/A
2690N/A assert self.state == UNEVALUATED
2690N/A
2690N/A try:
2690N/A fobj.seek(0)
2690N/A state = json.load(fobj, encoding="utf-8")
2690N/A except OSError, e:
2828N/A # Access to protected member; pylint: disable=W0212
2690N/A raise apx._convert_error(e)
2690N/A
2690N/A PlanDescription.setstate(self, state)
2690N/A del state
2690N/A
2690N/A def _executed_ok(self):
2690N/A """A private interface used after a plan is successfully
2690N/A invoked to free up memory."""
2690N/A
2690N/A # reduce memory consumption
2690N/A self._fmri_changes = []
2690N/A self._actuators = pkg.client.actuator.Actuator()
2690N/A self.added_groups = {}
2690N/A self.added_users = {}
2690N/A self.removed_groups = {}
2690N/A self.removed_users = {}
2690N/A
2690N/A @property
2690N/A def executed(self):
2690N/A """A boolean indicating if we attempted to execute this
2690N/A plan."""
2690N/A return self.state in [EXECUTED_OK, EXECUTED_ERROR]
2690N/A
2690N/A @property
2690N/A def services(self):
2690N/A """Returns a list of string tuples describing affected services
2690N/A (action, SMF FMRI)."""
2690N/A return sorted(
2690N/A ((str(a), str(smf_fmri))
2690N/A for a, smf_fmri in self._actuators.get_services_list()),
2690N/A key=operator.itemgetter(0, 1)
2690N/A )
2690N/A
2690N/A @property
2690N/A def mediators(self):
2690N/A """Returns a list of three-tuples containing information about
2690N/A the mediators. The first element in the tuple is the name of
2690N/A the mediator. The second element is a tuple containing the
2690N/A original version and source and the new version and source of
2690N/A the mediator. The third element is a tuple containing the
2690N/A original implementation and source and new implementation and
2690N/A source."""
2690N/A
2690N/A ret = []
2690N/A
2690N/A if not self._mediators_change or \
2690N/A (not self._cfg_mediators and not self._new_mediators):
2690N/A return ret
2690N/A
2690N/A def get_mediation(mediators, m):
2828N/A # Missing docstring; pylint: disable=C0111
2690N/A mimpl = mver = mimpl_source = \
2690N/A mver_source = None
2690N/A if m in mediators:
2690N/A mimpl = mediators[m].get(
2690N/A "implementation")
2690N/A mimpl_ver = mediators[m].get(
2690N/A "implementation-version")
2690N/A if mimpl_ver:
2690N/A mimpl_ver = \
2690N/A mimpl_ver.get_short_version()
2690N/A if mimpl and mimpl_ver:
2690N/A mimpl += "(@%s)" % mimpl_ver
2690N/A mimpl_source = mediators[m].get(
2690N/A "implementation-source")
2690N/A
2690N/A mver = mediators[m].get("version")
2690N/A if mver:
2690N/A mver = mver.get_short_version()
2690N/A mver_source = mediators[m].get(
2690N/A "version-source")
2690N/A return mimpl, mver, mimpl_source, mver_source
2690N/A
2690N/A for m in sorted(set(self._new_mediators.keys() +
2690N/A self._cfg_mediators.keys())):
2690N/A orig_impl, orig_ver, orig_impl_source, \
2690N/A orig_ver_source = get_mediation(
2690N/A self._cfg_mediators, m)
2690N/A new_impl, new_ver, new_impl_source, new_ver_source = \
2690N/A get_mediation(self._new_mediators, m)
2690N/A
2690N/A if orig_ver == new_ver and \
2690N/A orig_ver_source == new_ver_source and \
2690N/A orig_impl == new_impl and \
2690N/A orig_impl_source == new_impl_source:
2690N/A # Mediation not changed.
2690N/A continue
2690N/A
2690N/A out = (m,
2690N/A ((orig_ver, orig_ver_source),
2690N/A (new_ver, new_ver_source)),
2690N/A ((orig_impl, orig_impl_source),
2690N/A (new_impl, new_impl_source)))
2690N/A
2690N/A ret.append(out)
2690N/A
2690N/A return ret
2690N/A
2690N/A def get_mediators(self):
2690N/A """Returns list of strings describing mediator changes."""
2690N/A
2690N/A ret = []
2690N/A for m, ver, impl in sorted(self.mediators):
2690N/A ((orig_ver, orig_ver_source),
2690N/A (new_ver, new_ver_source)) = ver
2690N/A ((orig_impl, orig_impl_source),
2690N/A (new_impl, new_impl_source)) = impl
2690N/A out = "mediator %s:\n" % m
2690N/A if orig_ver and new_ver:
2690N/A out += " version: %s (%s default) " \
2690N/A "-> %s (%s default)\n" % (orig_ver,
2690N/A orig_ver_source, new_ver, new_ver_source)
2690N/A elif orig_ver:
2690N/A out += " version: %s (%s default) " \
2690N/A "-> None\n" % (orig_ver, orig_ver_source)
2690N/A elif new_ver:
2690N/A out += " version: None -> " \
2690N/A "%s (%s default)\n" % (new_ver,
2690N/A new_ver_source)
2690N/A
2690N/A if orig_impl and new_impl:
2690N/A out += " implementation: %s (%s default) " \
2690N/A "-> %s (%s default)\n" % (orig_impl,
2690N/A orig_impl_source, new_impl, new_impl_source)
2690N/A elif orig_impl:
2690N/A out += " implementation: %s (%s default) " \
2690N/A "-> None\n" % (orig_impl, orig_impl_source)
2690N/A elif new_impl:
2690N/A out += " implementation: None -> " \
2690N/A "%s (%s default)\n" % (new_impl,
2690N/A new_impl_source)
2690N/A ret.append(out)
2690N/A return ret
2690N/A
2690N/A @property
2690N/A def plan_desc(self):
2690N/A """Get the proposed fmri changes."""
2690N/A return self._fmri_changes
2690N/A
2690N/A @property
2690N/A def salvaged(self):
2690N/A """A list of tuples of items that were salvaged during plan
2690N/A execution. Each tuple is of the form (original_path,
2690N/A salvage_path). Where 'original_path' is the path of the item
2690N/A before it was salvaged, and 'salvage_path' is where the item was
2690N/A moved to. This property is only valid after plan execution
2690N/A has completed."""
2690N/A assert self.executed
2690N/A return self._salvaged
2690N/A
2690N/A @property
2690N/A def varcets(self):
2690N/A """Returns a tuple of two lists containing the facet and variant
2690N/A changes in this plan."""
2690N/A vs = []
2690N/A if self._new_variants:
2690N/A vs = self._new_variants.items()
2690N/A fs = []
2690N/A fs.extend(self._changed_facets.items())
2690N/A fs.extend([(f, None) for f in self._removed_facets])
2690N/A return (vs, fs)
2690N/A
2690N/A def get_varcets(self):
2690N/A """Returns a formatted list of strings representing the
2690N/A variant/facet changes in this plan"""
2690N/A vs, fs = self.varcets
2690N/A ret = []
2690N/A ret.extend(["variant %s: %s" % a for a in vs])
2690N/A ret.extend([" facet %s: %s" % a for a in fs])
2690N/A return ret
2690N/A
2690N/A def get_changes(self):
2690N/A """A generation function that yields tuples of PackageInfo
2690N/A objects of the form (src_pi, dest_pi).
2690N/A
2690N/A If 'src_pi' is None, then 'dest_pi' is the package being
2690N/A installed.
2690N/A
2690N/A If 'src_pi' is not None, and 'dest_pi' is None, 'src_pi'
2690N/A is the package being removed.
2690N/A
2690N/A If 'src_pi' is not None, and 'dest_pi' is not None,
2690N/A then 'src_pi' is the original version of the package,
2690N/A and 'dest_pi' is the new version of the package it is
2690N/A being upgraded to."""
2690N/A
2690N/A for pp in sorted(self.pkg_plans,
2690N/A key=operator.attrgetter("origin_fmri", "destination_fmri")):
2690N/A yield (PackageInfo.build_from_fmri(pp.origin_fmri),
2690N/A PackageInfo.build_from_fmri(pp.destination_fmri))
2690N/A
2690N/A def get_actions(self):
2690N/A """A generator function that yields action change descriptions
2690N/A in the order they will be performed."""
2690N/A
2828N/A # Unused variable '%s'; pylint: disable=W0612
2690N/A for pplan, o_act, d_act in itertools.chain(
2690N/A self.removal_actions,
2690N/A self.update_actions,
2690N/A self.install_actions):
2828N/A # pylint: enable=W0612
2690N/A yield "%s -> %s" % (o_act, d_act)
2690N/A
2708N/A def has_release_notes(self):
2708N/A """True if there are release notes for this plan"""
2708N/A return bool(self.release_notes[1])
2708N/A
2708N/A def must_display_notes(self):
2708N/A """True if the release notes must be displayed"""
2708N/A return self.release_notes[0]
2708N/A
2708N/A def get_release_notes(self):
2708N/A """A generator that returns the release notes for this plan"""
2708N/A for notes in self.release_notes[1]:
2708N/A yield notes
2708N/A
2690N/A def get_licenses(self, pfmri=None):
2690N/A """A generator function that yields information about the
2690N/A licenses related to the current plan in tuples of the form
2690N/A (dest_fmri, src, dest, accepted, displayed) for the given
2690N/A package FMRI or all packages in the plan. This is only
2690N/A available for licenses that are being installed or updated.
2690N/A
2690N/A 'dest_fmri' is the FMRI of the package being installed.
2690N/A
2690N/A 'src' is a LicenseInfo object if the license of the related
2690N/A package is being updated; otherwise it is None.
2690N/A
2690N/A 'dest' is the LicenseInfo object for the license that is being
2690N/A installed.
2690N/A
2690N/A 'accepted' is a boolean value indicating that the license has
2690N/A been marked as accepted for the current plan.
2690N/A
2690N/A 'displayed' is a boolean value indicating that the license has
2690N/A been marked as displayed for the current plan."""
2690N/A
2690N/A for pp in self.pkg_plans:
2690N/A dfmri = pp.destination_fmri
2690N/A if pfmri and dfmri != pfmri:
2690N/A continue
2690N/A
2828N/A # Unused variable; pylint: disable=W0612
2690N/A for lid, entry in pp.get_licenses():
2690N/A src = entry["src"]
2690N/A src_li = None
2690N/A if src:
2690N/A src_li = LicenseInfo(pp.origin_fmri,
2690N/A src, img=pp.image)
2690N/A
2690N/A dest = entry["dest"]
2690N/A dest_li = None
2690N/A if dest:
2690N/A dest_li = LicenseInfo(
2690N/A pp.destination_fmri, dest,
2690N/A img=pp.image)
2690N/A
2690N/A yield (pp.destination_fmri, src_li, dest_li,
2690N/A entry["accepted"], entry["displayed"])
2690N/A
2690N/A if pfmri:
2690N/A break
2690N/A
2690N/A def get_solver_errors(self):
2690N/A """Returns a list of strings for all FMRIs evaluated by the
2690N/A solver explaining why they were rejected. (All packages
2690N/A found in solver's trim database.) Only available if
2690N/A DebugValues["plan"] was set when the plan was created.
2690N/A """
2690N/A
2690N/A assert self.state >= EVALUATED_PKGS, \
2690N/A "%s >= %s" % (self.state, EVALUATED_PKGS)
2690N/A
2690N/A # in case this operation doesn't use solver
2690N/A if self._solver_errors is None:
2690N/A return []
2690N/A
2690N/A return self._solver_errors
2690N/A
2690N/A @property
2690N/A def plan_type(self):
2690N/A """Return the type of plan that was created (ex:
2690N/A API_OP_UPDATE)."""
2690N/A return self._op
2690N/A
2690N/A @property
2690N/A def update_index(self):
2690N/A """Boolean indicating if indexes will be updated as part of an
2690N/A image-modifying operation."""
2690N/A return self._update_index
2690N/A
2690N/A @property
2690N/A def backup_be(self):
2690N/A """Either None, True, or False. If None then executing this
2690N/A plan may create a backup BE. If False, then executing this
2690N/A plan will not create a backup BE. If True, then executing
2690N/A this plan will create a backup BE."""
2690N/A return self._backup_be
2690N/A
2690N/A @property
2690N/A def be_name(self):
2690N/A """The name of a new BE that will be created if this plan is
2690N/A executed."""
2690N/A return self._be_name
2690N/A
2690N/A @property
2690N/A def backup_be_name(self):
2690N/A """The name of a new backup BE that will be created if this
2690N/A plan is executed."""
2690N/A return self._backup_be_name
2690N/A
2690N/A @property
2690N/A def activate_be(self):
2690N/A """A boolean value indicating whether any new boot environment
2690N/A will be set active on next boot."""
2690N/A return self._be_activate
2690N/A
2690N/A @property
2690N/A def reboot_needed(self):
2690N/A """A boolean value indicating that execution of the plan will
2690N/A require a restart of the system to take effect if the target
2690N/A image is an existing boot environment."""
2690N/A return self._actuators.reboot_needed()
2690N/A
2690N/A @property
2690N/A def new_be(self):
2690N/A """A boolean value indicating that execution of the plan will
2690N/A take place in a clone of the current live environment"""
2690N/A return self._new_be
2690N/A
2690N/A @property
2690N/A def update_boot_archive(self):
2690N/A """A boolean value indicating whether or not the boot archive
2690N/A will be rebuilt"""
2690N/A return self._need_boot_archive
2690N/A
2690N/A @property
2690N/A def bytes_added(self):
2690N/A """Estimated number of bytes added"""
2690N/A return self._bytes_added
2690N/A
2690N/A @property
2690N/A def cbytes_added(self):
2690N/A """Estimated number of download cache bytes added"""
2690N/A return self._cbytes_added
2690N/A
2690N/A @property
2690N/A def bytes_avail(self):
2690N/A """Estimated number of bytes available in image /"""
2690N/A return self._bytes_avail
2690N/A
2690N/A @property
2690N/A def cbytes_avail(self):
2690N/A """Estimated number of bytes available in download cache"""
2690N/A return self._cbytes_avail