Add RBAC support and a Changelog

This commit is contained in:
Tim Foster 2008-08-22 13:59:25 +01:00
parent d0716c29fa
commit 5d95fb20bd
12 changed files with 428 additions and 67 deletions

81
Changelog Normal file
View File

@ -0,0 +1,81 @@
0.11
* Add RBAC support
- the service now runs under a zfssnap role
- service start/stop logs stay under /var/svc/log
- other logs saved to /export/home/zfssnap (and syslog)
* Add a 'zfs/interval' property value 'none' which doesn't use cron
* Add a 'zfs/fs-name' property value '##'
* Add a cache of svcprops to the method script
* Add a com.sun:auto-snapshot user property, com.sun:auto-snapshot:$LABEL
takes precedence
* Remove the seconds field of the snapshot name - we don't really need it
* Make recursive snapshots the default for bundled '//' manifests
* Changed the way // works with recursive snapshots
(look for local props only when using -r)
* Set avoidscrub to false by default (bug was fixed in in nv_94)
* Bugfix from Dan - Volumes are datasets too
* Automatically snapshot everything by setting com.sun:auto-snapshot=true
on startup. (this gets done on all root pools - existing properties set
to false will override this)
* Check for missed snapshots on startup
* Clean up shell style
* Clean up preremove script
* Write this Changelog
0.10
* Bugfix from Reid Spencer - Tim can't spell "RECURSIVE" (hah, I can now!:-)
* Bugfix from Breandan Dezendorf - Labelled snapshots not being destroyed correctly
* Ability to avoid taking snapshots when pool scrubs are in progress
0.9
* SVR4 packaging (with ugly postinstall/preremove scripts)
* Add some canned instances for frequent,daily,hourly,weekly,monthly snapshots
* Add 'zfs/fs-name' '//' property value
* Change the timeout for the start/stop methods to infinity
* Allow power users to avoid having ':' in snapshot names via $SEP
* Add GUI utilities and some basic GNOME integration
0.8
* Bugfix from Dick Davies - fencepost error in crontab entries
* Add locking around crontab updates
* Add zfs/verbose feature for more logging if you really need it
0.7
* Bugfix from Bill Sommerfeld - make less logging noise
* Add logging to syslog
0.6
* Option to take backups using zfs send after snapshots are taken
* Allow us to have multiple schedules per filesystem (add labels)
* Better fault handling - drop SMF instance to 'maintenance' if stuff goes wrong
0.5
* Bugfix from Joe Little - recursive snapshots weren't respecting retention limits
0.4
* Make zenity gui work on s10u2
* Clean up the logic that the gui uses to name different instances
0.3
* Add snapshot retention limits
0.2
* Fix the gui to show a different string when changing the interval
* Fix a bug where seperate instances were removing each other's cron jobs
0.1
* Take periodic snapshots using cron and SMF
* Snapshot children
* Add zenity gui to create SMF manifests

View File

@ -27,7 +27,7 @@ GUI is documented as part of the installation instructions below.
INSTALLATION INSTALLATION
To install, as root, pkgadd TIMFauto-snapshot. This package now contains To install, as root, pkgadd TIMFauto-snapshot. This package now contains
several canned SMF instances which are enabled by default. These are: several canned SMF instances. These are:
online 1:17:43 svc:/system/filesystem/zfs/auto-snapshot:hourly online 1:17:43 svc:/system/filesystem/zfs/auto-snapshot:hourly
online 1:17:46 svc:/system/filesystem/zfs/auto-snapshot:monthly online 1:17:46 svc:/system/filesystem/zfs/auto-snapshot:monthly
@ -149,10 +149,13 @@ you can now import the manifest for this instance, using the command :
then issue the command : then issue the command :
# svcadm enable svc:/system/filesystem/zfs/auto-snapshot:tank-root_filesystem # svcadm enable svc:/system/filesystem/zfs/auto-snapshot:tank-root_filesystem
You can see what work will be done by checking your crontab. As of version
0.7, all logging from the service is done from the method script using The service is run by a restricted role "zfssnap", which is created when installing
the print_log function, which uses logger(1) to send message to syslogd(1M) the service. It has the "ZFS File System Administration" RBAC Profile, as well
at priority level "daemon.notice". as the solaris.smf.manage.zfs-auto-snapshot Authorization. In order to see what
the service is doing, you can view the SMF log files in /var/svc/log for each
service instance and syslog, with more detailed logging output being sent to
the log files in the zfssnap role's home directory. (/export/home/zfssnap, by default)
SEE ALSO SEE ALSO

