~tkluck/backintime/mountmonitor

« back to all changes in this revision

Viewing changes to common/config.py

  • Committer: Timo Kluck
  • Date: 2009-11-26 22:25:01 UTC
  • mfrom: (585.1.47 trunk)
  • Revision ID: tkluck@netbook-tjk-20091126222501-6cfwq1jfud2c0m3j
* added kde support
 * removed accidentally added ¨feature¨ of a per-folder on-mount action (added by copy pasting code)
 * merge with current version in trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#    Back In Time
2
 
#    Copyright (C) 2008-2009 Oprea Dan
 
2
#    Copyright (C) 2008-2009 Oprea Dan, Bart de Koning, Richard Bailey
3
3
#
4
4
#    This program is free software; you can redistribute it and/or modify
5
5
#    it under the terms of the GNU General Public License as published by
20
20
import os
21
21
import datetime
22
22
import gettext
 
23
import socket
 
24
import random
23
25
 
24
26
import configfile
25
27
import tools
26
 
 
 
28
import logger
27
29
 
28
30
_=gettext.gettext
29
31
 
31
33
gettext.textdomain( 'backintime' )
32
34
 
33
35
 
34
 
class Config( configfile.ConfigFile ):
 
36
class Config( configfile.ConfigFileWithProfiles ):
35
37
        APP_NAME = 'Back In Time'
36
 
        VERSION = '0.9.26tjk'
37
 
        COPYRIGHT = 'Copyright (c) 2008-2009 Oprea Dan'
38
 
        CONFIG_VERSION = 2
 
38
        VERSION = '0.9.99tjk'
 
39
        COPYRIGHT = 'Copyright (c) 2008-2009 Oprea Dan, Bart de Koning, Richard Bailey'
 
40
        CONFIG_VERSION = 4
39
41
 
40
42
        NONE = 0
41
43
        _5_MIN = 2
79
81
 
80
82
 
81
83
        def __init__( self ):
 
84
                configfile.ConfigFileWithProfiles.__init__( self, _('Main profile') )
 
85
 
82
86
                self._APP_PATH =  os.path.dirname( os.path.abspath( os.path.dirname( __file__ ) ) )
83
87
                self._DOC_PATH = '/usr/share/doc/backintime'
84
88
                if os.path.exists( os.path.join( self._APP_PATH, 'LICENSE' ) ):
128
132
                        self.remap_key( 'MAIN_WINDOW_HEIGHT', 'gnome.main_window.height' )
129
133
                        self.remap_key( 'MAIN_WINDOW_HPANED1_POSITION', 'gnome.main_window.hpaned1' )
130
134
                        self.remap_key( 'MAIN_WINDOW_HPANED2_POSITION', 'gnome.main_window.hpaned2' )
 
135
                        self.set_int_value( 'config.version', 2 )
131
136
 
132
 
                if self.get_int_value( 'config.version', 1 ) < self.CONFIG_VERSION:
133
 
                        self.set_int_value( 'config.version', self.CONFIG_VERSION )
 
137
                if self.get_int_value( 'config.version', 1 ) < 3:
 
138
                        self.remap_key( 'snapshots.path', 'profile1.snapshots.path' )
 
139
                        self.remap_key( 'snapshots.include_folders', 'profile1.snapshots.include_folders' )
 
140
                        self.remap_key( 'snapshots.exclude_patterns', 'profile1.snapshots.exclude_patterns' )
 
141
                        self.remap_key( 'snapshots.automatic_backup_mode', 'profile1.snapshots.automatic_backup_mode' )
 
142
                        self.remap_key( 'snapshots.remove_old_snapshots.enabled', 'profile1.snapshots.remove_old_snapshots.enabled' )
 
143
                        self.remap_key( 'snapshots.remove_old_snapshots.value', 'profile1.snapshots.remove_old_snapshots.value' )
 
144
                        self.remap_key( 'snapshots.remove_old_snapshots.unit', 'profile1.snapshots.remove_old_snapshots.unit' )
 
145
                        self.remap_key( 'snapshots.min_free_space.enabled', 'profile1.snapshots.min_free_space.enabled' )
 
146
                        self.remap_key( 'snapshots.min_free_space.value', 'profile1.snapshots.min_free_space.value' )
 
147
                        self.remap_key( 'snapshots.min_free_space.unit', 'profile1.snapshots.min_free_space.unit' )
 
148
                        self.remap_key( 'snapshots.dont_remove_named_snapshots', 'profile1.snapshots.dont_remove_named_snapshots' )
 
149
                        self.set_int_value( 'config.version', 3 )
 
150
                        
 
151
                if self.get_int_value( 'config.version', 1 ) < 4:
 
152
                        # version 4 uses as path backintime/machine/user/profile_id
 
153
                        # but must be able to read old paths
 
154
                        profiles = self.get_profiles()
 
155
                        self.set_bool_value( 'update.other_folders', True )
 
156
                        logger.info( "Update to config version 4: other snapshot locations" )
 
157
                                                                        
 
158
                        for profile_id in profiles:
 
159
                                old_folder = self.get_snapshots_path( profile_id )
 
160
                                other_folder = os.path.join( old_folder, 'backintime' )
 
161
                                other_folder_key = 'profile' + str( profile_id ) + '.snapshots.other_folders'
 
162
                                self.set_str_value( other_folder_key, other_folder )
 
163
                                #self.set_snapshots_path( old_folder, profile_id )
 
164
                                tag = str( random.randint(100, 999) )
 
165
                                logger.info( "Random tag for profile %s: %s" %( profile_id, tag ) )
 
166
                                self.set_profile_str_value( 'snapshots.tag', tag, profile_id ) 
 
167
        
 
168
                        self.set_int_value( 'config.version', 4 )
134
169
 
135
170
        def save( self ):
136
171
                configfile.ConfigFile.save( self, self._LOCAL_CONFIG_PATH )
137
172
 
138
 
        def check_take_snapshot_params( self, snapshots_path, include_list, exclude_list ):
139
 
                #returns None or ( ID, message ) //0 - snapshots path, 1 - include list, 2 - exclude list
140
 
                if len( snapshots_path ) == 0 or not os.path.isdir( snapshots_path ):
