From a924e083afb0cd1e2632265ee1eff86b7f3b5bdc Mon Sep 17 00:00:00 2001 From: Tim Foster Date: Wed, 17 Sep 2008 01:34:36 +0100 Subject: [PATCH] Make logging work properly in the face of the RBAC changes Refresh i.manifest and r.manifest from ON gate --- src/i.manifest | 70 ++++++++++--- src/lib/svc/method/zfs-auto-snapshot | 38 +++---- src/r.manifest | 151 ++++++++++++++++++++++----- 3 files changed, 201 insertions(+), 58 deletions(-) diff --git a/src/i.manifest b/src/i.manifest index 72ebfdd..07c4b8c 100755 --- a/src/i.manifest +++ b/src/i.manifest @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -21,17 +20,58 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" -# # i.manifest - smf(5) service manifest install class action script # repfile=$PKG_INSTALL_ROOT/etc/svc/repository.db export repfile +SVCCFG=/usr/sbin/svccfg +AWK=/usr/bin/awk +RM=/usr/bin/rm +CP=/usr/bin/cp +MV=/usr/bin/mv +CHMOD=/usr/bin/chmod +CHOWN=/usr/bin/chown + +# +# Helper function. Handle services deathrow file. +# Arguments: $1:manifest file. +# +svc_deathrow() +{ + TEMP=/tmp/svc_deathrow.$$ + DEATHROW_FILE=${PKG_INSTALL_ROOT}/etc/svc/deathrow + # + # Services deathrow file handling, file format: + # < >< > + # (field separator is a space character) + # + if [ -s ${DEATHROW_FILE} ]; then + # + # Manifest file could be from another Solaris version, bypass + # the service bundle and validation (we only need the fmris + # list). Calling svccfg inventory with SVCCFG_NOVALIDATE=1 is + # safe because there is no access to the alternate repository. + # + ENTITIES=`SVCCFG_NOVALIDATE=1 $SVCCFG inventory $1` + for fmri in $ENTITIES; do + # + # If fmri matches one in deathrow file, remove the + # line from the file. + # + >${TEMP} + $AWK "(\$1==\"$fmri\") \ + {next}; {print}" ${DEATHROW_FILE} >>${TEMP} && \ + $MV ${TEMP} ${DEATHROW_FILE} + $RM -f ${TEMP} + done + fi +} + # # If the repository does not yet exist, create it from the appropriate seed. If # for some reason the seeds do not exist, svccfg(1M) will create the repository @@ -41,15 +81,13 @@ if [ ! -f $repfile ]; then if [ -n "$SUNW_PKG_INSTALL_ZONENAME" -a \ "$SUNW_PKG_INSTALL_ZONENAME" != "global" ]; then [ -f $PKG_INSTALL_ROOT/lib/svc/seed/nonglobal.db ] && \ - /usr/bin/cp $PKG_INSTALL_ROOT/lib/svc/seed/nonglobal.db \ - $repfile + $CP $PKG_INSTALL_ROOT/lib/svc/seed/nonglobal.db $repfile else [ -f $PKG_INSTALL_ROOT/lib/svc/seed/global.db ] && \ - /usr/bin/cp $PKG_INSTALL_ROOT/lib/svc/seed/global.db \ - $repfile + $CP $PKG_INSTALL_ROOT/lib/svc/seed/global.db $repfile fi - /usr/bin/chmod 0600 $repfile - /usr/bin/chown root:sys $repfile + $CHMOD 0600 $repfile + $CHOWN root:sys $repfile fi if [ ! -r $PKG_INSTALL_ROOT/etc/svc/volatile/repository_door ]; then @@ -59,17 +97,19 @@ if [ ! -r $PKG_INSTALL_ROOT/etc/svc/volatile/repository_door ]; then # cannot consistently handle dependent placement. Defer to next boot. # while read src dst; do - /usr/bin/cp -p $src $dst + $CP -p $src $dst + # deathrow handling + svc_deathrow $dst done else # # Local package install. # while read src dst; do - /usr/bin/cp -p $src $dst + $CP -p $src $dst [ "$PKG_INSTALL_ROOT" = "" -o "$PKG_INSTALL_ROOT" = "/" ] && \ - SVCCFG_CHECKHASH=1 /usr/sbin/svccfg import $dst + SVCCFG_CHECKHASH=1 $SVCCFG import $dst done fi diff --git a/src/lib/svc/method/zfs-auto-snapshot b/src/lib/svc/method/zfs-auto-snapshot index 0234a7d..d1af5bd 100755 --- a/src/lib/svc/method/zfs-auto-snapshot +++ b/src/lib/svc/method/zfs-auto-snapshot @@ -120,8 +120,6 @@ function schedule_snapshots { typeset FMRI=$1 zfs_smf_props $FMRI - # functions we call need $LOG set. - export LOG=$logfile # FIXME need work in here to actually validate the FMRI props typeset FILESYS="$fs_name" @@ -320,12 +318,12 @@ function check_missed_snapshots { # $INTERVAL $PERIOD $FMRI get_userprop_datasets export snapshot_children=false export fs_name="$SINGLE_LIST" - print_note "Checking for non-recursive missed // snapshots $SINGLE_LIST" + echo "Checking for non-recursive missed // snapshots $SINGLE_LIST" check_missed_snapshots $INTERVAL $PERIOD $FMRI no_repopulate_cache export snapshot_children=true export fs_name="$RECURSIVE_LIST" - print_note "Checking for recursive missed // snapshots $RECURSIVE_LIST" + echo "Checking for recursive missed // snapshots $RECURSIVE_LIST" check_missed_snapshots $INTERVAL $PERIOD $FMRI no_repopulate_cache return 0 @@ -410,13 +408,6 @@ function take_snapshot { zfs_smf_props $FMRI fi - # When taking snapshots, because we're running as a role - # and can't redirect our output through SMF, we don't have - # permissions to log to /var/svc/log, so we instead log - # to the role's home directory. - LOG_BASE=$(basename $logfile) - export LOG="$HOME/$LOG_BASE" - typeset DATE=$(date +%F-%H${SEP}%M) typeset FILESYS="$fs_name" typeset KEEP=$keep @@ -609,21 +600,24 @@ function check_failure { # integer exit status, error message to display, be fat # A function we use to emit output. Right now, this goes to syslog via logger(1) -# but it would be much nicer to be able to print it to the svc log file for -# each individual service instance - tricky because we're being called from -# cron, most of the time and are detached from smf. Working around this by -# appending to the $LOG file +# as well as being appended to a log file specified by $LOG. If this logfile +# variable doesn't exist, we simply echo the message to stdout, which will +# make it's way to the final log destination via SMF, since we'll always have +# $LOG defined when being called from cron otherwise. function print_log { # message to display logger -t zfs-auto-snap -p daemon.notice $* - echo $(date) $* >> $LOG + if [ -z "$LOG" ] ; then + echo $* + else + echo $(date) $* >> $LOG + fi } # Another function to emit output, this time checking to see if the # user has set the service into verbose mode, otherwise, we print nothing function print_note { # mesage to display if [ "$VERBOSE" == "true" ] ; then - logger -t zfs-auto-snap -p daemon.notice $* - echo $(date) $* >> $LOG + print_log $* fi } @@ -913,9 +907,11 @@ function auto_include { # created above, where the argument is the FMRI containing properties we can # consult to in order to actually take the snapshot. + +# When called via SMF, several variables are set for us - SMF_FMRI being one +# we check for the existance of that if [ -n "${SMF_FMRI}" ] ; then zfs_smf_props $SMF_FMRI - export LOG=$logfile fi # $1 start | stop | refresh | an FMRI that we want to take snapshots of. @@ -948,6 +944,10 @@ case "$1" in case $SMF_FMRI in svc:/*) + zfs_smf_props $SMF_FMRI + LOG_BASE=$(basename $logfile) + export LOG="$HOME/$LOG_BASE" + take_snapshot $SMF_FMRI if [ $? -eq 0 ] ; then result=$SMF_EXIT_OK diff --git a/src/r.manifest b/src/r.manifest index 489f786..879016a 100755 --- a/src/r.manifest +++ b/src/r.manifest @@ -3,9 +3,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -21,14 +20,86 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" # # r.manifest - smf(5) manifest remove class action script # +MFSTSCAN=/lib/svc/bin/mfstscan +SVCCFG=/usr/sbin/svccfg +SVCPROP=/usr/bin/svcprop +SVCADM=/usr/sbin/svcadm +AWK=/usr/bin/awk +CP=/usr/bin/cp +RM=/usr/bin/rm + +# number of seconds to wait before killing processes +STOP_DELAY=60 + +# +# Helper function. Delete the manifest hash value. +# Arguments: $1: manifest file. +# +svc_delhash() +{ + $SVCCFG delhash $1 >/dev/null 2>&1 + if [ "$?" != "0" ];then + # this Solaris release doesn't have delhash command + pg_name=`$MFSTSCAN -t $1` + if $SVCPROP -q -p $pg_name smf/manifest; then + $SVCCFG -s smf/manifest delpg $pg_name + fi + fi +} + +# +# Helper function. Handle services deathrow file. +# Arguments: $1:manifest file, $2:package name. +# +svc_deathrow() +{ + DEATHROW_FILE=${PKG_INSTALL_ROOT}/etc/svc/deathrow + # remove alternate root from manifest path + manifest=`echo "${PKG_INSTALL_ROOT} $1" | $AWK \ + '{ print substr($2, length($1)+1); }'` + # + # Services deathrow file handling, file format: + # < >< > + # (field separator is a space character) + # + # Manifest file could be from another Solaris version, bypass the + # the service bundle and validation (we only need the fmris list). + # Calling svccfg inventory with SVCCFG_NOVALIDATE=1 is safe because + # there is no access to the alternate repository. + # + ENTITIES=`SVCCFG_NOVALIDATE=1 $SVCCFG inventory $1` + for fmri in $ENTITIES; do + # add to services deathrow file + echo ${fmri} ${manifest} $2 >> ${DEATHROW_FILE} + done +} + +wait_disable() { + svcinst=$1 + wait_time=$2 + + while [ ${nsec:=0} -lt $wait_time ]; do + state=`$SVCPROP -p restarter/state $svcinst` + if [ "$state" = "disabled" -o "$state" = "maintenance" ]; then + nstate=`$SVCPROP -p restarter/next_state $svcinst` + if [ "$nstate" = "none" ]; then + return 0 + fi + fi + /usr/bin/sleep 1 + nsec=`expr ${nsec} + 1` + done + + return 1 +} + if [ "$PKG_INSTALL_ROOT" != "" -a "$PKG_INSTALL_ROOT" != "/" ]; then # # We can't safely disable the service in this case. @@ -44,40 +115,72 @@ else fi fi -MFSTSCAN=/lib/svc/bin/mfstscan -SVCCFG=/usr/sbin/svccfg -SVCPROP=/usr/bin/svcprop - while read mfst; do if [ "$smf_alive" = "yes" ]; then ENTITIES=`$SVCCFG inventory $mfst` for fmri in $ENTITIES; do - # - # Determine whether any of our instances are - # enabled. - # - en_p=`$SVCPROP -C -p general/enabled $fmri 2>/dev/null` - en_o=`$SVCPROP -C -p general_ovr/enabled $fmri 2>/dev/null` - if [ "$en_p" = "true" -o "$en_o" = "true" ]; then - echo "$fmri remains enabled; aborting" - exit 1 + # Determine whether fmri refers to an instance or a service. + $SVCPROP -p restarter/state $fmri >/dev/null 2>&1 + if [ $? -eq 1 ]; then + # this is a service fmri, all instances have been deleted + $SVCCFG delete $fmri 2>/dev/null + # process next instance + continue fi - $SVCCFG delete $fmri + # + # Try to disable the instance within a reasonable amount of time + # (eg. 60 secs). If it fails, forcibly delete the instance. + # + echo "Waiting up to $STOP_DELAY seconds for $fmri to stop..." + $SVCADM disable $fmri 2>/dev/null + if [ $? -eq 0 ]; then + wait_disable $fmri $STOP_DELAY + if [ $? -eq 0 ]; then + # the instance is disabled and can be safely deleted + $SVCCFG delete $fmri 2>/dev/null + # process next instance + continue + fi + echo "Failed to disable $fmri after $STOP_DELAY seconds" + else + echo "Failed to disable $fmri" + fi + + echo "Force deleting $fmri" + + ctid=`$SVCPROP -p restarter/contract $fmri 2>/dev/null` + tctid=`$SVCPROP -p restarter/transient_contract $fmri 2>/dev/null` + + $SVCCFG delete -f $fmri + + # + # Kill any remaining processes. + # pkill must occur after the delete to prevent startd + # from retrying the STOP method. + # + if [ -n "${tctid}" -a "${tctid}" -gt 1 ]; then + # kill the STOP method processes + /usr/bin/pkill -9 -c $tctid + fi + if [ -n "${ctid}" -a "${ctid}" -gt 1 ]; then + # kill any remaining running processes for the instance + /usr/bin/pkill -9 -c $ctid + fi done # # Delete the manifest hash value. # - pg_name=`$MFSTSCAN -t $mfst` - if $SVCPROP -q -p $pg_name smf/manifest; then - $SVCCFG -s smf/manifest delpg $pg_name - fi + svc_delhash $mfst + else + # deathrow handling + svc_deathrow $mfst $PKGINST fi - /usr/bin/rm $mfst + $RM -f $mfst done exit 0