76
src/i.manifest Executable file
View File

@ -0,0 +1,76 @@
#!/bin/sh
#
# 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.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# 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
#
#
# Copyright 2004 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
#
# 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
# automatically.
#
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
else
[ -f $PKG_INSTALL_ROOT/lib/svc/seed/global.db ] && \
/usr/bin/cp $PKG_INSTALL_ROOT/lib/svc/seed/global.db \
$repfile
fi
/usr/bin/chmod 0600 $repfile
/usr/bin/chown root:sys $repfile
fi
if [ ! -r $PKG_INSTALL_ROOT/etc/svc/volatile/repository_door ]; then
#
# smf(5) is not presently running for the destination environment.
# Since we presently cannot refresh without a running svc.startd(1M), we
# cannot consistently handle dependent placement. Defer to next boot.
#
while read src dst; do
/usr/bin/cp -p $src $dst
done
else
#
# Local package install.
#
while read src dst; do
/usr/bin/cp -p $src $dst
[ "$PKG_INSTALL_ROOT" = "" -o "$PKG_INSTALL_ROOT" = "/" ] && \
SVCCFG_CHECKHASH=1 /usr/sbin/svccfg import $dst
done
fi
exit 0

View File

@ -52,6 +52,7 @@
result=$SMF_EXIT_OK result=$SMF_EXIT_OK
export PATH=/usr/sbin:/usr/bin:${PATH}
# A prefix we use on all snapshot created by this script. # A prefix we use on all snapshot created by this script.
# See the definition of $SNAPNAME in the take_snapshot() # See the definition of $SNAPNAME in the take_snapshot()
@ -76,6 +77,9 @@ LOG=""
# a null string in this variable says we don't. # a null string in this variable says we don't.
HAS_RECURSIVE=$(zfs snapshot 2>&1 | fgrep -e '-r') HAS_RECURSIVE=$(zfs snapshot 2>&1 | fgrep -e '-r')
# OpenSolaris has no pfksh, so for now, we need to pfexec
# all calls to zfs that require privileges
PFZFS="pfexec zfs"
function get_pair { function get_pair {
NAME=$1 NAME=$1
@ -95,7 +99,7 @@ SMF_PROPS="$(svcprop -t -p zfs -p restarter/logfile $1 |\
-e 's#zfs/backup-lock#zfs/backup_lock#g' \ -e 's#zfs/backup-lock#zfs/backup_lock#g' \
-e 's#zfs/snapshot-children#zfs/snapshot_children#g' \ -e 's#zfs/snapshot-children#zfs/snapshot_children#g' \
-e 's#zfs/backup-save-cmd#zfs/backup_save_cmd#g' \ -e 's#zfs/backup-save-cmd#zfs/backup_save_cmd#g' \
-e 's#zfs/##g' -e 's/$/,/g')" -e 's#zfs/##g' -e 's#restarter/##g' -e 's/$/,/g')"
IFS=, IFS=,
for line in $SMF_PROPS ; do for line in $SMF_PROPS ; do
IFS=' IFS='
@ -377,7 +381,13 @@ function take_snapshot {
FMRI=$1 FMRI=$1
zfs_smf_props $FMRI zfs_smf_props $FMRI
export LOG=$logfile # 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 DATE=$(date +%F-%H${SEP}%M)
typeset FILESYS="$fs_name" typeset FILESYS="$fs_name"
typeset KEEP=$keep typeset KEEP=$keep
@ -466,20 +476,20 @@ function take_snapshot {
for child in $(zfs list -r -H -o name -t filesystem,volume $fs) ; do for child in $(zfs list -r -H -o name -t filesystem,volume $fs) ; do
destroy_older_snapshots $child $KEEP $LABEL destroy_older_snapshots $child $KEEP $LABEL
print_note "Taking snapshot $child@$SNAPNAME" print_note "Taking snapshot $child@$SNAPNAME"
zfs snapshot $child@$SNAPNAME $PFZFS snapshot $child@$SNAPNAME
check_failure $? "Unable to take snapshot $child@$SNAPNAME." check_failure $? "Unable to take snapshot $child@$SNAPNAME."
done done
else else
destroy_older_snapshots $fs $KEEP $LABEL $HAS_RECURSIVE destroy_older_snapshots $fs $KEEP $LABEL $HAS_RECURSIVE
print_note "Taking recursive snapshot $fs@$SNAPNAME" print_note "Taking recursive snapshot $fs@$SNAPNAME"
zfs snapshot -r $fs@$SNAPNAME $PFZFS snapshot -r $fs@$SNAPNAME
check_failure $? "Unable to take recursive snapshots of $fs@$SNAPNAME." check_failure $? "Unable to take recursive snapshots of $fs@$SNAPNAME."
fi fi
else else
destroy_older_snapshots $fs $KEEP $LABEL destroy_older_snapshots $fs $KEEP $LABEL
print_note "Taking snapshot $fs@$SNAPNAME" print_note "Taking snapshot $fs@$SNAPNAME"
zfs snapshot $fs@$SNAPNAME $PFZFS snapshot $fs@$SNAPNAME
check_failure $? "Unable to take snapshot $fs@$SNAPNAME." check_failure $? "Unable to take snapshot $fs@$SNAPNAME."
fi fi
@ -532,7 +542,7 @@ function destroy_older_snapshots {
# using print_note, as this checks our $VERBOSE flag # using print_note, as this checks our $VERBOSE flag
print_note "$snapshot being destroyed ${RECURSIVE} as per \ print_note "$snapshot being destroyed ${RECURSIVE} as per \
retention policy." retention policy."
zfs destroy ${RECURSIVE} $snapshot $PFZFS destroy ${RECURSIVE} $snapshot
check_failure $? "Unable to destroy $snapshot" "NON_FATAL" check_failure $? "Unable to destroy $snapshot" "NON_FATAL"
else else
# don't destroy this one # don't destroy this one
@ -697,12 +707,12 @@ function take_backup { # filesystem backup-type label fmri
case $BACKUP in case $BACKUP in
"incremental") "incremental")
print_note "Starting incr. ZFS send of differences between $PREV_SNAP and $LAST_SNAP." print_note "Starting incr. ZFS send of differences between $PREV_SNAP and $LAST_SNAP."
zfs send -i $PREV_SNAP $LAST_SNAP | $BACKUP_SAVE_CMD $PFZFS send -i $PREV_SNAP $LAST_SNAP | $BACKUP_SAVE_CMD
check_failure $? "Error performing incremental backup of $dataset." check_failure $? "Error performing incremental backup of $dataset."
;; ;;
"full") "full")
print_note "Starting ZFS send of $LAST_SNAP." print_note "Starting ZFS send of $LAST_SNAP."
zfs send $LAST_SNAP | $BACKUP_SAVE_CMD $PFZFS send $LAST_SNAP | $BACKUP_SAVE_CMD
check_failure $? "Error performing full backup of $dataset." check_failure $? "Error performing full backup of $dataset."
;; ;;
esac esac
@ -826,7 +836,7 @@ function auto_include {
*false | false*) *false | false*)
;; ;;
*) *)
zfs set com.sun:auto-snapshot=true $pool $PFZFS set com.sun:auto-snapshot=true $pool
;; ;;
esac esac
fi fi