141
 
                        return ( 0, _('Snapshots folder is not valid !') )
142
 
 
143
 
                if len( snapshots_path ) <= 1:
144
 
                        return ( 0, _('Snapshots folder can\'t be the root folder !') )
145
 
 
146
 
                if len( include_list ) <= 0:
147
 
                        return ( 1, _('You must select at least one folder to backup !') )
148
 
 
149
 
                snapshots_path2 = snapshots_path + '/'
150
 
 
151
 
                for item in include_list:
152
 
                        path = item[0]
153
 
                        if path == snapshots_path:
154
 
                                print "Path: " + path
155
 
                                print "SnapshotsPath: " + snapshots_path 
156
 
                                return ( 1, _('You can\'t include backup folder !') )
157
 
                        
158
 
                        if len( path ) >= len( snapshots_path2 ):
159
 
                                if path[ : len( snapshots_path2 ) ] == snapshots_path2:
160
 
                                        print "Path: " + path
161
 
                                        print "SnapshotsPath2: " + snapshots_path2
162
 
                                        return ( 1, _('You can\'t include a backup sub-folder !') )
163
 
                        #else:
164
 
                        #       path2 = path + '/'
165
 
                        #       if len( path2 ) < len( snapshots_path ):
166
 
                        #               if path2 == snapshots_path[ : len( path2 ) ]:
167
 
                        #                       print "Path2: " + path2
168
 
                        #                       print "SnapshotsPath: " + snapshots_path 
169
 
                        #                       return ( 1, _('"Backup folders" can\'t include snapshots folder !') )
170
 
 
171
 
                for exclude in exclude_list:
172
 
                        if exclude.find( ':' ) >= 0:
173
 
                                return ( 2, _('Exclude patterns can\'t contain \':\' char !') )
174
 
 
175
 
                return None
176
 
 
177
 
        def get_snapshots_path( self ):
178
 
                return self.get_str_value( 'snapshots.path', '' )
179
 
 
180
 
        def get_snapshots_full_path( self ):
181
 
                return os.path.join( self.get_snapshots_path(), 'backintime' ) 
182
 
 
183
 
        def set_snapshots_path( self, value ):
184
 
                print "Snapshots path: %s" % value
185
 
 
186
 
                if len( value ) > 0:
187
 
                        if not os.path.isdir( value ):
188
 
                                return _( '%s is not a folder !' ) % value
189
 
                        else:
190
 
                                old_value = self.get_snapshots_path()
191
 
                                self.set_str_value( 'snapshots.path', value )
192
 
                                full_path = self.get_snapshots_full_path()
193
 
                                self.set_str_value( 'snapshots.path', old_value )
194
 
 
195
 
                                if not os.path.isdir( full_path ):
196
 
                                        tools.make_dirs( full_path )
197
 
                                        if not os.path.isdir( full_path ):
198
 
                                                return _( 'Can\'t write to: %s\nAre you sure have write access ?' ) % value
199
 
 
200
 
                self.set_str_value( 'snapshots.path', value )
201
 
                return None
202
 
 
203
 
        def get_include_folders( self ):
204
 
                value = self.get_str_value( 'snapshots.include_folders', '' )
 
173
        def check_config( self ):
 
174
                profiles = self.get_profiles()
 
175
 
 
176
                checked_profiles = []
 
177
 
 
178
                for profile_id in profiles:
 
179
                        profile_name = self.get_profile_name( profile_id )
 
180
                        snapshots_path = self.get_snapshots_path( profile_id )
 
181
 
 
182
                        #check snapshots path
 
183
                        if len( snapshots_path ) <= 0:
 
184
                                self.notify_error( _('Profile: "%s"') % profile_name + '\n' + _('Snapshots folder is not valid !') )
 
185
                                return False
 
186
 
 
187
                        ## Should not check for similar snapshot paths any longer! 
 
188
                        #for other_profile in checked_profiles:
 
189
                        #       if snapshots_path == self.get_snapshots_path( other_profile[0] ):
 
190
                        #               self.notify_error( _('Profiles "%s" and "%s" have the same snapshots path !') % ( profile_name, other_profile[1] ) )
 
191
                        #               return False
 
192
                        #
 
193
                        #if not os.path.isdir( snapshots_path ):
 
194
                        #       return ( 0, _('Snapshots folder is not valid !') )
 
195
 
 
196
                        #if len( self.get_snapshots_path( profile_id ) ) <= 1:
 
197
                        #       return ( 0, _('Snapshots folder can\'t be the root folder !') )
 
198
 
 
199
                        #check include
 
200
                        include_list = self.get_include_folders( profile_id )
 
201
                        if len( include_list ) <= 0:
 
202
                                self.notify_error( _('Profile: "%s"') % profile_name + '\n' + _('You must select at least one folder to backup !') )
 
203
                                return False
 
204
 
 
205
                        snapshots_path2 = snapshots_path + '/'
 
206
 
 
207
                        for item in include_list:
 
208
                                path = item[0]
 
209
                                if path == snapshots_path:
 
210
                                        self.notify_error( _('Profile: "%s"') % profile_name + '\n' + _('You can\'t include backup folder !') )
 
211
                                        return False
 
212
                        
 
213
                                if len( path ) >= len( snapshots_path2 ):
 
214
                                        if path[ : len( snapshots_path2 ) ] == snapshots_path2:
 
215
                                                self.notify_error( _('Profile: "%s"') % profile_name + '\n' + _('You can\'t include a backup sub-folder !') )
 
216
                                                return False
 
217
 
 
218
                        checked_profiles.append( ( profile_id, profile_name ) )
 
219
 
 
220
                return True
 
221
 
 
222
        def get_snapshots_path( self, profile_id = None ):
 
223
                return self.get_profile_str_value( 'snapshots.path', '', profile_id )
 
224
 
 
225
        def get_snapshots_full_path( self, profile_id = None ):
 
226
                '''Returns the full path for the snapshots: .../backintime/machine/user/profile_id/'''
 
227
                if self.get_int_value( 'config.version', 1 ) < 4:
 
228
                        return os.path.join( self.get_snapshots_path( profile_id ), 'backintime' )
 
229
                else:
 
