| Current File : //sbin/beadm |
#!/usr/bin/python2.7 -E
#
# Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
#
"""
beadm - The Boot Environment Administration tool. Use this CLI to
manage boot environments.
"""
import getopt
import gettext
import os
import sys
import shutil
import traceback
import time
import subprocess
import errno
from beadm import _
from beadm.BootEnvironment import *
import solaris.zones as zones
import beadm.messages as msg
import libbe as lb
def usage():
'''Defines parameters and options of the command beadm.'''
print >> sys.stderr, _("""
Usage:
beadm subcommand cmd_options
subcommands:
beadm activate beName
beadm create [-a] [-d description]
[-e non-activeBeName | beName@snapshot]
[-o property=value] ... [-p zpool] beName
beadm create beName@snapshot
beadm destroy [-fF] beName | beName@snapshot
beadm destroy [-fF] -O
beadm list [[-a] | [-d] [-s]] [-H] [beName]
beadm mount [-b] beName mountpoint
beadm rename beName newBeName
beadm set-policy {-n policy [-n -policy2] ...} beName [beName2 ...]
beadm unmount [-f] beName""")
sys.exit(1)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Public Command Line functions described in beadm(1)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def activate(opts):
"""
Function: activate
Description: Activate a Boot Environment.The following is the
subcommand, options and args that make up the
opts object passed in:
Parameters:
opts - A string containing the active subcommand
Returns:
0 - Success
1 - Failure
"""
if len(opts) != 1:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
priv_check()
be = BootEnvironment()
if lb.beVerifyBEName(opts[0]) != 0:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
rc = lb.beActivate(opts[0])
if rc == 0:
return 0
be.msg_buf["0"] = opts[0]
if rc == msg.Msgs.BE_ERR_BE_NOENT:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_BE_DOES_NOT_EXIST, opts[0])
elif rc == msg.Msgs.BE_ERR_PERM or rc == msg.Msgs.BE_ERR_ACCESS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_PERMISSIONS, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_ACTIVATE, be.msg_buf, -1)
return 1
else:
be.msg_buf["1"] = lb.beGetErrDesc(rc)
if be.msg_buf["1"] == None:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_ACTIVATE, be.msg_buf, -1)
return 1
def create(opts):
"""
Function: create
Description: Create a Boot Environment. The following is the
subcommand, options and args that make up the
opts object passed in:
create [-a] [-d description]
[-e non-activeBeName | beName@Snapshot]
[-o property=value] ... [-p zpool] beName
create beName@Snapshot
Parameters:
opts - A object containing the create subcommand
and all the options and arguments passed in
on the command line mentioned above.
Returns:
0 - Success
1 - Failure
"""
priv_check()
be = BootEnvironment()
activate = False
try:
opts_args, be.trgt_be_name_or_snapshot = getopt.getopt(opts,
"ad:e:o:p:")
except getopt.GetoptError:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
# Counters for detecting multiple options.
# e.g. beadm create -p rpool -p rpool2 newbe
num_a_opts = 0
num_e_opts = 0
num_p_opts = 0
num_d_opts = 0
for opt, arg in opts_args:
if opt == "-a":
activate = True
num_a_opts += 1
elif opt == "-e":
be.src_be_name_or_snapshot = arg
num_e_opts += 1
elif opt == "-o":
key, value = arg.split("=")
be.properties[key] = value
elif opt == "-p":
be.trgt_rpool = arg
num_p_opts += 1
elif opt == "-d":
be.description = arg
num_d_opts += 1
if num_a_opts > 1 or num_e_opts > 1 or num_p_opts > 1 or num_d_opts > 1:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
# Check that all info provided from the user is legitimate.
if (verifyCreateOptionsArgs(be) != 0):
usage()
if initBELog("create", be) != 0:
return 1
msg.printMsg(msg.Msgs.BEADM_MSG_BE_CREATE_START,
be.trgt_be_name_or_snapshot[0], be.log_id)
if '@' in be.trgt_be_name_or_snapshot[0]:
# Create a snapshot
rc = createSnapshot(be)
else:
if lb.beVerifyBEName(be.trgt_be_name_or_snapshot[0]) != 0:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
# Create a BE based on a snapshot
if be.src_be_name_or_snapshot is not None and \
'@' in be.src_be_name_or_snapshot:
# Create a BE from a snapshot
rc = createBEFromSnapshot(be)
else:
rc = createBE(be)
# Activate the BE if the user chose to.
if activate and rc == 0:
rc = activateBE(be)
cleanupBELog(be)
return rc
def destroy_be(be, be_name, snap_name, be_active, be_active_on_boot,
is_snapshot, suppress_prompt, force_unmount):
# If the user is trying to destroy the 'active' BE then quit now.
if not is_snapshot and be_active == be_name:
be.msg_buf["0"] = be.msg_buf["1"] = be_active
msg.printMsg(msg.Msgs.BEADM_ERR_DESTROY_ACTIVE, be.msg_buf, -1)
return 1
if not suppress_prompt:
# Display a destruction question and wait for user response.
# Quit if negative user response.
if not displayDestructionQuestion(be):
return 0
if is_snapshot:
# Destroy a snapshot.
rc = lb.beDestroySnapshot(be_name, snap_name)
else:
# Destroy a BE. Passing in 1 for the second arg destroys
# any snapshots the BE may have as well.
rc = lb.beDestroy(be_name, 1, force_unmount)
# Check if the BE that was just destroyed was the
# 'active on boot' BE. If it was, display a message letting
# the user know that the 'active' BE is now also the
# 'active on boot' BE.
if be_active_on_boot == be_name and rc == 0:
msg.printMsg(msg.Msgs.BEADM_MSG_ACTIVE_ON_BOOT,
be_active, -1)
if rc == 0:
try:
shutil.rmtree("/var/log/beadm/" + \
be.trgt_be_name_or_snapshot[0], True)
except:
msg.printMsg(msg.Msgs.BEADM_ERR_LOG_RM,
"/var/log/beadm/" + be.trgt_be_name_or_snapshot[0],
-1)
return 0
be.msg_buf["0"] = be.trgt_be_name_or_snapshot[0]
if rc == msg.Msgs.BE_ERR_MOUNTED:
be.msg_buf["1"] = be.msg_buf["2"] = be.trgt_be_name_or_snapshot[0]
msg.printMsg(msg.Msgs.BEADM_ERR_MOUNTED, be.msg_buf, -1)
return 1
elif rc == msg.Msgs.BE_ERR_DESTROY_CURR_BE:
msg.printMsg(msg.Msgs.BEADM_ERR_DESTROY_ACTIVE, \
be.msg_buf["0"], -1)
return 1
elif rc == msg.Msgs.BE_ERR_ZONES_UNMOUNT:
be.msg_buf["1"] = be.trgt_be_name_or_snapshot[0]
msg.printMsg(msg.Msgs.BE_ERR_ZONES_UNMOUNT, be.msg_buf, -1)
return 1
elif rc == msg.Msgs.BE_ERR_PERM or rc == msg.Msgs.BE_ERR_ACCESS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_PERMISSIONS, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_DESTROY, be.msg_buf, -1)
return 1
else:
be.msg_buf["1"] = lb.beGetErrDesc(rc)
if be.msg_buf["1"] == None:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_DESTROY, be.msg_buf, -1)
return 1
def destroy(opts):
"""
Function: destroy
Description: Destroy a Boot Environment. The following is the
subcommand, options and args that make up the
opts object passed in:
destroy [-fF] beName | beName@snapshot
destroy the boot environment or boot
environment snapshot
destroy [-fF] -O
destroy all orphan boot environments
Parameters:
opts - A object containing the destroy subcommand
and all the options and arguments passed in
on the command line mentioned above.
Returns:
0 - Success
1 - Failure
"""
priv_check()
force_unmount = 0
suppress_prompt = False
be_active_on_boot = None
destroy_orphans = False
be = BootEnvironment()
try:
opts_args, be.trgt_be_name_or_snapshot = getopt.getopt(opts, "fFO")
except getopt.GetoptError:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
# Counters for detecting multiple options.
# e.g. beadm destroy -f -f newbe
num_f_opts = 0
num_sf_opts = 0
num_o_opts = 0
for opt, arg in opts_args:
if opt == "-f":
force_unmount = 1
num_sf_opts += 1
elif opt == "-F":
suppress_prompt = True
num_f_opts += 1
elif opt == "-O":
destroy_orphans = True
num_o_opts += 1
if num_sf_opts > 1 or num_f_opts > 1 or num_o_opts > 1:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
# Check if invocation has correct arguments
if (((not destroy_orphans) and len(be.trgt_be_name_or_snapshot) != 1) or
(destroy_orphans and len(be.trgt_be_name_or_snapshot) != 0)):
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
is_snapshot = False
if destroy_orphans:
# Fail if we are in global zone.
if zones.getzoneid() == 0:
msg.printMsg(msg.Msgs.BEADM_ERR_ZONE_NOTSUP, 'global', -1)
return 1
# Get list of Boot Environments.
rc, be_list = lb.beList()
if rc != 0:
string = lb.beGetErrDesc(rc)
if string is None:
string = msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_LIST, string, -1)
return 1
# Scroll over list of all boot environments.
error_seen = 0
for be_entry in be_list:
# Check if BE is orphan.
if 'orphan' in be_entry and be_entry['orphan']:
is_active = None
is_be_active_on_boot = None
# Get BE properties.
be_name = be_entry.get("orig_be_name")
if be_entry.get("active"):
is_active = be_name
if be_entry.get("active_boot"):
is_be_active_on_boot = be_name
# Set the target BE name to destroy.
be.trgt_be_name_or_snapshot = [be_name]
# If we fail for any BE, set error_seen and continue
# to destroy other orphan zone BEs.
if (destroy_be(be, be_name, None, is_active, \
is_be_active_on_boot, False, suppress_prompt, \
force_unmount) != 0):
error_seen = 1
return error_seen
if "@" in be.trgt_be_name_or_snapshot[0]:
is_snapshot = True
try:
be_name, snap_name = be.trgt_be_name_or_snapshot[0].split("@")
except ValueError:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
else:
be_name = be.trgt_be_name_or_snapshot[0]
snap_name = None
if lb.beVerifyBEName(be_name) != 0:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
# Check to see if the BE or BE snapshot the user supplied actually exists.
rc, be_list = lb.beList(be_name)
if rc != 0:
if rc == msg.Msgs.BE_ERR_BE_NOENT:
if is_snapshot:
msg.printMsg(msg.Msgs.BEADM_ERR_SNAP_DOES_NOT_EXISTS,
be_name, -1)
else:
msg.printMsg(msg.Msgs.BEADM_ERR_BE_DOES_NOT_EXIST, be_name, -1)
return 1
else:
string = lb.beGetErrDesc(rc)
if string is None:
string = msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_LIST, string, -1)
return 1
if is_snapshot:
for be_entry in be_list:
if be_entry.get("snap_name") == be.trgt_be_name_or_snapshot[0]:
break
else:
msg.printMsg(msg.Msgs.BEADM_ERR_SNAP_DOES_NOT_EXISTS,
be.trgt_be_name_or_snapshot[0], -1)
return 1
be_active, be_active_on_boot = getActiveBEAndActiveOnBootBE()
return (destroy_be(be, be_name, snap_name, be_active, be_active_on_boot,
is_snapshot, suppress_prompt, force_unmount))
def list(opts):
"""
Description: List the attributes of a Boot Environment.
The following is the subcommand, options
and args that make up the opts object
passed in:
list [[-a] | [-d] [-s]] [-H] [beName]
-a displays all info
-d displays BE info plus dataset info
-s displays BE info plus snapshot info
-H displays info parsable by a computer
Parameters:
opts - A object containing the list subcommand
and all the options and arguments passed in
on the command line mentioned above.
Returns:
0 - Success
1 - Failure
"""
be = BootEnvironment()
list_all_attrs = ""
list_datasets = ""
list_snapshots = ""
dont_display_headers = False
be_name = None
be_list = None
# Counters for detecting multiple options.
# e.g. beadm list -a -a newbe
num_a_opts = 0
num_d_opts = 0
num_s_opts = 0
num_h_opts = 0
try:
opts_args, be.trgt_be_name_or_snapshot = getopt.getopt(opts, "adHs")
except getopt.GetoptError:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
for opt, arg in opts_args:
if opt == "-a":
list_all_attrs = opt
num_a_opts += 1
elif opt == "-d":
list_datasets = opt
num_d_opts += 1
elif opt == "-s":
list_snapshots = opt
num_s_opts += 1
elif opt == "-H":
dont_display_headers = True
num_h_opts += 1
if num_a_opts > 1 or num_d_opts > 1 or num_s_opts > 1 or num_h_opts > 1:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
if len(be.trgt_be_name_or_snapshot) > 1:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
if len(be.trgt_be_name_or_snapshot) == 1:
be_name = be.trgt_be_name_or_snapshot[0]
if lb.beVerifyBEName(be_name) != 0:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
if (list_all_attrs == "-a" and (list_datasets == "-d" \
or list_snapshots == "-s")):
msg.printMsg(msg.Msgs.BEADM_ERR_MUTUALLY_EXCL,
list_all_attrs + " " + list_datasets + " " +
list_snapshots, -1)
usage()
list_options = ""
# When zones are implemented add "listZones == "-z" below
# Coalesce options to pass to display BEs.
if (list_datasets == "-d" and list_snapshots == "-s" or \
list_all_attrs == "-a"):
list_options = "-a"
elif list_datasets != "" or list_snapshots != "" or list_all_attrs != "":
list_options = list_datasets + " " + list_snapshots
rc, be_list = lb.beList()
if rc != 0:
if rc == msg.Msgs.BE_ERR_BE_NOENT:
if be_name == None:
msg.printMsg(msg.Msgs.BEADM_ERR_NO_BES_EXIST,
None, -1)
return 1
string = \
msg.getMsg(msg.Msgs.BEADM_ERR_BE_DOES_NOT_EXIST,
be_name)
else:
string = lb.beGetErrDesc(rc)
if string == None:
string = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_LIST, string, -1)
return 1
# classify according to command line options
if list_options.find("-a") != -1 or \
(list_options.find("-d") != -1 and list_options.find("-s") != -1):
list_object = CompleteList(dont_display_headers) #all
elif list_options.find("-d") != -1:
list_object = DatasetList(dont_display_headers) #dataset
elif list_options.find("-s") != -1:
list_object = SnapshotList(dont_display_headers) #snapshot
else:
list_object = BEList(dont_display_headers) #only BE
# use list method for object
if list_object.list(be_list, dont_display_headers, be_name) != 0:
msg.printMsg(msg.Msgs.BEADM_ERR_LIST_DATA, None, -1)
return 1
return 0
def mount(opts):
"""
Description: Mount a Boot Environment on a directory.
The following is the subcommand, options
and args that make up the opts object
passed in:
mount [-b] beName [mountpoint]
Parameters:
opts - A object containing the mount subcommand
and all the options and arguments passed in
on the command line mentioned above.
Returns:
0 - Success
1 - Failure
"""
priv_check()
be = BootEnvironment()
mountpoint = None
b_flag = False
try:
optlist, be_name_mnt_point = getopt.getopt(opts, "b")
for opt, arg in optlist:
if opt == "-b":
b_flag = True
except getopt.GetoptError:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
mnt_point_len = len(be_name_mnt_point)
if mnt_point_len != 2:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
else:
# Check for leading / in mount point
mountpoint = be_name_mnt_point[1]
if not mountpoint.startswith('/'):
msg.printMsg(msg.Msgs.BEADM_ERR_MOUNTPOINT,
mountpoint, -1)
return 1
if lb.beVerifyBEName(be_name_mnt_point[0]) != 0:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
rc = lb.beMount(be_name_mnt_point[0], mountpoint, b_flag)
if rc == 0:
return 0
be.msg_buf["0"] = be_name_mnt_point[0]
if rc == msg.Msgs.BE_ERR_MOUNTED:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_MOUNT_EXISTS,
be_name_mnt_point[0])
elif rc == msg.Msgs.BE_ERR_BE_NOENT:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_BE_DOES_NOT_EXIST,
be_name_mnt_point[0])
elif rc == msg.Msgs.BE_ERR_PERM or rc == msg.Msgs.BE_ERR_ACCESS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_PERMISSIONS, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_MOUNT, be.msg_buf, -1)
return 1
else:
be.msg_buf["1"] = lb.beGetErrDesc(rc)
if be.msg_buf["1"] == None:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_MOUNT, be.msg_buf, -1)
return 1
def unmount(opts):
"""
Description: Unmount a Boot Environment.
The following is the subcommand, options
and args that make up the opts object
passed in:
unmount [-f] beName
Parameters:
opts - A object containing the unmount subcommand
and all the options and arguments passed in
on the command line mentioned above.
Returns:
0 - Success
1 - Failure
"""
priv_check()
be = BootEnvironment()
force_unmount = 0
# Counter for detecting multiple options.
# e.g. beadm unmount -f -f newbe
num_f_opts = 0
try:
optlist, args = getopt.getopt(opts, "f")
except getopt.GetoptError:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
for opt, arg in optlist:
if opt == "-f":
force_unmount = 1
num_f_opts += 1
if num_f_opts > 1:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
if len(args) != 1:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
if lb.beVerifyBEName(args[0]) != 0:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
rc = lb.beUnmount(args[0], force_unmount)
if rc == 0:
return 0
be.msg_buf["0"] = args[0]
if rc == msg.Msgs.BE_ERR_UMOUNT_CURR_BE:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_UNMOUNT_ACTIVE,
args[0])
elif rc == msg.Msgs.BE_ERR_UMOUNT_SHARED:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_SHARED_FS, args[0])
elif rc == msg.Msgs.BE_ERR_PERM or rc == msg.Msgs.BE_ERR_ACCESS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_PERMISSIONS, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_UNMOUNT, be.msg_buf, -1)
return 1
else:
be.msg_buf["1"] = lb.beGetErrDesc(rc)
if be.msg_buf["1"] == None:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_UNMOUNT, be.msg_buf, -1)
return 1
def rename(opts):
"""
Description: Rename the name of a Boot Environment.
The following is the subcommand, options
and args that make up the opts object
passed in:
rename beName newBeName
Parameters:
opts - A object containing the mount subcommand
and all the options and arguments passed in
on the command line mentioned above.
Returns:
0 - Success
1 - Failure
"""
priv_check()
be = BootEnvironment()
try:
be_names = getopt.getopt(opts, "")[1]
except getopt.GetoptError:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
if len(be_names) != 2:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
if lb.beVerifyBEName(be_names[0]) != 0:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
if lb.beVerifyBEName(be_names[1]) != 0:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
rc = lb.beRename(be_names[0], be_names[1])
if rc == 0:
return 0
be.msg_buf["0"] = be_names[0]
if rc == msg.Msgs.BE_ERR_BE_NOENT:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_BE_DOES_NOT_EXIST,
be_names[0])
elif rc == msg.Msgs.BE_ERR_PERM or rc == msg.Msgs.BE_ERR_ACCESS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_PERMISSIONS, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_RENAME, be.msg_buf, -1)
return 1
else:
be.msg_buf["1"] = lb.beGetErrDesc(rc)
if be.msg_buf["1"] == None:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_RENAME, be.msg_buf, -1)
return 1
def set_policy(opts):
"""
Description: Sets the given Boot Environments' policy properties
to the specified value(s).
The following is the subcommand, options
and args that make up the opts object
passed in:
set-policy -n policy [-n -policy2] beName [beName2 ...]
Parameters:
opts - A object containing the set-policy subcommand
and all the options and arguments passed in
on the command line mentioned above.
Returns:
0 - Success
1 - Failure
"""
priv_check()
be = BootEnvironment()
try:
optlist, be_names = getopt.getopt(opts, "n:")
except getopt.GetoptError:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
usage()
policy = set()
for opt, arg in optlist:
if opt == "-n":
policy = policy.union(arg.split(','))
try:
errors = lb.beSetPolicy(be_names, policy)
if not errors:
return 0
for be_name, err_str in errors:
be.msg_buf["0"] = be_name
be.msg_buf["1"] = err_str
msg_code = msg.Msgs.BEADM_ERR_SET_POLICY
msg.printMsg(msg_code, be.msg_buf, -1)
return 1
except lb.LibbeBadPolicyError as lbpe:
be.msg_buf["0"] = lbpe.badpolicy
msg_code = msg.Msgs.BEADM_ERR_BAD_POLICY
except lb.LibbePolicyConflictError as lpce:
be.msg_buf["0"] = "' and '".join(lpce.conflicts)
msg_code = msg.Msgs.BEADM_ERR_POLICY_CONFLICT
except lb.LibbeBEDoesNotExistError as lbdnee:
be.msg_buf["0"] = lbdnee.be_name
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_BE_DOES_NOT_EXIST,
lbdnee.be_name)
msg_code = msg.Msgs.BEADM_ERR_SET_POLICY
except lb.LibbeUnsupportedOperationError as luoe:
be.msg_buf["0"] = luoe.error_str
msg_code = msg.Msgs.BEADM_ERR_SET_POLICY_UNSUP
except lb.LibbeInvalidPolicyError as lipe:
be.msg_buf["0"] = lipe.error_str
msg_code = msg.Msgs.BEADM_ERR_SET_POLICY_INVALID
except lb.LibbeOperationError as lpoe:
be.msg_buf["0"] = lpoe.be_name
be.msg_buf["1"] = lpoe.error_str
msg_code = msg.Msgs.BEADM_ERR_SET_POLICY
msg.printMsg(msg_code, be.msg_buf, -1)
return 1
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# End of CLI public functions
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def priv_check():
'''Checks to make sure that beadm is run with superuser privs'''
if not os.geteuid() == 0:
print >> sys.stderr, _("Must be root to execute this command")
sys.exit(1)
if not os.access("/", os.W_OK):
print >> sys.stderr, _("Current system is read-only")
sys.exit(1);
# Verify the options and arguments for the beadm create subcommand
def verifyCreateOptionsArgs(be):
"""Check valid BE names."""
len_be_args = len(be.trgt_be_name_or_snapshot)
if len_be_args < 1:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
return 1
if len_be_args > 1:
msg.printMsg(msg.Msgs.BEADM_ERR_OPT_ARGS, None, -1)
idx = 0
while len_be_args > idx:
msg.printMsg(msg.Msgs.BEADM_MSG_FREE_FORMAT,
be.trgt_be_name_or_snapshot[idx], -1)
idx += 1
return 1
return 0
def parseCLI(cli_opts_args):
"""Parse command line interface arguments."""
gettext.install("beadm", "/usr/lib/locale")
if len(cli_opts_args) == 0:
usage()
subcommand = cli_opts_args[0]
opts_args = cli_opts_args[1:]
if subcommand == "activate":
rc = activate(opts_args)
elif subcommand == "create":
rc = create(opts_args)
elif subcommand == "destroy":
rc = destroy(opts_args)
elif subcommand == "list":
rc = list(opts_args)
elif subcommand == "mount":
rc = mount(opts_args)
elif subcommand == "rename":
rc = rename(opts_args)
elif subcommand == "set-policy":
rc = set_policy(opts_args)
elif subcommand == "unmount" or \
subcommand == "umount": #aliased for convenience
rc = unmount(opts_args)
else:
msg.printMsg(msg.Msgs.BEADM_ERR_ILL_SUBCOMMAND,
subcommand, -1)
usage()
return(rc)
def main():
"""main function."""
gettext.install("beadm", "/usr/lib/locale")
# Set BE_PRINT_ERR=true to enable more verbose error messaging
# when failures occur.
os.environ["BE_PRINT_ERR"] = "true"
return(parseCLI(sys.argv[1:]))
def initBELog(log_id, be):
"""
Initiate the BE log
Format of the log
yyyymmdd_hhmmss - 20071130_140558
yy - year; 2007
mm - month; 11
dd - day; 30
hh - hour; 14
mm - minute; 05
ss - second; 58
"""
# /var/log/beadm/<beName>/<logId>.log.<yyyymmdd_hhmmss>
date = time.strftime("%Y%m%d_%H%M%S", time.localtime())
be.log = "/var/log/beadm/" + be.trgt_be_name_or_snapshot[0] + \
"/" + log_id + ".log" + "." + date
if not os.path.isfile(be.log) and not os.path.islink(be.log):
if not os.path.isdir(os.path.dirname(be.log)):
try:
os.makedirs(os.path.dirname(be.log), 0755)
except OSError as err:
#
# if we get an OSError due to EROFS we are in a read-only
# environment
#
if err.errno == errno.EROFS:
be.msg_buf["0"] = be.trgt_be_name_or_snapshot[0]
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_ROFS,
0)
msg.printMsg(msg.Msgs.BEADM_ERR_CREATE,
be.msg_buf, -1)
return 1
else:
be.msg_buf["0"] = be.trgt_be_name_or_snapshot[0]
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_PERMISSIONS,
0)
msg.printMsg(msg.Msgs.BEADM_ERR_CREATE,
be.msg_buf, -1)
return 1
try:
be.log_id = open(be.log, "a")
except (IOError, OSError) as err:
if err.errno == errno.EROFS:
msg.printMsg(msg.Msgs.BEADM_ERR_ROFS, None, -1)
return 1
else:
msg.printMsg(msg.Msgs.BEADM_ERR_LOG_CREATE,
None, -1)
return 1
else:
# Should never happen due to new time stamp each call
msg.printMsg(msg.Msgs.BEADM_ERR_LOG_CREATE, None, -1)
return 1
return 0
def cleanupBELog(be):
"""Clean up BE log."""
be.log_id.close()
def displayDestructionQuestion(be):
"""Display a destruction question and wait for user response."""
msg.printMsg(msg.Msgs.BEADM_MSG_DESTROY, be.trgt_be_name_or_snapshot[0],
-1)
while True:
try:
value = raw_input().strip().upper()
except KeyboardInterrupt:
return False
if (value == 'Y' or value == 'YES'):
return True
elif len(value) == 0 or value == 'N' or value == 'NO':
msg.printMsg(msg.Msgs.BEADM_MSG_DESTROY_NO,
be.trgt_be_name_or_snapshot[0], -1)
return False
else:
msg.printMsg(msg.Msgs.BEADM_ERR_INVALID_RESPONSE,
-1)
def setMaxColumnWidths(be_max_w, ds_max_w, ss_max_w, be_list):
"""Figure out max column widths for BE's, Datasets and Snapshots."""
for be_item in be_list:
if be_item.get("orig_be_name") is not None:
determineMaxBEColWidth(be_item, be_max_w)
if be_item.get("dataset") is not None:
determineMaxDSColWidth(be_item, ds_max_w)
if be_item.get("snap_name") is not None:
determineMaxSSColWidth(be_item, ss_max_w)
def getActiveBEAndActiveOnBootBE():
"""Return the 'active on boot' BE, the 'active' BE or None."""
active_be = None
active_be_on_boot = None
rc, be_list = lb.beList()
if rc != 0:
if rc == msg.Msgs.BE_ERR_BE_NOENT:
string = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_BES_EXIST)
else:
string = lb.beGetErrDesc(rc)
if string == None:
string = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_LIST, string, -1)
return None
for be_vals in be_list:
srcBeName = be_vals.get("orig_be_name")
if be_vals.get("active"):
active_be = srcBeName
if be_vals.get("active_boot"):
active_be_on_boot = srcBeName
if active_be is not None and active_be_on_boot is not None:
break
return active_be, active_be_on_boot
def createSnapshot(be):
"""Create a snapshot."""
try:
be_name, snap_name = be.trgt_be_name_or_snapshot[0].split("@")
except ValueError:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
rc = lb.beCreateSnapshot(be_name, snap_name)[0]
if rc == 0:
return 0
be.msg_buf["0"] = be.trgt_be_name_or_snapshot[0]
if rc == msg.Msgs.BE_ERR_BE_NOENT:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_BE_DOES_NOT_EXIST,
be_name)
elif rc == msg.Msgs.BE_ERR_SS_EXISTS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_SNAP_EXISTS,
be.trgt_be_name_or_snapshot[0])
elif rc == msg.Msgs.BE_ERR_PERM or rc == msg.Msgs.BE_ERR_ACCESS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_PERMISSIONS, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_CREATE, be.msg_buf, -1)
return 1
else:
be.msg_buf["1"] = lb.beGetErrDesc(rc)
if be.msg_buf["1"] == None:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_CREATE, be.msg_buf, -1)
return 1
def createBE(be):
"""Create a Boot Environment."""
rc = lb.beCopy(be.trgt_be_name_or_snapshot[0], be.src_be_name_or_snapshot,
None, be.trgt_rpool, be.properties, be.description)[0]
if rc == 0:
msg.printMsg(msg.Msgs.BEADM_MSG_BE_CREATE_SUCCESS,
be.trgt_be_name_or_snapshot[0], be.log_id)
return 0
be.msg_buf["0"] = be.trgt_be_name_or_snapshot[0]
if rc == msg.Msgs.BE_ERR_BE_NOENT:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_BE_DOES_NOT_EXIST,
be.src_be_name_or_snapshot)
elif rc == msg.Msgs.BE_ERR_BE_EXISTS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_BE_EXISTS,
be.trgt_be_name_or_snapshot[0])
elif rc == msg.Msgs.BE_ERR_PERM or rc == msg.Msgs.BE_ERR_ACCESS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_PERMISSIONS, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_CREATE, be.msg_buf, -1)
return 1
else:
be.msg_buf["1"] = lb.beGetErrDesc(rc)
if be.msg_buf["1"] == None:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_CREATE, be.msg_buf, be.log_id)
return 1
def createBEFromSnapshot(be):
"""Create a BE based off a snapshot."""
try:
be_name, snap_name = be.src_be_name_or_snapshot.split("@")
except ValueError:
msg.printMsg(msg.Msgs.BEADM_ERR_BENAME, None, -1)
return 1
rc = lb.beCopy(be.trgt_be_name_or_snapshot[0], be_name, snap_name,
be.trgt_rpool, be.properties, be.description)[0]
if rc == 0:
msg.printMsg(msg.Msgs.BEADM_MSG_BE_CREATE_SUCCESS,
be.trgt_be_name_or_snapshot[0], be.log_id)
return 0
be.msg_buf["0"] = be.trgt_be_name_or_snapshot[0]
if rc == msg.Msgs.BE_ERR_SS_NOENT:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_SNAP_DOES_NOT_EXISTS,
be.src_be_name_or_snapshot)
elif rc == msg.Msgs.BE_ERR_BE_EXISTS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_BE_EXISTS, \
be.trgt_be_name_or_snapshot[0])
elif rc == msg.Msgs.BE_ERR_BE_NOENT:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_BE_DOES_NOT_EXIST, \
be_name)
elif rc == msg.Msgs.BE_ERR_PERM or rc == msg.Msgs.BE_ERR_ACCESS:
be.msg_buf["1"] = msg.getMsg(msg.Msgs.BEADM_ERR_PERMISSIONS, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_CREATE, be.msg_buf, -1)
return 1
else:
be.msg_buf["1"] = lb.beGetErrDesc(rc)
if be.msg_buf["1"] == None:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_CREATE, be.msg_buf, be.log_id)
return 1
def activateBE(be):
"""
Activate a BE. Called from create() when -a is provided as CLI
Option.
"""
rc = lb.beActivate(be.trgt_be_name_or_snapshot[0])
if rc == 0:
return 0
be.msg_buf["0"] = be.trgt_be_name_or_snapshot[0]
if rc == msg.Msgs.BE_ERR_BE_NOENT:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_BE_DOES_NOT_EXIST,
be.trgt_be_name_or_snapshot)
else:
be.msg_buf["1"] = lb.beGetErrDesc(rc)
if be.msg_buf["1"] == None:
be.msg_buf["1"] = \
msg.getMsg(msg.Msgs.BEADM_ERR_NO_MSG, rc)
msg.printMsg(msg.Msgs.BEADM_ERR_ACTIVATE, be.msg_buf, -1)
return 1
if __name__ == "__main__":
try:
RC = main()
except SystemExit, e:
raise e
except:
traceback.print_exc()
sys.exit(99)
sys.exit(RC)