View File

@ -25,6 +25,58 @@
# Use is subject to license terms. # Use is subject to license terms.
# #
# a postinstall script - it should import the manifests # a postinstall script - adds zfssnap role.
# and enable the service # Return 0 if a user exists, 1 otherwise.
echo "Post install script doing nathing!" #
# Check if the first argument is 0, settting our return
# variable to an error otherwise
#
function check_error {
RETURN_CODE=$1
ERROR="$2"
if [ "$RETURN_CODE" -ne 0 ] ; then
echo "ERROR: $ERROR"
fi
}
function user_exists {
typeset USER=$1
if /usr/bin/grep ^$USER: $BASEDIR/etc/passwd > /dev/null ; then
return 0
else
return 1
fi
}
function auth_exists {
typeset AUTH=$1
if /usr/bin/grep ^$AUTH: $BASEDIR/etc/security/auth_attr > /dev/null ; then
return 0
else
return 1
fi
}
# add our authorization
if ! auth_exists solaris.smf.manage.zfs-auto-snapshot; then
echo "solaris.smf.manage.zfs-auto-snapshot:::Manage the ZFS Automatic Snapshot Service::" \
>> /etc/security/auth_attr
fi
# add the zfssnap role - probably only works on a local system :-(
if ! user_exists zfssnap; then
/usr/sbin/roleadd -d /export/home/zfssnap -c "ZFS Automatic Snapshots role" \
-P "ZFS File System Management" \
-A solaris.smf.manage.zfs-auto-snapshot -m zfssnap
check_error $? "Unable to create zfssnap role!"
/usr/bin/passwd -r files -N zfssnap
check_error $? "Unable to make zfssnap a no-password account"
# make sure their path has /usr/sbin in it
echo "PATH=/usr/sbin:\${PATH}" >> /export/home/zfssnap/.profile
echo "export PATH" >> /export/home/zfssnap/.profile
else
echo "zfssnap role already exists."
fi