230
                        machine = socket.gethostname()
 
231
                        user = os.environ['LOGNAME']
 
232
                        return os.path.join( self.get_snapshots_path( profile_id ), 'backintime', machine, user, profile_id ) 
 
233
 
 
234
        def set_snapshots_path( self, value, profile_id = None ):
 
235
                """Sets the snapshot path to value, initializes, and checks it"""
 
236
                if len( value ) <= 0:
 
237
                        return False
 
238
 
 
239
                if profile_id == None:
 
240
                        print "BUG: calling set_snapshots_path without profile_id!"
 
241
                        tjoep
 
242
                        return False
 
243
                        
 
244
                if not os.path.isdir( value ):
 
245
                        self.notify_error( _( '%s is not a folder !' % value) )
 
246
                        return False
 
247
 
 
248
                #Initialize the snapshots folder
 
249
                print "Check snapshot folder: %s" % value
 
250
                machine = socket.gethostname()
 
251
                user = os.environ['LOGNAME']
 
252
                full_path = os.path.join( value, 'backintime', machine, user, profile_id ) 
 
253
                if not os.path.isdir( full_path ):
 
254
                        print "Create folder: %s" % full_path
 
255
                        tools.make_dirs( full_path )
 
256
                        if not os.path.isdir( full_path ):
 
257
                                self.notify_error( _( 'Can\'t write to: %s\nAre you sure you have write access ?' % value ) )
 
258
                                return False
 
259
                
 
260
                #Test write access for the folder
 
261
                check_path = os.path.join( full_path, 'check' )
 
262
                tools.make_dirs( check_path )
 
263
                if not os.path.isdir( check_path ):
 
264
                        self.notify_error( _( 'Can\'t write to: %s\nAre you sure you have write access ?' % full_path ) )
 
265
                        return False
 
266
                
 
267
                os.rmdir( check_path )
 
268
                self.set_profile_str_value( 'snapshots.path', value, profile_id )
 
269
                return True
 
270
 
 
271
        def get_other_folders_paths( self, profile_id = None ):
 
272
                '''Returns the other snapshots folders paths as a list'''
 
273
                value = self.get_profile_str_value( 'snapshots.other_folders', '', profile_id )
 
274
                if len( value ) <= 0:
 
275
                        return []
 
276
                        
 
277
                paths = []
 
278
 
 
279
                for item in value.split(':'):
 
280
                        fields = item.split( '|' )
 
281
 
 
282
                        path = os.path.expanduser( item )
 
283
                        path = os.path.abspath( path )
 
284
 
 
285
                        paths.append( ( path ) )
 
286
 
 
287
                return paths
 
288
        
 
289
        def get_include_folders( self, profile_id = None ):
 
290
                value = self.get_profile_str_value( 'snapshots.include_folders', '', profile_id )
205
291
                if len( value ) <= 0:
206
292
                        return []
207
293
 
222
308
 
223
309
                return paths
224
310
 
225
 
        def set_include_folders( self, list ):
 
311
        def set_include_folders( self, list, profile_id = None ):
226
312
                value = ''
227
313
 
228
314
                for item in list:
230
316
                                value = value + ':'
231
317
                        value = value + item[0] + '|' + str( item[1] )
232
318
 
233
 
                self.set_str_value( 'snapshots.include_folders', value )
234
 
 
235
 
        def get_exclude_patterns( self ):
236
 
                value = self.get_str_value( 'snapshots.exclude_patterns', '.*:*.backup*:*~' )
 
319
                self.set_profile_str_value( 'snapshots.include_folders', value, profile_id )
 
320
 
 
321
        def get_exclude_patterns( self, profile_id = None ):
 
322
                '''Gets the exclude patterns (default: caches, thumbnails, trashbins, and backups)'''
 
323
                value = self.get_profile_str_value( 'snapshots.exclude_patterns', '.cache*:[Cc]ache*:.thumbnails*:[Tt]rash*:*.backup*:*~', profile_id )
237
324
                if len( value ) <= 0:
238
325
                        return []
239
326
                return value.split(':')
240
327
 
241
 
        def set_exclude_patterns( self, list ):
242
 
                self.set_str_value( 'snapshots.exclude_patterns', ':'.join( list ) )
243
 
 
244
 
        def get_automatic_backup_mode( self ):
245
 
                return self.get_int_value( 'snapshots.automatic_backup_mode', self.NONE )
246
 
 
247
 
        def set_automatic_backup_mode( self, value ):
248
 
                self.set_int_value( 'snapshots.automatic_backup_mode', value )
249
 
                #self.setup_cron()
250
 
 
251
 
        def get_on_mount_action( self ):
252
 
                return self.get_int_value( 'snapshots.on_mount_action', self.NONE )
253
 
 
254
 
        def set_on_mount_action( self, value ):
255
 
                self.set_int_value( 'snapshots.on_mount_action', value )
256
 
 
257
 
        def get_per_directory_schedule( self ):
258
 
                return self.get_bool_value( 'snapshots.expert.per_directory_schedule', False )
259
 
 
260
 
        def set_per_directory_schedule( self, value ):
261
 
                return self.set_bool_value( 'snapshots.expert.per_directory_schedule', value )
262
 
 
263
 
        def get_remove_old_snapshots( self ):
264
 
                return ( self.get_bool_value( 'snapshots.remove_old_snapshots.enabled', True ),
265
 
                                 self.get_int_value( 'snapshots.remove_old_snapshots.value', 10 ),
266
 
                                 self.get_int_value( 'snapshots.remove_old_snapshots.unit', self.YEAR ) )
267
 
        
268
 
        def is_remove_old_snapshots_enabled( self ):
269
 
                return self.get_bool_value( 'snapshots.remove_old_snapshots.enabled', True )
270
 
        
271
 
        def get_remove_old_snapshots_date( self ):
272
 
                enabled, value, unit = self.get_remove_old_snapshots()
 
328
        def set_exclude_patterns( self, list, profile_id = None ):
 
329
                self.set_profile_str_value( 'snapshots.exclude_patterns', ':'.join( list ), profile_id )
 
330
 
 
331
        def get_tag( self, profile_id = None ):
 
332
                return self.get_profile_str_value( 'snapshots.tag', str(random.randint(100, 999)), profile_id )
 
