Replace all mentions of /usr/bin/python2.6 with /usr/bin/python2
[time-slider.git] / usr / share / time-slider / lib / time_slider / snapnowui.py
1 #!/usr/bin/python2
2 #
3 # CDDL HEADER START
4 #
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.
8 #
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.
13 #
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]
19 #
20 # CDDL HEADER END
21 #
22
23 import sys
24 import os
25 import datetime
26 import getopt
27 import string
28
29 try:
30     import pygtk
31     pygtk.require("2.4")
32 except:
33     pass
34 try:
35     import gtk
36     import gtk.glade
37     gtk.gdk.threads_init()
38 except:
39     sys.exit(1)
40 try:
41     import glib
42     import gobject
43 except:
44     sys.exit(1)
45
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__),
51                                os.path.pardir,
52                                os.path.pardir))
53 LOCALE_PATH = os.path.join('/usr', 'share', 'locale')
54 RESOURCE_PATH = os.path.join(SHARED_FILES, 'res')
55
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'
60
61 # set up the glade gettext system and locales
62 gtk.glade.bindtextdomain(GETTEXT_DOMAIN, LOCALE_PATH)
63 gtk.glade.textdomain(GETTEXT_DOMAIN)
64
65 import zfs
66 from rbac import RBACprofile
67
68 class SnapshotNowDialog:
69
70     def __init__(self, dir_path, zfs_fs):
71         self.dir_path = dir_path
72         self.zfs_fs = zfs_fs
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")
78         # signal dictionary     
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)
84
85         self.snap_name_entry.connect("activate", self.__on_entry_activate, 0)
86
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"))
89
90         self.dialog.show ()
91
92     def validate_name (self, name, showErrorDialog=False):
93         #check name validity
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
96
97         invalid = False
98         _validchars = string.ascii_letters + string.digits + \
99                       "-_.:"
100         _allchars = string.maketrans("", "")
101         _invalidchars = _allchars.translate(_allchars, _validchars)
102   
103         valid_name = ""
104
105         for c in name:
106           if c not in _invalidchars:
107             valid_name = valid_name + c
108           else:
109             invalid = True
110
111         if invalid and showErrorDialog:
112           dialog = gtk.MessageDialog(None,
113                                      0,
114                                      gtk.MESSAGE_ERROR,
115                                      gtk.BUTTONS_CLOSE,
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"))
121           dialog.run ()                                  
122           dialog.destroy ()
123         return valid_name
124         
125
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))
128         return
129         
130
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 = "pfexec /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.
139         error = ferr.read()
140         self.dialog.hide ()
141         if len(error) > 0:
142           dialog = gtk.MessageDialog(None,
143                                      0,
144                                      gtk.MESSAGE_ERROR,
145                                      gtk.BUTTONS_CLOSE,
146                                      _("Error occured while creating the snapshot"))
147           dialog.set_title (_("Error"))
148           dialog.format_secondary_text(error)
149           dialog.run ()
150         else:
151           dialog = gtk.MessageDialog(None,
152                                      0,
153                                      gtk.MESSAGE_INFO,
154                                      gtk.BUTTONS_CLOSE,
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})
161           dialog.run ()
162
163         sys.exit(1)
164       else:
165         self.snap_name_entry.set_text (valid_name)
166
167 def main(argv):
168     try:
169         opts,args = getopt.getopt(sys.argv[1:], "", [])
170     except getopt.GetoptError:
171         sys.exit(2)
172     #FIXME
173     #check for 2 args here we assume the arguments are correct
174     if len(args) != 2:
175         dialog = gtk.MessageDialog(None,
176                                    0,
177                                    gtk.MESSAGE_ERROR,
178                                    gtk.BUTTONS_CLOSE,
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."))
186         dialog.run()
187         sys.exit (2)
188         
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.
193     #
194     # Valid combinations of the above are:
195     # - 1 or 4
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])
200         gtk.main()
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]
204         for arg in args:
205             newargs.append(arg)
206         os.execv("/usr/bin/gksu", newargs)
207         # Shouldn't reach this point
208         sys.exit(1)
209     else:
210         dialog = gtk.MessageDialog(None,
211                                    0,
212                                    gtk.MESSAGE_ERROR,
213                                    gtk.BUTTONS_CLOSE,
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 "))
221         dialog.run()
222         print argv + "is not a valid executable path"
223         sys.exit(1)
224