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]
37 gtk.gdk.threads_init()
46 # here we define the path constants so that other modules can use it.
47 # this allows us to get access to the shared files without having to
48 # know the actual location, we just use the location of the current
49 # file and use paths relative to that.
50 SHARED_FILES = os.path.abspath(os.path.join(os.path.dirname(__file__),
53 LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
54 RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
56 # the name of the gettext domain. because we have our translation files
57 # not in a global folder this doesn't really matter, setting it to the
58 # application name is a good idea tough.
59 GETTEXT_DOMAIN = 'time-slider'
61 # set up the glade gettext system and locales
62 gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
63 gtk.glade.textdomain(GETTEXT_DOMAIN)
66 from .rbac import RBACprofile
68 class SnapshotNowDialog:
70 def __init__(self, dir_path, zfs_fs):
71 self.dir_path = dir_path
73 self.xml = gtk.glade.XML("%s/../../glade/time-slider-snapshot.glade" \
74 % (os.path.dirname(__file__)))
75 self.dialog = self.xml.get_widget("dialog")
76 self.dir_label = self.xml.get_widget("dir_label")
77 self.snap_name_entry = self.xml.get_widget("snapshot_name_entry")
79 dic = {"on_closebutton_clicked" : gtk.main_quit,
80 "on_window_delete_event" : gtk.main_quit,
81 "on_cancel_clicked" : gtk.main_quit,
82 "on_ok_clicked" : self.__on_ok_clicked}
83 self.xml.signal_autoconnect(dic)
85 self.snap_name_entry.connect("activate", self.__on_entry_activate, 0)
87 self.dir_label.set_text(self.dir_path)
88 self.snap_name_entry.set_text("my-snapshot-%s" % datetime.datetime.now().strftime("%Y-%m-%d_%Hh%M:%S"))
92 def validate_name (self, name, showErrorDialog=False):
94 # from http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/common/zfs/zfs_namecheck.c#dataset_namecheck
95 # http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/common/zfs/zfs_namecheck.c#valid_char
98 _validchars = string.ascii_letters + string.digits + \
100 _allchars = string.maketrans("", "")
101 _invalidchars = _allchars.translate(_allchars, _validchars)
106 if c not in _invalidchars:
107 valid_name = valid_name + c
111 if invalid and showErrorDialog:
112 dialog = gtk.MessageDialog(None,
116 _("Invalid characters in snapshot name"))
117 dialog.set_title (_("Error"))
118 dialog.format_secondary_text(_("Allowed characters for snapshot names are :\n"
119 "[a-z][A-Z][0-9][-_.:\n"
120 "All invalid characters will be removed\n"))
126 def __on_entry_activate (self, widget, none):
127 self.snap_name_entry.set_text (self.validate_name (self.snap_name_entry.get_text(), True))
131 def __on_ok_clicked (self, widget):
132 name = self.snap_name_entry.get_text()
133 valid_name = self.validate_name (name, True)
134 if name == valid_name:
135 cmd = "/usr/sbin/zfs snapshot %s@%s" % (self.zfs_fs, self.validate_name (self.snap_name_entry.get_text()))
136 fin,fout,ferr = os.popen3(cmd)
137 # Check for any error output generated and
138 # return it to caller if so.
142 dialog = gtk.MessageDialog(None,
146 _("Error occured while creating the snapshot"))
147 dialog.set_title (_("Error"))
148 dialog.format_secondary_text(error)
151 dialog = gtk.MessageDialog(None,
155 _("Snapshot created successfully"))
156 dialog.set_title (_("Success"))
157 dialog.format_secondary_text(_("A snapshot of zfs filesystem %(zfs_fs)s\n"
158 "named %(valid_name)s\n"
159 "has been created.\n") %
160 { "zfs_fs" : self.zfs_fs, "valid_name" : valid_name})
165 self.snap_name_entry.set_text (valid_name)
169 opts,args = getopt.getopt(sys.argv[1:], "", [])
170 except getopt.GetoptError:
173 #check for 2 args here we assume the arguments are correct
175 dialog = gtk.MessageDialog(None,
179 _("Invalid arguments count."))
180 dialog.set_title (_("Error"))
181 dialog.format_secondary_text(_("Snapshot Now requires"
182 " 2 arguments :\n- The path of the "
183 "directory to be snapshotted.\n"
184 "- The zfs filesystem corresponding "
185 "to this directory."))
189 rbacp = RBACprofile()
190 # The user security attributes checked are the following:
191 # 1. The "Primary Administrator" role
192 # 4. The "ZFS Files System Management" profile.
194 # Valid combinations of the above are:
196 # Note that an effective UID=0 will match any profile search so
197 # no need to check it explicitly.
198 if rbacp.has_profile("ZFS File System Management"):
199 manager = SnapshotNowDialog(args[0],args[1])
201 elif os.path.exists(argv) and os.path.exists("/usr/bin/gksu"):
202 # Run via gksu, which will prompt for the root password
203 newargs = ["gksu", argv]
206 os.execv("/usr/bin/gksu", newargs)
207 # Shouldn't reach this point
210 dialog = gtk.MessageDialog(None,
214 _("Insufficient Priviliges"))
215 dialog.set_title (_("Error"))
216 dialog.format_secondary_text(_("Snapshot Now requires "
217 "administrative privileges to run. "
218 "You have not been assigned the necessary"
219 "administrative priviliges."
220 "\n\nConsult your system administrator "))
222 print(argv + "is not a valid executable path")