333
 
 
334
        def get_automatic_backup_mode( self, profile_id = None ):
 
335
                return self.get_profile_int_value( 'snapshots.automatic_backup_mode', self.NONE, profile_id )
 
336
 
 
337
        def set_automatic_backup_mode( self, value, profile_id = None ):
 
338
                self.set_profile_int_value( 'snapshots.automatic_backup_mode', value, profile_id )
 
339
 
 
340
        def get_on_mount_action( self, profile_id = None ):
 
341
                return self.get_profile_int_value( 'snapshots.on_mount_action', self.NO_ACTION, profile_id )
 
342
 
 
343
        def set_on_mount_action( self, value, profile_id = None ):
 
344
                self.set_profile_int_value( 'snapshots.on_mount_action', value, profile_id )
 
345
 
 
346
        def get_per_directory_schedule( self, profile_id = None ):
 
347
                return self.get_profile_bool_value( 'snapshots.expert.per_directory_schedule', False, profile_id )
 
348
 
 
349
        def set_per_directory_schedule( self, value, profile_id = None ):
 
350
                return self.set_profile_bool_value( 'snapshots.expert.per_directory_schedule', value, profile_id )
 
351
 
 
352
        def get_remove_old_snapshots( self, profile_id = None ):
 
353
                return ( self.get_profile_bool_value( 'snapshots.remove_old_snapshots.enabled', True, profile_id ),
 
354
                                 self.get_profile_int_value( 'snapshots.remove_old_snapshots.value', 10, profile_id ),
 
355
                                 self.get_profile_int_value( 'snapshots.remove_old_snapshots.unit', self.YEAR, profile_id ) )
 
356
        
 
357
        def is_remove_old_snapshots_enabled( self, profile_id = None ):
 
358
                return self.get_profile_bool_value( 'snapshots.remove_old_snapshots.enabled', True, profile_id )
 
359
        
 
360
        def get_remove_old_snapshots_date( self, profile_id = None ):
 
361
                enabled, value, unit = self.get_remove_old_snapshots( profile_id )
273
362
                if not enabled:
274
363
                        return datetime.date( 1, 1, 1 )
275
364
 
289
378
                
290
379
                return datetime.date( 1, 1, 1 )
291
380
 
292
 
        def set_remove_old_snapshots( self, enabled, value, unit ):
293
 
                self.set_bool_value( 'snapshots.remove_old_snapshots.enabled', enabled )
294
 
                self.set_int_value( 'snapshots.remove_old_snapshots.value', value )
295
 
                self.set_int_value( 'snapshots.remove_old_snapshots.unit', unit )
 
381
        def set_remove_old_snapshots( self, enabled, value, unit, profile_id = None ):
 
382
                self.set_profile_bool_value( 'snapshots.remove_old_snapshots.enabled', enabled, profile_id )
 
383
                self.set_profile_int_value( 'snapshots.remove_old_snapshots.value', value, profile_id )
 
384
                self.set_profile_int_value( 'snapshots.remove_old_snapshots.unit', unit, profile_id )
296
385
 
297
 
        def get_min_free_space( self ):
298
 
                return ( self.get_bool_value( 'snapshots.min_free_space.enabled', True ),
299
 
                                 self.get_int_value( 'snapshots.min_free_space.value', 1 ),
300
 
                                 self.get_int_value( 'snapshots.min_free_space.unit', self.DISK_UNIT_GB ) )
 
386
        def get_min_free_space( self, profile_id = None ):
 
387
                return ( self.get_profile_bool_value( 'snapshots.min_free_space.enabled', True, profile_id ),
 
388
                                 self.get_profile_int_value( 'snapshots.min_free_space.value', 1, profile_id ),
 
389
                                 self.get_profile_int_value( 'snapshots.min_free_space.unit', self.DISK_UNIT_GB, profile_id ) )
301
390
        
302
 
        def is_min_free_space_enabled( self ):
303
 
                return self.get_bool_value( 'snapshots.min_free_space.enabled', True )
 
391
        def is_min_free_space_enabled( self, profile_id = None ):
 
392
                return self.get_profile_bool_value( 'snapshots.min_free_space.enabled', True, profile_id )
304
393
 
305
 
        def get_min_free_space_in_mb( self ):
306
 
                enabled, value, unit = self.get_min_free_space()
 
394
        def get_min_free_space_in_mb( self, profile_id = None ):
 
395
                enabled, value, unit = self.get_min_free_space( profile_id )
307
396
                if not enabled:
308
397
                        return 0
309
398
 
316
405
 
317
406
                return 0
318
407
 
319
 
        def set_min_free_space( self, enabled, value, unit ):
320
 
                self.set_bool_value( 'snapshots.min_free_space.enabled', enabled )
321
 
                self.set_int_value( 'snapshots.min_free_space.value', value )
322
 
                self.set_int_value( 'snapshots.min_free_space.unit', unit )
323
 
 
324
 
        def get_dont_remove_named_snapshots( self ):
325
 
                return self.get_bool_value( 'snapshots.dont_remove_named_snapshots', True )
326
 
 
327
 
        def set_dont_remove_named_snapshots( self, value ):
328
 
                self.set_bool_value( 'snapshots.dont_remove_named_snapshots', value )
329
 
        
330
 
        def get_smart_remove( self ):
331
 
                return self.get_bool_value( 'snapshots.smart_remove', False )
332
 
 
333
 
        def set_smart_remove( self, value ):
334
 
                self.set_bool_value( 'snapshots.smart_remove', value )
335
 
        
336
 
        def is_notify_enabled( self ):
337
 
                return self.get_bool_value( 'snapshots.notify.enabled', True )
338
 
 
339
 
        def set_notify_enabled( self, value ):
340
 
                self.set_bool_value( 'snapshots.notify.enabled', value )
341
 
 
342
 
        def is_run_nice_from_cron_enabled( self ):
343
 
                return self.get_bool_value( 'snapshots.cron.nice', True )
344
 
 
345
 
        def set_run_nice_from_cron_enabled( self, value ):
346
 
                self.set_bool_value( 'snapshots.cron.nice', value )