83
src/r.manifest Executable file
View File

@ -0,0 +1,83 @@
#!/bin/sh
#
# 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.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# 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
#
#
# Copyright 2005 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
#
if [ "$PKG_INSTALL_ROOT" != "" -a "$PKG_INSTALL_ROOT" != "/" ]; then
#
# We can't safely disable the service in this case.
#
smf_alive=no
else
#
# We can verify if the service is disabled prior to
# removal.
#
if [ -r /etc/svc/volatile/repository_door ]; then
smf_alive=yes
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
fi
$SVCCFG delete $fmri
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
fi
/usr/bin/rm $mfst
done
exit 0

View File

@ -21,13 +21,21 @@ snapshots into the past.
type='method' type='method'
name='start' name='start'
exec='/lib/svc/method/zfs-auto-snapshot start' exec='/lib/svc/method/zfs-auto-snapshot start'
timeout_seconds='0' /> timeout_seconds='0'>
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<exec_method <exec_method
type='method' type='method'
name='stop' name='stop'
exec='/lib/svc/method/zfs-auto-snapshot stop' exec='/lib/svc/method/zfs-auto-snapshot stop'
timeout_seconds='0' /> timeout_seconds='0' >
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<property_group name='startd' type='framework'> <property_group name='startd' type='framework'>
<propval name='duration' type='astring' value='transient' /> <propval name='duration' type='astring' value='transient' />

View File

@ -17,19 +17,27 @@ com.sun:auto-snapshot:frequent=true every
<instance name='frequent' enabled='false' > <instance name='frequent' enabled='false' >
<exec_method
type='method'
name='start'
exec='/lib/svc/method/zfs-auto-snapshot start'
timeout_seconds='0'>
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<exec_method <exec_method
type='method' type='method'
name='start' name='stop'
exec='/lib/svc/method/zfs-auto-snapshot start' exec='/lib/svc/method/zfs-auto-snapshot stop'
timeout_seconds='0' /> timeout_seconds='0' >
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<exec_method <property_group name='startd' type='framework'>
type='method'
name='stop'
exec='/lib/svc/method/zfs-auto-snapshot stop'
timeout_seconds='0' />
<property_group name='startd' type='framework'>
<propval name='duration' type='astring' value='transient' /> <propval name='duration' type='astring' value='transient' />
</property_group> </property_group>

View File

