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