347
 
 
348
 
        def get_take_snapshot_user_script( self, step ):
349
 
                return self.get_str_value( "snapshots.take_snapshot.%s.user.script" )
350
 
 
351
 
        def set_take_snapshot_user_script( self, step, path ):
352
 
                self.set_str_value( "snapshots.take_snapshot.%s.user.script" % step, path )
353
 
 
354
 
        def get_take_snapshot_user_script_before( self ):
355
 
                return self.get_take_snapshot_user_script( 'before' )
356
 
 
357
 
        def set_take_snapshot_user_script_before( self, path ):
358
 
                self.set_take_snapshot_user_script( 'before', path )
359
 
 
360
 
        def get_take_snapshot_user_script_after( self ):
361
 
                return self.get_take_snapshot_user_script( 'after' )
362
 
 
363
 
        def set_take_snapshot_user_script_after( self, path ):
364
 
                self.set_take_snapshot_user_script( 'after', path )
365
 
 
366
 
        def get_take_snapshot_user_script_new_snapshot( self ):
367
 
                return self.get_take_snapshot_user_script( 'new_snapshot' )
368
 
 
369
 
        def set_take_snapshot_user_script_new_snapshot( self, path ):
370
 
                self.set_take_snapshot_user_script( 'new_snapshot', path )
371
 
 
372
 
        def get_take_snapshot_user_script_error( self ):
373
 
                return self.get_take_snapshot_user_script( 'error' )
374
 
 
375
 
        def set_take_snapshot_user_script_error( self, path ):
376
 
                self.set_take_snapshot_user_script( 'error', path )
 
408
        def set_min_free_space( self, enabled, value, unit, profile_id = None ):
 
409
                self.set_profile_bool_value( 'snapshots.min_free_space.enabled', enabled, profile_id )
 
410
                self.set_profile_int_value( 'snapshots.min_free_space.value', value, profile_id )
 
411
                self.set_profile_int_value( 'snapshots.min_free_space.unit', unit, profile_id )
 
412
 
 
413
        def get_dont_remove_named_snapshots( self, profile_id = None ):
 
414
                return self.get_profile_bool_value( 'snapshots.dont_remove_named_snapshots', True, profile_id )
 
415
 
 
416
        def set_dont_remove_named_snapshots( self, value, profile_id = None ):
 
417
                self.set_profile_bool_value( 'snapshots.dont_remove_named_snapshots', value, profile_id )
 
418
        
 
419
        def get_smart_remove( self, profile_id = None ):
 
420
                return self.get_profile_bool_value( 'snapshots.smart_remove', False, profile_id )
 
421
 
 
422
        def set_smart_remove( self, value, profile_id = None ):
 
423
                self.set_profile_bool_value( 'snapshots.smart_remove', value, profile_id )
 
424
        
 
425
        def is_notify_enabled( self, profile_id = None ):
 
426
                return self.get_profile_bool_value( 'snapshots.notify.enabled', True, profile_id )
 
427
 
 
428
        def set_notify_enabled( self, value, profile_id = None ):
 
429
                self.set_profile_bool_value( 'snapshots.notify.enabled', value, profile_id )
 
430
 
 
431
        def is_run_nice_from_cron_enabled( self, profile_id = None ):
 
432
                return self.get_profile_bool_value( 'snapshots.cron.nice', True, profile_id )
 
433
 
 
434
        def set_run_nice_from_cron_enabled( self, value, profile_id = None ):
 
435
                self.set_profile_bool_value( 'snapshots.cron.nice', value, profile_id )
 
436
 
 
437
        def is_no_on_battery_enabled( self, profile_id = None ):
 
438
                return self.get_profile_bool_value( 'snapshots.no_on_battery', False, profile_id )
 
439
 
 
440
        def set_no_on_battery_enabled( self, value, profile_id = None ):
 
441
                self.set_profile_bool_value( 'snapshots.no_on_battery', value, profile_id )
 
442
 
 
443
        def get_take_snapshot_user_script( self, step, profile_id = None ):
 
444
                return self.get_profile_str_value ( "snapshots.take_snapshot.%s.user.script" % step, '', profile_id )
 
445
 
 
446
        def set_take_snapshot_user_script( self, step, path, profile_id = None ):
 
447
                self.set_profile_str_value( "snapshots.take_snapshot.%s.user.script" % step, path, profile_id )
 
448
 
 
449
        def get_take_snapshot_user_script_before( self, profile_id = None ):
 
450
                return self.get_take_snapshot_user_script( 'before', profile_id )
 
451
 
 
452
        def set_take_snapshot_user_script_before( self, path, profile_id = None ):
 
453
                self.set_take_snapshot_user_script( 'before', path, profile_id )
 
454
 
 
455
        def get_take_snapshot_user_script_after( self, profile_id = None ):
 
456
                return self.get_take_snapshot_user_script( 'after', profile_id )
 
457
 
 
458
        def set_take_snapshot_user_script_after( self, path, profile_id = None ):
 
459
                self.set_take_snapshot_user_script( 'after', path, profile_id )
 
460
 
 
461
        def get_take_snapshot_user_script_new_snapshot( self, profile_id = None ):
 
462
                return self.get_take_snapshot_user_script( 'new_snapshot', profile_id = None )
 
463
 
 
464
        def set_take_snapshot_user_script_new_snapshot( self, path, profile_id = None ):
 
465
                self.set_take_snapshot_user_script( 'new_snapshot', path, profile_id )
 
466
 
 
467
        def get_take_snapshot_user_script_error( self, profile_id = None ):
 
468
                return self.get_take_snapshot_user_script( 'error', profile_id )
 
469
 
 
470
        def set_take_snapshot_user_script_error( self, path, profile_id = None ):
 
471
                self.set_take_snapshot_user_script( 'error', path, profile_id )
377
472
 
378
473
        def get_app_path( self ):
379
474
                return self._APP_PATH
384
479
        def get_app_instance_file( self ):
385
480
                return os.path.join( self._LOCAL_DATA_FOLDER, 'app.lock' )
386
481
 
387
 
        def get_take_snapshot_message_file( self ):
388
 
                return os.path.join( self._LOCAL_DATA_FOLDER, 'worker.message' )
