5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
29 from time_slider import util, smf, zfs
31 # Set to True if SMF property value of "plugin/command" is "true"
32 verboseprop = "plugin/verbose"
33 propbasename = "org.opensolaris:time-slider-plugin"
37 # Check that appropriate environment variables have been
38 # provided by time-sliderd
40 # The label used for the snapshot set just taken, ie. the
41 # component proceeding the "@" in the snapshot name
42 snaplabel = os.getenv("AUTOSNAP_LABEL")
43 # The SMF fmri of the auto-snapshot instance corresponding to
44 # the snapshot set just taken.
45 snapfmri = os.getenv("AUTOSNAP_FMRI")
46 # The SMF fmri of the time-slider plugin instance associated with
48 pluginfmri = os.getenv("PLUGIN_FMRI")
50 if pluginfmri == None:
51 sys.stderr.write("No time-slider plugin SMF instance FMRI defined. " \
52 "This plugin does not support command line "
53 "execution. Exiting\n")
55 syslog.openlog(pluginfmri, 0, syslog.LOG_DAEMON)
57 cmd = [smf.SVCPROPCMD, "-p", verboseprop, pluginfmri]
58 outdata,errdata = util.run_command(cmd)
59 if outdata.rstrip() == "true":
65 log_error(syslog.LOG_ERR,
66 "No snapshot label provided. Exiting")
69 log_error(syslog.LOG_ERR,
70 "No auto-snapshot SMF instance FMRI provided. Exiting")
73 schedule = snapfmri.rsplit(':', 1)[1]
74 plugininstance = pluginfmri.rsplit(':', 1)[1]
76 # The user property/tag used when tagging and holding zfs datasets
77 propname = "%s:%s" % (propbasename, plugininstance)
79 # Identifying snapshots is a 3 stage process.
81 # First: identify all snapshots matching the AUTOSNAP_LABEL
82 # value passed in by the time-slider daemon.
84 # Second: Filter out snapshots of volumes, since rsync can only
85 # back up filesystems.
87 # Third: we need to filter the results and ensure that the
88 # filesystem corresponding to each snapshot is actually
89 # tagged with the property (com.sun:auto-snapshot<:schedule>)
91 # This is necessary to avoid confusion whereby a snapshot might
92 # have been sent|received from one zpool to another on the same
93 # system. The received snapshot will show up in the first pass
94 # results but is not actually part of the auto-snapshot set
95 # created by time-slider. It also avoids incorrectly placing
96 # zfs holds on the imported snapshots.
99 datasets = zfs.Datasets()
100 candidates = datasets.list_snapshots(snaplabel)
101 autosnapsets = datasets.list_auto_snapshot_sets(schedule)
102 autosnapfs = [name for [name,mount] in datasets.list_filesystems() \
103 if name in autosnapsets]
105 snapnames = [name for [name,ctime] in candidates \
106 if name.split('@',1)[0] in autosnapfs]
108 # Mark the snapshots with a user property. Doing this instead of
109 # placing a physical hold on the snapshot allows time-slider to
110 # expire the snapshots naturally or destroy them if a zpool fills
111 # up and triggers a remedial cleanup.
112 # It also prevents the possiblity of leaving snapshots lying around
113 # indefinitely on the system if the plugin SMF instance becomes
114 # disabled or having to release a pile of held snapshots.
115 # We set org.opensolaris:time-slider-plugin:<instance> to "pending",
118 for snap in snapnames:
119 snapshot = zfs.Snapshot(snap)
120 fs = zfs.Filesystem(snapshot.fsname)
121 if fs.get_user_property(rsyncsmf.RSYNCFSTAG) == "true":
122 if fs.is_mounted() == True:
123 snapshot.set_user_property(propname, "pending")
124 util.debug("Marking %s as pending rsync" % (snap), verbose)
126 util.debug("Ignoring snapshot of unmounted fileystem: %s" \
129 def maintenance(svcfmri):
130 log_error(syslog.LOG_ERR,
131 "Placing plugin into maintenance state")
132 cmd = [smf.SVCADMCMD, "mark", "maintenance", svcfmri]
133 subprocess.Popen(cmd, close_fds=True)
135 def log_error(loglevel, message):
136 syslog.syslog(loglevel, message + '\n')
137 sys.stderr.write(message + '\n')