#
# 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
# 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
#
#
#
"""module describing a user packaging object
This module contains the UserAction class, which represents a user
packaging object. This contains the attributes necessary to create
a new user."""
from . import generic
try:
except ImportError:
"""Class representing a user packaging object."""
__slots__ = []
# if these values are different on disk than in action
# prefer on-disk version for actual login accounts (root)
"max", "expire", "flag",
"warn", "inactive"]
""" three way attribute merge between old manifest,
what's on disk and new manifest. For any values
on disk that are not in the new plan, use the values
on disk. Use new plan values unless attribute is
in self.use_existing_attrs, or if old manifest and
on-disk copy match...."""
continue
# preserve UID if not specified explicitly
continue
# prefer manifest version if not mutable password
if attr == "password" and \
continue
# Only prefer on-disk entries if password is
# user-settable (e.g. '' or UP).
continue
if attr != "group-list":
else:
return out
"""read state of user from files. May raise KeyError"""
if "gid" in cur_attrs:
cur_attrs["group"] = \
if grps:
"""client-side method that adds the user...
update any attrs that changed from orig
unless the on-disk stuff was changed"""
if not have_cfgfiles:
# The user action is ignored if cfgfiles is not
# available.
return
try:
orig_attrs = {}
if orig:
# Grab default values from files, extend by
# specifics from original manifest for
# comparisons sake.
orig_attrs["group-list"] = []
else:
# If we're installing a user for the first time,
# we want to override whatever value might be
# represented by the presence or absence of the
# user in the ftpusers file. Remove the value
# from the representation of the file so that
# the new value takes precedence in the merge.
del cur_attrs["ftpuser"]
# add default values to new attrs if not present
for attr in default_attrs:
if "group-list" in final_attrs:
final_attrs["group-list"])
except EnvironmentError as e:
raise
# If we're in the postinstall phase and the files
# *still* aren't there, bail gracefully.
if retry:
txt = _("User cannot be installed without user "
"database files present.")
except KeyError as e:
# cannot find group
finally:
if "pw" in locals():
if users:
"""Returns a tuple of lists of the form (errors, warnings,
info). The error list will be empty if the action has been
correctly installed in the given image."""
errors = []
warnings = []
info = []
if not have_cfgfiles:
# The user action is ignored if cfgfiles is not
# available.
try:
except EnvironmentError as e:
else:
except KeyError as e:
# Get the default values if they're non-empty
(k, v)
if v != ""
))
# Certain defaults are dynamic, so we need to ignore what's on
# disk
# ignore changes in certain fields if password is
# mutable; this indicates that this account is used
# by a human and logins, timeouts, etc. are changable.
else:
del should_be["shell-change-ok"]
# always ignore flag
if "flag" in cur_attrs:
del cur_attrs["flag"]
# Note where attributes are missing
for k in should_be:
# Note where attributes should be empty
for k in cur_attrs:
if cur_attrs[k]:
_("{entry}: '{found}' should be '{expected}'").format(
for a in should_be
)
"""client-side method that removes this user"""
if not have_cfgfiles:
# The user action is ignored if cfgfiles is not
# available.
return
try:
# negative logic
except KeyError as e:
# Already gone; don't care.
raise
finally:
"""Generates the indices needed by the search dictionary. See
generic.py for a more detailed explanation."""
"""Performs additional validation of action attributes that
for performance or other reasons cannot or should not be done
during Action object creation. An ActionError exception (or
subclass of) will be raised if any attributes are not valid.
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.
"""
"uid", "group", "gcos-field", "home-dir", "login-shell",
"ftpuser", "lastchg", "min", "max", "warn", "inactive",
"expire", "flag"),
required_attrs=("group",))
"""Arrange for user actions to be installed in uid order. This
will only hold true for actions installed at one time, but that's
generally what we need on initial install."""
# put unspecified uids at the end
return (a > b) - (a < b)