389
 
 
390
 
        def get_take_snapshot_instance_file( self ):
391
 
                return os.path.join( self._LOCAL_DATA_FOLDER, 'worker.lock' )
392
 
 
393
 
        def get_last_snapshot_info_file( self ):
394
 
                return os.path.join( self._LOCAL_DATA_FOLDER, 'snapshot.last' )
395
 
 
396
 
        def get_take_snapshot_user_callback( self ):
397
 
                return os.path.join( self._LOCAL_CONFIG_FOLDER, 'user.callback' )
 
482
        def __get_file_id__( self, profile_id = None ):
 
483
                if profile_id is None:
 
484
                        profile_id = self.get_current_profile()
 
485
                if profile_id == '1':
 
486
                        return ''
 
487
                return profile_id
 
488
 
 
489
        def get_take_snapshot_message_file( self, profile_id = None ):
 
490
                return os.path.join( self._LOCAL_DATA_FOLDER, "worker%s.message" % self.__get_file_id__( profile_id ) )
 
491
 
 
492
        def get_take_snapshot_instance_file( self, profile_id = None ):
 
493
                return os.path.join( self._LOCAL_DATA_FOLDER, "worker%s.lock" % self.__get_file_id__( profile_id ) )
 
494
 
 
495
        def get_last_snapshot_info_file( self, profile_id = None ):
 
496
                return os.path.join( self._LOCAL_DATA_FOLDER, "snapshot%s.last" % self.__get_file_id__( profile_id ) )
 
497
 
 
498
        def get_take_snapshot_user_callback( self, profile_id = None ):
 
499
                return os.path.join( self._LOCAL_CONFIG_FOLDER, "user%s.callback" % self.__get_file_id__( profile_id ) )
398
500
 
399
501
        def get_license( self ):
400
502
                return tools.read_file( os.path.join( self.get_doc_path(), 'LICENSE' ), '' )
411
513
                                path = path[ : -1 ]
412
514
                return path
413
515
 
414
 
        def is_configured( self ):
415
 
                if len( self.get_snapshots_path() ) == 0:
 
516
        def is_configured( self, profile_id = None ):
 
517
                '''Checks if the program is configured''' 
 
518
                if len( self.get_snapshots_path( profile_id ) ) == 0:
416
519
                        return False
417
520
 
418
 
                if len( self.get_include_folders() ) == 0:
 
521
                if len( self.get_include_folders( profile_id ) ) == 0:
419
522
                        return False
420
523
 
421
524
                return True
422
 
 
423
 
        def can_backup( self ):
424
 
                if not self.is_configured():
 
525
        
 
526
        def update_snapshot_location( self ):
 
527
                '''Updates to location: backintime/machine/user/profile_id'''
 
528
                if self.get_update_other_folders() == True:
 
529
                        logger.info( 'Snapshot location update flag detected' )
 
530
                        logger.warning( 'Snapshot location needs update' ) 
 
531
                        profiles = self.get_profiles()
 
532
 
 
533
                        answer_change = self.question_handler( _('BackinTime changed its backup format.\n\nYour old snapshots can be moved according to this new format. OK?') )
 
534
                        #print answer_change
 
535
                        if answer_change == True:
 
536
                                logger.info( 'Update snapshot locations' )
 
537
                                #print len( profiles )
 
538
                                
 
539
                                if len( profiles ) == 1:
 
540
                                        logger.info( 'Only 1 profile found' )
 
541
                                        answer_same = True
 
542
                                elif len( profiles ) > 1:
 
543
                                        answer_same = self.question_handler( _('%s profiles found. \n\nThe new backup format supports storage of different users and profiles on the same location. Do you want the same location for both profiles? \n\n(The program will still be able to discriminate between them)') % len( profiles ) )
 
544
                                else:
 
545
                                        logger.warning( 'No profiles are found!' )
 
546
                                        self.notify_error( _( 'No profiles are found. Will have to update to profiles first, please restart BackinTime' ) )
 
547
                                        logger.info( 'Config version is %s' % str( self.get_int_value( 'config.version', 1 ) ) )
 
548
                                        
 
549
                                        if self.get_int_value( 'config.version', 1 ) > 1:
 
550
                                                self.set_int_value( 'config.version', 2 )
 
551
                                                logger.info( 'Config version set to 2' )
 
552
                                                return False
 
553
                                        
 
554
                                # Moving old snapshots per profile_id
 
555
                                #print answer_same
 
556
                                profile_id = profiles[0]
 
557
                                #print profile_id
 
558
                                #old_folder = self.get_snapshots_path( profile_id )
 
559
                                #print old_folder
 
560
                                main_folder = self.get_snapshots_path( profile_id )
 
561
                                old_snapshots_paths=[]
 
562
                                counter = 0
 
563
                                success = []
 
564
                                
 
565
                                for profile_id in profiles:
 
566
                                        #print counter
 
567
                                        old_snapshots_paths.append( self.get_snapshots_path( profile_id ) )
 
568
                                        #print old_snapshots_paths
 
569
                                        old_folder = os.path.join( self.get_snapshots_path( profile_id ), 'backintime' )
 
570
                                        #print old_folder
 
571
                                        if profile_id != "1" and answer_same == True:
 
572
                                                #print 'profile_id != 1, answer = True'
 
573
                                                self.set_snapshots_path( main_folder, profile_id )
 
574
                                                logger.info( 'Folder of profile %s is set to %s' %( profile_id, main_folder ) )
 
575
                                        else:
 
576
                                                self.set_snapshots_path( self.get_snapshots_path( profile_id ), profile_id )
 
577
                                                logger.info( 'Folder of profile %s is set to %s' %( profile_id, main_folder ) )
 
578
                                        new_folder = self.get_snapshots_full_path( profile_id )
 
579
                                        #print new_folder
 
580
                                        #snapshots_to_move = tools.get_snapshots_list_in_folder( old_folder )
 
581
                                        #print snapshots_to_move
 
582
 
 
583
                                        output = tools.move_snapshots_folder( old_folder, new_folder )
 
584
 
 
585
                                        snapshots_left = tools.get_snapshots_list_in_folder( old_folder )
 
586
                                        if output == True:
 
587
                                                success.append( True )
 
