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]
27 factoryDefaultSchedules = ("monthly", "weekly", "daily", "hourly", "frequent")
29 BASESVC= "svc:/system/filesystem/zfs/auto-snapshot"
30 SNAPLABELPREFIX = "zfs-auto-snap"
34 # Bombarding the class with schedule queries causes the occasional
35 # OSError exception due to interrupted system calls.
36 # Serialising them helps prevent this unlikely event from occuring.
37 _scheddetaillock = threading.RLock()
39 class AutoSnap(smf.SMFInstance):
41 def __init__(self, schedule):
42 smf.SMFInstance.__init__(self, "%s:%s" % (BASESVC, schedule))
43 self.schedule = schedule
45 def get_schedule_details(self):
46 svc= "%s:%s" % (BASESVC, self.schedule)
47 _scheddetaillock.acquire()
49 interval = self.get_prop(ZFSPROPGROUP, "interval")
50 period = int(self.get_prop(ZFSPROPGROUP, "period"))
51 keep = int(self.get_prop(ZFSPROPGROUP, "keep"))
53 except OSError, message:
54 raise RuntimeError, "%s subprocess error:\n %s" % \
57 _scheddetaillock.release()
59 return [self.schedule, interval, period, keep]
61 # FIXME - merge with enable_default_schedules()
62 def disable_default_schedules():
64 Disables the default auto-snapshot SMF instances corresponding
65 to: "frequent", "hourly", "daily", "weekly" and "monthly"
67 Raises RuntimeError exception if unsuccessful
70 for s in factoryDefaultSchedules:
71 # Acquire the scheddetail lock since their status will
72 # likely be changed as a result of enabling the instances.
73 _scheddetaillock.acquire()
74 instanceName = "%s:%s" % (BASESVC,s)
75 svc = smf.SMFInstance(instanceName)
77 _scheddetaillock.release()
79 def enable_default_schedules():
81 Enables the default auto-snapshot SMF instances corresponding
82 to: "frequent", "hourly", "daily", "weekly" and "monthly"
84 Raises RuntimeError exception if unsuccessful
86 for s in factoryDefaultSchedules:
87 # Acquire the scheddetail lock since their status will
88 # likely be changed as a result of enabling the instances.
89 _scheddetaillock.acquire()
90 instanceName = "%s:%s" % (BASESVC,s)
91 svc = smf.SMFInstance(instanceName)
93 _scheddetaillock.release()
95 def get_default_schedules():
97 Finds the default schedules that are enabled (online, offline or degraded)
99 #This is not the fastest method but it is the safest, we need
100 #to ensure that default schedules are processed in the pre-defined
101 #order to ensure that the overlap between them is adhered to
102 #correctly. monthly->weekly->daily->hourly->frequent. They have
103 #to be processed first and they HAVE to be in the correct order.
104 _defaultSchedules = []
105 for s in factoryDefaultSchedules:
106 instanceName = "%s:%s" % (BASESVC,s)
107 cmd = [smf.SVCSCMD, "-H", "-o", "state", instanceName]
108 _scheddetaillock.acquire()
110 outdata,errdata = util.run_command(cmd)
112 _scheddetaillock.release()
113 result = outdata.rstrip()
114 # Note that the schedules, being dependent on the time-slider service
115 # itself will typically be in an offline state when enabled. They will
116 # transition to an "online" state once time-slider itself comes
117 # "online" to satisfy it's dependency
118 if result == "online" or result == "offline" or result == "degraded":
119 instance = AutoSnap(s)
121 _defaultSchedules.append(instance.get_schedule_details())
122 except RuntimeError, message:
123 raise RuntimeError, "Error getting schedule details for " + \
124 "default auto-snapshot SMF instance:" + \
125 "\n\t" + instanceName + "\nDetails:\n" + \
127 return _defaultSchedules
129 def get_custom_schedules():
131 Finds custom schedules ie. not the factory default
132 'monthly', 'weekly', 'hourly', 'daily' and 'frequent' schedules
134 _customSchedules = []
135 cmd = [smf.SVCSCMD, "-H", "-o", "state,FMRI", BASESVC]
136 _scheddetaillock.acquire()
138 outdata,errdata = util.run_command(cmd)
140 _scheddetaillock.release()
142 for line in outdata.rstrip().split('\n'):
143 line = line.rstrip().split()
146 fmri = fmri.rsplit(":", 1)
148 if label not in factoryDefaultSchedules:
149 # Note that the schedules, being dependent on the time-slider service
150 # itself will typically be in an offline state when enabled. They will
151 # transition to an "online" state once time-slider itself comes
152 # "online" to satisfy it's dependency
153 if state == "online" or state == "offline" or state == "degraded":
154 instance = AutoSnap(label)
156 _customSchedules.append(instance.get_schedule_details())
157 except RuntimeError, message:
158 raise RuntimeError, "Error getting schedule details " + \
159 "for custom auto-snapshot SMF " + \
160 "instance:\n\t" + label + "\n" + \
161 "Details:\n" + str(message)
162 return _customSchedules
165 if __name__ == "__main__":
166 defaults = get_default_schedules()
167 for sched in defaults:
168 S = AutoSnap(sched[0])
169 print S.get_schedule_details()