Merge branch 'master' of /home/tmbinc/enigma2-git
[enigma2.git] / lib / python / Plugins / SystemPlugins / SoftwareManager / BackupRestore.py
1 from Screens.Screen import Screen
2 from Screens.MessageBox import MessageBox
3 from Screens.Console import Console
4 from Components.ActionMap import ActionMap, NumberActionMap
5 from Components.Pixmap import Pixmap
6 from Components.Label import Label
7 from Components.MenuList import MenuList
8 from Components.config import getConfigListEntry, configfile, ConfigSelection, ConfigSubsection, ConfigText, ConfigLocations
9 from Components.config import config
10 from Components.ConfigList import ConfigList,ConfigListScreen
11 from Components.FileList import MultiFileSelectList
12 from Plugins.Plugin import PluginDescriptor
13 from enigma import eTimer
14 from Tools.Directories import *
15 from os import popen, path, makedirs, listdir, access, stat, rename, remove, W_OK, R_OK
16 from time import gmtime, strftime, localtime
17 from datetime import date
18
19
20 config.plugins.configurationbackup = ConfigSubsection()
21 config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
22 config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf', '/etc/resolv.conf', '/etc/default_gw', '/etc/hostname'])
23
24 def getBackupPath():
25         backuppath = config.plugins.configurationbackup.backuplocation.value
26         if backuppath.endswith('/'):
27                 return backuppath + 'backup'
28         else:
29                 return backuppath + '/backup'
30
31 def getBackupFilename():
32         return "enigma2settingsbackup.tar.gz"
33                 
34
35 class BackupScreen(Screen, ConfigListScreen):
36         skin = """
37                 <screen position="135,144" size="350,310" title="Backup running..." >
38                 <widget name="config" position="10,10" size="330,250" transparent="1" scrollbarMode="showOnDemand" />
39                 </screen>"""
40                 
41         def __init__(self, session, runBackup = False):
42                 Screen.__init__(self, session)
43                 self.session = session
44                 self.runBackup = runBackup
45                 self["actions"] = ActionMap(["WizardActions", "DirectionActions"], 
46                 {
47                         "ok": self.close,
48                         "back": self.close,
49                         "cancel": self.close,
50                 }, -1)
51                 self.finished_cb = None
52                 self.backuppath = getBackupPath()
53                 self.backupfile = getBackupFilename()
54                 self.fullbackupfilename = self.backuppath + "/" + self.backupfile
55                 self.list = []
56                 ConfigListScreen.__init__(self, self.list)
57                 self.onLayoutFinish.append(self.layoutFinished)
58                 if self.runBackup:
59                         self.onShown.append(self.doBackup)
60
61         def layoutFinished(self):
62                 self.setWindowTitle()
63
64         def setWindowTitle(self):
65                 self.setTitle(_("Backup running..."))
66
67         def doBackup(self):
68                 try:
69                         if (path.exists(self.backuppath) == False):
70                                 makedirs(self.backuppath)
71                         self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
72                         if path.exists(self.fullbackupfilename):
73                                 dt = str(date.fromtimestamp(stat(self.fullbackupfilename).st_ctime))
74                                 self.newfilename = self.backuppath + "/" + dt + '-' + self.backupfile
75                                 if path.exists(self.newfilename):
76                                         remove(self.newfilename)
77                                 rename(self.fullbackupfilename,self.newfilename)
78                         if self.finished_cb:
79                                 self.session.openWithCallback(self.finished_cb, Console, title = _("Backup running"), cmdlist = ["tar -czvf " + self.fullbackupfilename + " " + self.backupdirs],finishedCallback = self.backupFinishedCB,closeOnSuccess = True)
80                         else:
81                                 self.session.open(Console, title = _("Backup running"), cmdlist = ["tar -czvf " + self.fullbackupfilename + " " + self.backupdirs],finishedCallback = self.backupFinishedCB, closeOnSuccess = True)
82                 except OSError:
83                         if self.finished_cb:
84                                 self.session.openWithCallback(self.finished_cb, MessageBox, _("Sorry your backup destination is not writeable.\nPlease choose an other one."), MessageBox.TYPE_INFO)
85                         else:
86                                 self.session.openWithCallback(self.backupErrorCB,MessageBox, _("Sorry your backup destination is not writeable.\nPlease choose an other one."), MessageBox.TYPE_INFO)
87
88         def backupFinishedCB(self,retval = None):
89                 self.close(True)
90
91         def backupErrorCB(self,retval = None):
92                 self.close(False)
93
94         def runAsync(self, finished_cb):
95                 self.finished_cb = finished_cb
96                 self.doBackup()
97                 
98
99 class BackupSelection(Screen):
100         skin = """
101         <screen position="135,125" size="450,310" title="Select files/folders to backup...">
102                 <widget name="checkList" position="10,10" size="430,250" transparent="1" scrollbarMode="showOnDemand" />
103                 <ePixmap position="0,265" zPosition="1" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
104                 <widget name="key_red" position="0,265" zPosition="2" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
105                 <ePixmap position="140,265" zPosition="1" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
106                 <widget name="key_green" position="140,265" zPosition="2" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
107                 <ePixmap position="280,265" zPosition="1" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
108                 <widget name="key_yellow" position="280,265" zPosition="2" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
109         </screen>"""
110
111         def __init__(self, session):
112                 Screen.__init__(self, session)
113                 self["key_red"] = Label(_("Cancel"))
114                 self["key_green"] = Label(_("Save"))
115                 self["key_yellow"] = Label()
116                 
117                 self.selectedFiles = config.plugins.configurationbackup.backupdirs.value
118                 defaultDir = '/'
119                 inhibitDirs = ["/bin", "/boot", "/dev", "/autofs", "/lib", "/proc", "/sbin", "/sys", "/hdd", "/tmp", "/mnt", "/media"]
120                 self.filelist = MultiFileSelectList(self.selectedFiles, defaultDir, inhibitDirs = inhibitDirs )
121                 self["checkList"] = self.filelist
122                 
123                 self["actions"] = ActionMap(["DirectionActions", "OkCancelActions", "ShortcutActions"],
124                 {
125                         "cancel": self.exit,
126                         "red": self.exit,
127                         "yellow": self.changeSelectionState,
128                         "green": self.saveSelection,
129                         "ok": self.okClicked,
130                         "left": self.left,
131                         "right": self.right,
132                         "down": self.down,
133                         "up": self.up
134                 }, -1)
135                 if not self.selectionChanged in self["checkList"].onSelectionChanged:
136                         self["checkList"].onSelectionChanged.append(self.selectionChanged)
137                 self.onLayoutFinish.append(self.layoutFinished)
138
139         def layoutFinished(self):
140                 idx = 0
141                 self["checkList"].moveToIndex(idx)
142                 self.setWindowTitle()
143                 self.selectionChanged()
144
145         def setWindowTitle(self):
146                 self.setTitle(_("Select files/folders to backup..."))
147
148         def selectionChanged(self):
149                 current = self["checkList"].getCurrent()[0]
150                 if current[2] is True:
151                         self["key_yellow"].setText(_("Deselect"))
152                 else:
153                         self["key_yellow"].setText(_("Select"))
154                 
155         def up(self):
156                 self["checkList"].up()
157
158         def down(self):
159                 self["checkList"].down()
160
161         def left(self):
162                 self["checkList"].pageUp()
163
164         def right(self):
165                 self["checkList"].pageDown()
166
167         def changeSelectionState(self):
168                 self["checkList"].changeSelectionState()
169                 self.selectedFiles = self["checkList"].getSelectedList()
170
171         def saveSelection(self):
172                 self.selectedFiles = self["checkList"].getSelectedList()
173                 config.plugins.configurationbackup.backupdirs.value = self.selectedFiles
174                 config.plugins.configurationbackup.backupdirs.save()
175                 config.plugins.configurationbackup.save()
176                 config.save()
177                 self.close(None)
178
179         def exit(self):
180                 self.close(None)
181
182         def okClicked(self):
183                 if self.filelist.canDescent():
184                         self.filelist.descent()
185
186
187 class RestoreMenu(Screen):
188         skin = """
189                 <screen position="135,144" size="450,300" title="Restore backups..." >
190                 <widget name="filelist" position="10,10" size="430,230" scrollbarMode="showOnDemand" />
191                 <ePixmap position="0,265" zPosition="1" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
192                 <widget name="canceltext" position="0,265" zPosition="2" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
193                 <ePixmap position="140,265" zPosition="1" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
194                 <widget name="restoretext" position="140,265" zPosition="2" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
195                 <ePixmap position="280,265" zPosition="1" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
196                 <widget name="deletetext" position="280,265" zPosition="2" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
197                 </screen>"""
198
199         def __init__(self, session, plugin_path):
200                 Screen.__init__(self, session)
201                 self.skin_path = plugin_path
202                 
203                 self["canceltext"] = Label(_("Cancel"))
204                 self["restoretext"] = Label(_("Restore"))
205                 self["deletetext"] = Label(_("Delete"))
206
207                 self.sel = []
208                 self.val = []
209                 self.entry = False
210                 self.exe = False
211                 
212                 self.path = ""
213
214                 self["actions"] = NumberActionMap(["SetupActions"],
215                 {
216                         "ok": self.KeyOk,
217                         "cancel": self.keyCancel
218                 }, -1)
219
220                 self["shortcuts"] = ActionMap(["ShortcutActions"],
221                 {
222                         "red": self.keyCancel,
223                         "green": self.KeyOk,
224                         "yellow": self.deleteFile,
225                 })
226                 self.flist = []
227                 self["filelist"] = MenuList(self.flist)
228                 self.fill_list()
229                 self.onLayoutFinish.append(self.layoutFinished)
230
231         def layoutFinished(self):
232                 self.setWindowTitle()
233
234         def setWindowTitle(self):
235                 self.setTitle(_("Restore backups..."))
236
237
238         def fill_list(self):
239                 self.flist = []
240                 self.path = getBackupPath()
241                 if (path.exists(self.path) == False):
242                         makedirs(self.path)
243                 for file in listdir(self.path):
244                         if (file.endswith(".tar.gz")):
245                                 self.flist.append((file))
246                                 self.entry = True
247                 self["filelist"].l.setList(self.flist)
248
249         def KeyOk(self):
250                 if (self.exe == False) and (self.entry == True):
251                         self.sel = self["filelist"].getCurrent()
252                         self.val = self.path + "/" + self.sel
253                         self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore\nfollowing backup:\n" + self.sel + "\nSystem will restart after the restore!"))
254
255         def keyCancel(self):
256                 self.close()
257
258         def startRestore(self, ret = False):
259                 if (ret == True):
260                         self.exe = True
261                         self.session.open(Console, title = _("Restore running"), cmdlist = ["tar -xzvf " + self.path + "/" + self.sel + " -C /", "killall -9 enigma2"])
262
263         def deleteFile(self):
264                 if (self.exe == False) and (self.entry == True):
265                         self.sel = self["filelist"].getCurrent()
266                         self.val = self.path + "/" + self.sel
267                         self.session.openWithCallback(self.startDelete, MessageBox, _("Are you sure you want to delete\nfollowing backup:\n" + self.sel ))
268
269         def startDelete(self, ret = False):
270                 if (ret == True):
271                         self.exe = True
272                         print "removing:",self.val
273                         if (path.exists(self.val) == True):
274                                 remove(self.val)
275                         self.exe = False
276                         self.fill_list()
277
278 class RestoreScreen(Screen, ConfigListScreen):
279         skin = """
280                 <screen position="135,144" size="350,310" title="Restore running..." >
281                 <widget name="config" position="10,10" size="330,250" transparent="1" scrollbarMode="showOnDemand" />
282                 </screen>"""
283                 
284         def __init__(self, session, runRestore = False):
285                 Screen.__init__(self, session)
286                 self.session = session
287                 self.runRestore = runRestore
288                 self["actions"] = ActionMap(["WizardActions", "DirectionActions"], 
289                 {
290                         "ok": self.close,
291                         "back": self.close,
292                         "cancel": self.close,
293                 }, -1)
294                 self.finished_cb = None
295                 self.backuppath = getBackupPath()
296                 self.backupfile = getBackupFilename()
297                 self.fullbackupfilename = self.backuppath + "/" + self.backupfile
298                 self.list = []
299                 ConfigListScreen.__init__(self, self.list)
300                 self.onLayoutFinish.append(self.layoutFinished)
301                 if self.runRestore:
302                         self.onShown.append(self.doRestore)
303
304         def layoutFinished(self):
305                 self.setWindowTitle()
306
307         def setWindowTitle(self):
308                 self.setTitle(_("Restore running..."))
309
310         def doRestore(self):
311                 if self.finished_cb:
312                         self.session.openWithCallback(self.finished_cb, Console, title = _("Restore running"), cmdlist = ["tar -xzvf " + self.fullbackupfilename + " -C /", "killall -9 enigma2"])
313                 else:
314                         self.session.open(Console, title = _("Restore running"), cmdlist = ["tar -xzvf " + self.fullbackupfilename + " -C /", "killall -9 enigma2"])
315
316         def backupFinishedCB(self,retval = None):
317                 self.close(True)
318
319         def backupErrorCB(self,retval = None):
320                 self.close(False)
321
322         def runAsync(self, finished_cb):
323                 self.finished_cb = finished_cb
324                 self.doRestore()