588
                                                if len( snapshots_left ) == 0:
 
589
                                                        logger.info( 'Update was successful. Snapshots of profile %s are moved to their new location' % profile_id )
 
590
                                                else:
 
591
                                                        logger.warning( 'Not all snapshots are removed from the original folder!' )
 
592
                                                        logger.info( 'The following snapshots are still present: %s' % snapshots_left )
 
593
                                                        logger.info( 'You could move them manually or leave them where they are now' )
 
594
                                        else:
 
595
                                                logger.warning( '%s: are not moved to their new location!' %snapshots_left )
 
596
                                                
 
597
                                                answer_unsuccessful = self.question_handler( _('%s\nof profile %s are not moved to their new location\nDo you want to proceed?\n(BackinTime will be able to continue taking snapshots, however the remaining snapshots will not be considered for automatic removal)\n\nIf not BackinTime will restore former settings for this profile, however cannot continue taking snapshots' %( snapshots_left, profile_id ) ) )
 
598
                                                if answer_unsuccessful == True:
 
599
                                                        success.append( True )
 
600
                                                else:
 
601
                                                        success.append( False )
 
602
                                                        # restore
 
603
                                                        logger.info( 'Restore former settings' )
 
604
                                                        self.set_snapshots_path( old_snapshots_paths[counter], profile_id )
 
605
                                                        #print self.get_snapshots_path( profile_id )
 
606
                                                        self.error_handler( _('Former settings of profile %s are restored.\nBackinTime cannot continue taking new snapshots.\n\nYou can manually move the snapshots, \nif you are done restart BackinTime to proceed' %profile_id ) )
 
607
                                        
 
608
                                        counter = counter + 1
 
609
                                
 
610
                                #print success
 
611
                                overall_success = True
 
612
                                for item in success:
 
613
                                        if item == False:
 
614
                                                overall_success = False 
 
615
                                if overall_success == True:
 
616
                                        self.set_update_other_folders( False )
 
617
                                        #print self.get_update_other_folders()
 
618
                                        logger.info( 'BackinTime will be able to make new snapshots again!' )
 
619
                                        self.error_handler( _('Update was successful!\n\nBackinTime will continue taking snapshots again as scheduled' ) )
 
620
                        elif answer_change == False:
 
621
                                logger.info( 'Move refused by user' )
 
622
                                logger.warning( 'Old snapshots are not taken into account by smart-remove' )
 
623
                                answer_continue = self.question_handler( _('Are you sure you do not want to move your old snapshots?\n\n\nIf you do, you will not see these questions again next time, BackinTime will continue making snapshots again, but smart-remove cannot take your old snapshots into account any longer!\n\nIf you do not, you will be asked again next time you start BackinTime.') )
 
624
                                if answer_continue == True:
 
625
                                        self.set_update_other_folders( False )
 
626
                                        for profile_id in profiles:
 
627
                                                old_folder = self.get_snapshots_path( profile_id )
 
628
                                                self.set_snapshots_path( old_folder, profile_id )
 
629
                                                logger.info( 'Folder of profile %s is set to %s' %( profile_id, self.get_snapshots_path( profile_id ) ) )
 
630
                                        
 
631
                                        logger.info( 'BackinTime will be able to make new snapshots again!' )
 
632
                                        self.error_handler( _('BackinTime will continue taking snapshots again as scheduled' ) )
 
633
                                else: 
 
634
                                        self.error_handler( _( 'BackinTime still cannot continue taking new snapshots.\nRestart BackinTime to see the questions again' ) )
 
635
                        else:
 
636
                                return False
 
637
                
 
638
        def can_backup( self, profile_id = None ):
 
639
                '''Checks if snapshots_path exists''' 
 
640
                if not self.is_configured( profile_id ):
425
641
                        return False
426
642
 
427
 
                if not os.path.isdir( self.get_snapshots_full_path() ):
 
643
                if not os.path.isdir( self.get_snapshots_full_path( profile_id ) ):
 
644
                        print "%s does not exist" % self.get_snapshots_full_path( profile_id )
428
645
                        return False
429
646
 
430
647
                return True
431
648
 
432
649
        def setup_cron( self ):
433
 
                #auto_backup_mode = self.get_automatic_backup_mode()
434
 
                min_backup_mode = self.NONE
435
 
                max_backup_mode = self.NONE
436
 
 
437
 
                if self.get_per_directory_schedule():
438
 
                        for item in self.get_include_folders():
439
 
                                backup_mode = item[1]
440
 
 
441
 
                                if self.NONE != backup_mode:
442
 
                                        if self.NONE == min_backup_mode:
443
 
                                                min_backup_mode = backup_mode
444
 
                                                max_backup_mode = backup_mode
445
 
                                        elif backup_mode < min_backup_mode:
446
 
                                                min_backup_mode = backup_mode
447
 
                                        elif backup_mode > max_backup_mode:
448
 
                                                max_backup_mode = backup_mode
 
650
                system_entry_message = "#Back In Time system entry, this will be edited by the gui:"
449
651
                
450
 
                        print "Min automatic backup: %s" % self.AUTOMATIC_BACKUP_MODES[ min_backup_mode ]
451
 
                        print "Max automatic backup: %s" % self.AUTOMATIC_BACKUP_MODES[ max_backup_mode ]
452
 
                else:
453
 
                        min_backup_mode = self.get_automatic_backup_mode()
454
 
                        max_backup_mode = min_backup_mode
455
 
                        print "Automatic backup: %s" % self.AUTOMATIC_BACKUP_MODES[ min_backup_mode ]
456
 
 
457
 
                if self.NONE == min_backup_mode:
 
652
                """We have to check if the system_entry_message is in use,
 
653
                if not then the entries are most likely from Back in Time 0.9.26
 
654
                or earlier."""
 
655
                if os.system( "crontab -l | grep '%s' > /dev/null" % system_entry_message ) != 0:
 
656
                        """Then the system entry message has not yet been used in this crontab
 
657
                        therefore we assume all entries are system entries and clear them all.
 
658
                        This is the old behaviour"""
 
659
                        print "Clearing all backintime entries"
458
660
                        os.system( "crontab -l | grep -v backintime | crontab -" )