@ -18,16 +18,24 @@ and keeps 24 of these snapshots into the past.
<instance name='hourly' enabled='false' > <instance name='hourly' enabled='false' >
<exec_method <exec_method
type='method' type='method'
name='start' name='start'
exec='/lib/svc/method/zfs-auto-snapshot start' exec='/lib/svc/method/zfs-auto-snapshot start'
timeout_seconds='0' /> timeout_seconds='0'>
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<exec_method <exec_method
type='method' type='method'
name='stop' name='stop'
exec='/lib/svc/method/zfs-auto-snapshot stop' exec='/lib/svc/method/zfs-auto-snapshot stop'
timeout_seconds='0' /> timeout_seconds='0' >
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<property_group name='startd' type='framework'> <property_group name='startd' type='framework'>
<propval name='duration' type='astring' value='transient' /> <propval name='duration' type='astring' value='transient' />

View File

@ -18,16 +18,24 @@ and keeps 12 of these snapshots into the past.
<instance name='monthly' enabled='false' > <instance name='monthly' enabled='false' >
<exec_method <exec_method
type='method' type='method'
name='start' name='start'
exec='/lib/svc/method/zfs-auto-snapshot start' exec='/lib/svc/method/zfs-auto-snapshot start'
timeout_seconds='0' /> timeout_seconds='0'>
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<exec_method <exec_method
type='method' type='method'
name='stop' name='stop'
exec='/lib/svc/method/zfs-auto-snapshot stop' exec='/lib/svc/method/zfs-auto-snapshot stop'
timeout_seconds='0' /> timeout_seconds='0' >
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<property_group name='startd' type='framework'> <property_group name='startd' type='framework'>
<propval name='duration' type='astring' value='transient' /> <propval name='duration' type='astring' value='transient' />

View File

@ -18,16 +18,24 @@ and keeps 4 of these snapshots into the past.
<instance name='weekly' enabled='false' > <instance name='weekly' enabled='false' >
<exec_method <exec_method
type='method' type='method'
name='start' name='start'
exec='/lib/svc/method/zfs-auto-snapshot start' exec='/lib/svc/method/zfs-auto-snapshot start'
timeout_seconds='0' /> timeout_seconds='0'>
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<exec_method <exec_method
type='method' type='method'
name='stop' name='stop'
exec='/lib/svc/method/zfs-auto-snapshot stop' exec='/lib/svc/method/zfs-auto-snapshot stop'
timeout_seconds='0' /> timeout_seconds='0' >
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<property_group name='startd' type='framework'> <property_group name='startd' type='framework'>
<propval name='duration' type='astring' value='transient' /> <propval name='duration' type='astring' value='transient' />

View File

@ -56,6 +56,14 @@
<propval name='duration' type='astring' value='transient' /> <propval name='duration' type='astring' value='transient' />
</property_group> </property_group>
<property_group name='general' type='framework'>
<propval name='action_authorization' type='astring'
value='solaris.smf.manage.zfs-auto-snapshot' />
<propval name='value_authorization' type='astring'
value='solaris.smf.manage.zfs-auto-snapshot' />
</property_group>
<!-- the properties we expect that any instance will define <!-- the properties we expect that any instance will define
they being : they being :
fs-name : The name of the filesystem we want to snapshot. fs-name : The name of the filesystem we want to snapshot.
@ -159,16 +167,24 @@ they being :
sec. timeout. sec. timeout.
<exec_method <exec_method
type='method' type='method'
name='start' name='start'
exec='/home/timf/zfs-auto-snapshot %m' exec='/lib/svc/method/zfs-auto-snapshot start'
timeout_seconds='0' /> timeout_seconds='0'>
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<exec_method <exec_method
type='method' type='method'
name='stop' name='stop'
exec='/home/timf/zfs-auto-snapshot %m' exec='/lib/svc/method/zfs-auto-snapshot stop'
timeout_seconds='0' /> timeout_seconds='0' >
<method_context>
<method_credential user='zfssnap' group='staff' />
</method_context>
</exec_method>
<property_group name='startd' type='framework'> <property_group name='startd' type='framework'>
<propval name='duration' type='astring' value='transient' /> <propval name='duration' type='astring' value='transient' />
@ -192,7 +208,7 @@ they being :
<propval name="verbose" type="boolean" value="false" override="true"/> <propval name="verbose" type="boolean" value="false" override="true"/>
<propval name="avoidscrub" type="boolean" value="true" override="true"/> <propval name="avoidscrub" type="boolean" value="false" override="true"/>
</property_group> </property_group>