459
 
                        return None #no automatic backup
460
 
 
461
 
                if not tools.check_command( 'crontab' ):
462
 
                        return _( 'Can\'t find crontab.\nAre you sure cron is installed ?\nIf not you should disable all automatic backups.' )
463
 
 
464
 
                #remove old cron
465
 
                os.system( "crontab -l | grep -v backintime | crontab -" )
466
 
 
467
 
                cron_line = ''
468
 
                
469
 
                if self._5_MIN == min_backup_mode:
470
 
                        cron_line = 'echo "*/5 * * * * {cmd}"'
471
 
                elif self._10_MIN == min_backup_mode:
472
 
                        cron_line = 'echo "*/10 * * * * {cmd}"'
473
 
                if self.HOUR == min_backup_mode:
474
 
                        cron_line = 'echo "@hourly {cmd}"'
475
 
                elif self.DAY == min_backup_mode:
476
 
                        cron_line = 'echo "@daily {cmd}"'
477
 
                elif self.WEEK == min_backup_mode and self.MONTH == max_backup_mode: #for every-week and every-month use every-day
478
 
                        cron_line = 'echo "@daily {cmd}"'
479
 
                elif self.WEEK == min_backup_mode:
480
 
                        cron_line = 'echo "@weekly {cmd}"'
481
 
                elif self.MONTH == min_backup_mode:
482
 
                        cron_line = 'echo "@monthly {cmd}"'
483
 
 
484
 
                if len( cron_line ) > 0:
485
 
                        cmd = '/usr/bin/backintime --backup-job >/dev/null 2>&1'
486
 
                        if self.is_run_nice_from_cron_enabled():
487
 
                                cmd = 'nice -n 19 ' + cmd
488
 
                        cron_line = cron_line.replace( '{cmd}', cmd )
489
 
                        os.system( "( crontab -l; %s ) | crontab -" % cron_line )
490
 
 
491
 
                return None
492
 
 
 
661
                
 
662
                print "Clearing system backintime entries"
 
663
                os.system( "crontab -l | grep -Pv '(?s)%s.*?backintime' | crontab -" % system_entry_message )
 
664
                
 
665
                profiles = self.get_profiles()
 
666
                
 
667
                for profile_id in profiles:
 
668
                        profile_name = self.get_profile_name( profile_id )
 
669
                        print "Profile: %s" % profile_name
 
670
                        min_backup_mode = self.NONE
 
671
                        max_backup_mode = self.NONE
 
672
 
 
673
                        if self.get_per_directory_schedule( profile_id ):
 
674
                                for item in self.get_include_folders( profile_id ):
 
675
                                        backup_mode = item[1]
 
676
 
 
677
                                        if self.NONE != backup_mode:
 
678
                                                if self.NONE == min_backup_mode:
 
679
                                                        min_backup_mode = backup_mode
 
680
                                                        max_backup_mode = backup_mode
 
681
                                                elif backup_mode < min_backup_mode:
 
682
                                                        min_backup_mode = backup_mode
 
683
                                                elif backup_mode > max_backup_mode:
 
684
                                                        max_backup_mode = backup_mode
 
685
                
 
686
                                print "Min automatic backup: %s" % self.AUTOMATIC_BACKUP_MODES[ min_backup_mode ]
 
687
                                print "Max automatic backup: %s" % self.AUTOMATIC_BACKUP_MODES[ max_backup_mode ]
 
688
                        else:
 
689
                                min_backup_mode = self.get_automatic_backup_mode( profile_id )
 
690
                                max_backup_mode = min_backup_mode
 
691
                                print "Automatic backup: %s" % self.AUTOMATIC_BACKUP_MODES[ min_backup_mode ]
 
692
 
 
693
                        if self.NONE == min_backup_mode:
 
694
                                continue
 
695
 
 
696
                        if not tools.check_command( 'crontab' ):
 
697
                                self.notify_error( _( 'Can\'t find crontab.\nAre you sure cron is installed ?\nIf not you should disable all automatic backups.' ) )
 
698
                                return False
 
699
 
 
700
                        cron_line = ''
 
701
                        
 
702
                        if self._5_MIN == min_backup_mode:
 
703
                                cron_line = 'echo "{msg}\n*/5 * * * * {cmd}"'
 
704
                        elif self._10_MIN == min_backup_mode:
 
705
                                cron_line = 'echo "{msg}\n*/10 * * * * {cmd}"'
 
706
                        if self.HOUR == min_backup_mode:
 
707
                                cron_line = 'echo "{msg}\n0 * * * * {cmd}"'
 
708
                        elif self.DAY == min_backup_mode:
 
709
                                cron_line = 'echo "{msg}\n15 15 * * * {cmd}"'
 
710
                        elif self.WEEK == min_backup_mode and self.MONTH == max_backup_mode: #for every-week and every-month use every-day
 
711
                                cron_line = 'echo "{msg}\n15 15 * * * {cmd}"'
 
712
                        elif self.WEEK == min_backup_mode:
 
713
                                cron_line = 'echo "{msg}\n15 15 * * 0 {cmd}"'
 
714
                        elif self.MONTH == min_backup_mode:
 
715
                                cron_line = 'echo "{msg}\n15 15 1 * * {cmd}"'
 
716
 
 
717
                        if len( cron_line ) > 0:
 
718
                                cmd = "/usr/bin/backintime --profile \\\"%s\\\" --backup-job >/dev/null 2>&1" % profile_name
 
719
                                if self.is_run_nice_from_cron_enabled( profile_id ):
 
720
                                        cmd = 'nice -n 19 ' + cmd
 
721
                                cron_line = cron_line.replace( '{cmd}', cmd )
 
722
                                cron_line = cron_line.replace( '{msg}', system_entry_message )
 
723
                                os.system( "( crontab -l; %s ) | crontab -" % cron_line )
 
724
 
 
725
                return True
 
726
        
 
727
        def get_update_other_folders( self ):
 
728
                return self.get_bool_value( 'update.other_folders', True )
 
729
                
 
730
        def set_update_other_folders( self, value ):
 
731
                self.set_bool_value( 'update.other_folders', value )
493
732
 
494
733
if __name__ == "__main__":
495
734
        config = Config()