def check_store(wiz): config = Config.get_config() store_name = wiz.fields["name"].value if store_name in config.storage: dlg.Warn(wiz, "That name is already in use", "Duplicate Store") return False return True
def __init__(self, parent): ''' Constructor ''' log.info("***RestorePanel.init") gui.RestorePanel.__init__(self, parent) self.db = DB() self.config = Config.get_config() self.images = wx.ImageList(16, 16) self.images.Add( wx.Bitmap(os.path.join(const.PixmapDir, "folder.png"), wx.BITMAP_TYPE_PNG) ) self.images.Add( wx.Bitmap(os.path.join(const.PixmapDir, "document.png"), wx.BITMAP_TYPE_PNG) ) self.fs_tree.SetImageList(self.images) # Looks better if this is blank. self.set_selected_file("") self.force_rebuild() self.image = wx.Bitmap(os.path.join(const.PixmapDir, "review.png")) self.title = _("Restore") # Ensure the right page is showing self.nb_restore.SetSelection(0) log.trace("Done RestorePanel.init")
def __init__(self, parent, default_name=None): ''' Constructor ''' gui.HistoryWindow.__init__(self, parent) log.trace("Starting up a history panel") self.db = DB() self.config = Config.get_config() self.order = const.ASC self.update_data(default_name) # self.imgList = wx.ImageList(16, 16) # self.img_up = self.imgList.Add(wx.Bitmap("images/go-up.png", wx.BITMAP_TYPE_PNG)) # self.img_down = self.imgList.Add(wx.Bitmap("images/go-down.png", wx.BITMAP_TYPE_PNG)) # self.lstRuns.SetImageList(self.imgList, wx.IMAGE_LIST_SMALL) icon = wx.Icon(os.path.join(const.PixmapDir, "storage.png"), wx.BITMAP_TYPE_ANY) self.SetIcon(icon) # listmix.ColumnSorterMixin.__init__(self, 7) # self.Bind(wx.EVT_LIST_COL_CLICK, self.onColClick, self.lstRuns) # self.SortListItems(2, 1) # Ensure the right page is showing self.nb_history.SetSelection(0) self.Show()
def do_rebuilddb(parent): config = Config.get_config() wiz = wizard.Wizard(parent, _("Backup Database Recovery"), _("Welcome to the Backup Database Recovery wizard.\n" "\n" "This wizard will interrogate your stores to recover information\n" "about your backed up files. This information is stored locally and\n" "means that backup software can tell you about saved files without\n" "need to contact and read from the store.\n" "\n" "Note that this wizard does not actually recover files, it just recovers\n" "information about those files."), _("We are now ready to restore your backup information."), wiz_execute, icon=os.path.join(const.PixmapDir, "storage.png")) # Type of storage page = wizard.Page(wiz, _("Choose Backups")) backups = config.backups.keys() backups.sort() wizard.LabelField(page, "label", _("Choose which backups to recover details for. This does not recover your\n" "actual files themselves, just information about which files were backed\n" "up and when. Usually you will want to select all.")) for backup in backups: wizard.CheckField(page, backup, None, backup, default=False if not const.Debug else True) # Run the wizard wiz.run()
def __init__(self, parent): ''' Constructor ''' log.info("***BackupPanel.init") gui.BackupPanel.__init__(self, parent) self.btnAddFolder.SetBitmapLabel(wx.Bitmap(os.path.join(const.PixmapDir, "add.png"))) self.db = DB() self.config = Config.get_config() self.state = ViewState self.update_data(False) self.nbBackup.SetSelection(0) self.clear() self.nbBackup.Layout() self.Fit() self.radSchedDailyWeekly.SetValue(True) if self.lstItems.GetCount() > 0: self.lstItems.SetSelection(0) self.onItemSelected(None) # self.onNotifyEmail(None) self.image = wx.Bitmap(os.path.join(const.PixmapDir, "backup.png")) self.title = _("Backups") self.onBackupSchedule(None) log.trace("Done BackupPanel.init")
def __init__(self, parent): ''' Constructor ''' log.info("***ConfigPanel.init") gui.ConfigPanel.__init__(self, parent) self.config = Config.get_config() self.db = DB() self.state = ViewState self.update_filetype_list() self.clear_filetype() self.image = wx.Bitmap(os.path.join(const.PixmapDir, "configure.png")) self.title = _("Configuration") if self.lstFileTypes.GetCount() > 0: self.lstFileTypes.SetSelection(0) self.onFileType(None) self.show_mail() self.txtMailServer.SetFocus() self.nb_config.SetSelection(0) self.show_security() self.pwd_hidden = True self.mail_hidden = True log.trace("Done ConfigPanel.init")
def check_backup(wiz): config = Config.get_config() backup_name = wiz.fields["name"].value if backup_name in config.backups: dlg.Warn(wiz, "That name is already in use", "Duplicate Backup") return False return True
def wiz_execute(wiz): log.debug("Executing backup creation wizard") config = Config.get_config() name = wiz.fields["name"].value path = wiz.fields["folderpath"].value excl = [] for typ in config.file_types.iterkeys(): if wiz.fields['excl-'+typ].value: excl.append(typ) store = wiz.fields["store"].value b = Backup(name) b.active = True b.include_folders = [path] b.include_packages = True b.exclude_types = excl b.store = store b.excrypt = False b.sched_type = "daily/weekly" b.sched_times = "19:00/Sun" b.verify = False b.notify_msg = True b.notify_email = False b.shutdown_after = False config.backups[name] = b config.save() update_crontab(config.backups) dlg.Info(wiz, _("Your backup has been successfully created.")) app.broadcast_update()
def __init__(self, parent): ''' Constructor ''' log.info("***StorePanel.init") gui.StoragePanel.__init__(self, parent) self.db = DB() self.config = Config.get_config() self.state = ViewState self.load_static_data() self.update_store_list() self.clear() if self.lstItems.GetCount() > 0: self.lstItems.SetSelection(0) self.onItemSelected(None) self.onAutoManage(None) self.image = wx.Bitmap(os.path.join(const.PixmapDir, "storage.png")) self.title = _("Storage") self.ftp_hidden = True self.db_hidden = True log.trace("Done StorePanel.init")
def __init__(self, test_folder, options): self.test_folder = os.path.join(test_folder, "tester") self.options = options self.config = Config.get_config() self.store_folder = os.path.join(self.test_folder, "stores") self.files_folder = os.path.join(self.test_folder, "files") self.restore_folder = os.path.join(self.test_folder, "restore") self.db = DB() self.max_fs_id = self.db.query("select max(fs_id) from fs", ())[0][0] if self.max_fs_id is None: self.max_fs_id = 0 self.max_version_id = self.db.query("select max(version_id) from versions", ())[0][0] if self.max_version_id is None: self.max_version_id = 0 self.max_run_id = self.db.query("select max(run_id) from runs", ())[0][0] if self.max_run_id is None: self.max_run_id = 0 self.max_message_id = self.db.query("select max(message_id) from messages", ())[0][0] if self.max_message_id is None: self.max_message_id = 0 log.debug("MAX IDs", self.max_fs_id, self.max_version_id, self.max_run_id, self.max_message_id) self.teststring1 = os.urandom(204800) self.teststring2 = os.urandom(204800)
def wiz_execute(wiz): db = DB() config = Config.get_config() backups = config.backups.keys() backups.sort() for name in backups: if wiz.fields[name].value: # Get the backup object and store backup = config.backups[name] store = config.storage[backup.store].copy() # For each run on the store with ProgressDialog(wiz, _("Connecting"), _("Connecting to the store.\nPlease wait...")): store.connect() prog_dlg = ProgressDialog(wiz, _("Loading"), _("Retrieving data from store.\nPlease wait...")) prog_dlg.Show() try: try: runs = store.list(backup.name) except: # If it fails, there were no backup runs runs = [] runs.sort() for run in runs: (date, type) = run.split(" ") date = datetime.strptime(date, const.DateTimeFormat) db.start_run(backup.name, store.name, type, date) db.save_message(_("Database rebuild started")) try: store_size, _file_sizes, nfiles, nfolders = recover_run(config, db, backup, store, run) db.save_message(_("Database rebuild complete")) db.update_run_stats(store_size, nfiles, nfolders, backup.include_packages, "") db.update_run_status(const.StatusSuccess) except Exception as e: msg = _("Database rebuild failed. {error}").format(error=str(e)) db.save_message(msg) db.update_run_status(const.StatusFailed) dlg.Warn(wiz, msg, _("Error")) return finally: prog_dlg.Destroy() store.disconnect() wiz.parent.force_rebuild() # Now tell app about change. app.broadcast_update() dlg.Info(wiz, _("Your backup files database has been rebuilt.\nYou can now view your file and backup history."), _("Rebuild"))
def __init__(self, backup_name, run_date): ''' Verify a run to ensure it is valid ''' self.config = Config.get_config() self.backup = self.config.backups[backup_name] self.store = self.config.storage[self.backup.store].copy() self.db = DB() # Find the run runs = self.db.runs(self.backup.name, run_date) if len(runs) == 0: raise Exception(_("Verify failed: Backup run does not exist")) self.vrun = runs[0]
def wiz_execute(wiz): # Connect if wiz.fields["storagetype"].value == _("Local Folder"): name = wiz.fields["name"].value path = wiz.fields["folderpath"].value store = FolderStore(name, 0, False, path) elif wiz.fields["storagetype"].value == _("FTP Server"): name = wiz.fields["name"].value server = wiz.fields["ftpserver"].value login = wiz.fields["ftplogin"].value password = wiz.fields["ftppassword"].value root = wiz.fields["ftproot"].value sftp = wiz.fields["sftp"].value store = FTPStore(name, 0, False, server, root, login, password, sftp) log.debug("Store = ", store) elif wiz.fields["storagetype"].value == _("DropBox"): name = wiz.fields["name"].value login = wiz.fields["dblogin"].value password = wiz.fields["dbpassword"].value root = wiz.fields["dbroot"].value key = wiz.fields["dbkey"].value secret_key = wiz.fields["dbsecretkey"].value store = DropBoxStore(name, 0, False, root, login, password, key, secret_key) elif wiz.fields["storagetype"].value == _("Amazon S3"): name = wiz.fields["name"].value key = wiz.fields["s3key"].value secret_key = wiz.fields["s3secretkey"].value bucket = wiz.fields["s3bucket"].value store = S3Store(name, 0, False, bucket, key, secret_key) elif wiz.fields["storagetype"].value == _("Server Share"): name = wiz.fields["name"].value path = wiz.fields["sharepath"].value mountcmd = wiz.fields["sharemountcmd"].value umountcmd = wiz.fields["shareumountcmd"].value store = ShareStore(name, 0, False, path, mountcmd, umountcmd) try: with ProgressDialog(wiz, _("Creating Store"), _("Creating and testing new store.\nPlease wait...")): # we will rely on the user to test the store # store.test() config = Config.get_config() config.storage[store.name] = store config.save() dlg.Info(wiz, _("Store successfully created.")) app.broadcast_update() except Exception as e: dlg.Warn(wiz, str(e), _("Failed to create store"))
def __init__(self, name, type, options): ''' Prepare to run a backup event @param name: name of the backup @param type: type (Full/Incr) @param type: dry_run If dry_run is True, then we will print the files we *would have* backed up to stdout. ''' self.type = type self.dry_run = options.dry_run self.options = options self.config = Config.get_config() try: self.backup = self.config.backups[name] except: raise Exception(_("Backup is missing or corrupt. Please reconfigure backup.")) try: # Get a fresh store (a copy of the config version self.store = self.config.storage[self.backup.store].copy() except: raise Exception(_("Storage definition is missing. Please reconfigure backup.")) self.db = DB() self.start_time = None self.nfiles = None self.nfolders = None self.bytes = None self.run_id = None self.backup_folder = None # Make sure there are no other backups running of this name self.lock = locking.InterProcessLock(name="Vault-%s" % self.backup.name) # Build a quick file exclusion list, to speed up exclusion checking self.excl_ext = self.build_excl_exts() log.debug("Exclusion List:", ",".join(self.excl_ext))
def __init__(self, parent): ''' Constructor ''' log.info("***OverviewPanel.init") gui.OverviewPanel.__init__(self, parent) self.imgStatus.SetBitmap(wx.Bitmap(os.path.join(const.PixmapDir, "status-ok.png"))) self.db = DB() self.config = Config.get_config() self.update_data() self.image = wx.Bitmap(os.path.join(const.PixmapDir, "overview.png")) self.title = "Overview" self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.update_data, self.timer) # Update the display every 30 seconds self.timer.Start(30000) log.trace("Done OverviewPanel.init")
def setUp(self): self.config = Config.get_config() self.db = DB() self.db.check_upgrade() self.mark_db_ids() self.test_folder = tempfile.mkdtemp() self.files_folder = os.path.join(self.test_folder, "files") self.store_folder = os.path.join(self.test_folder, "store") self.restore_folder = os.path.join(self.test_folder, "restore") utils.makedirs(self.files_folder) utils.makedirs(self.store_folder) utils.makedirs(self.restore_folder) utils.build_file_structure(self.files_folder, 50 * const.Kilobyte, 500 * const.Kilobyte) # Build a store object (dont save config) # Note the careful size selection - we want backups to overflow the FolderStore. self.store = FolderStore("teststore", "2MB", True, self.store_folder) self.config.storage[self.store.name] = self.store # Build the backup object (dont save config) self.backup = Backup("testbackup") self.backup.include_folders = [self.files_folder] self.backup.store = self.store.name self.backup.notify_msg = False self.include_packages = True self.config.backups[self.backup.name] = self.backup # build an options object for use with the backup self.options = BlankClass() self.options.dry_run = False self.options.message = False self.options.email = False self.options.shutdown = False self.options.norecurse = False self.old_pass = self.config.data_passphrase self.config.data_passphrase = "banana"
def __init__(self, parent, run): ''' Constructor ''' gui.RunDetailsWindow.__init__(self, parent) log.info("Starting up a run details window") self.run = run self.db = DB() self.config = Config.get_config() self.paths = {} self.load_run_details() self.load_files(200) self.load_messages() icon = wx.Icon(os.path.join(const.PixmapDir, "storage.png"), wx.BITMAP_TYPE_ANY) self.SetIcon(icon) # Ensure the right page is showing self.nbDetails.SetSelection(0) self.Show()
def do_backup_wizard(parent): config = Config.get_config() wiz = wizard.Wizard(parent, _("Backup Creation Wizard"), _("Welcome to the backup creation wizard.\n" "\n" "The first time you use The Vault, you need to define\n" "what you want backed up and where to. This wizard will guide you\n" "through the creation of your backup."), _("We are now ready to create the backup."), wiz_execute, icon=os.path.join(const.PixmapDir, "storage.png")) # Name page = wizard.Page(wiz, _("Backup Name"), check_cb = check_backup) wizard.TextField(page, "name", _("What shall we call this backup?"), default=None if not const.Debug else "TestName") # Type of Folder page = wizard.Page(wiz, _("Backup What Folder")) wizard.DirEntryField(page, "folderpath", _("What folder should be backed up"), must_exist=True, default=None if not const.Debug else os.path.join(const.RunDir, "files")) # Exclude File Types names = [key for key in config.file_types.iterkeys()] names.sort() page = wizard.Page(wiz, _("Excluded Files")) wizard.LabelField(page, "excl", _("Select which file types to *exclude* from the backup")) for name in names: wizard.CheckField(page, "excl-"+name, None, name, default=None if not const.Debug else False) page = wizard.Page(wiz, _("Store")) print(config.storage.keys()) wizard.OptionsField(page, "store", _("Which store should this be saved to?"), config.storage.keys()) # Run the wizard wiz.run()
def __init__(self, parent, backup_name): ''' Constructor ''' gui.RunBackupWindow.__init__(self, parent) log.trace("Starting up a run backup window") self.config = Config.get_config() self.cboBackup.AppendItems(self.config.backups.keys()) self.cboBackup.SetStringSelection(backup_name) self.status(_("Idle")) self.lock = threading.Lock() self.proc = None self.btnStop.Enable(False) self.pnlDryRun.Hide() self.Layout() self.Fit() self.Show() icon = wx.Icon(os.path.join(const.PixmapDir, "storage.png"), wx.BITMAP_TYPE_ANY) self.SetIcon(icon)
def wiz_execute(wiz): # Connect if wiz.fields["storagetype"].value == _("Local Folder"): store = FolderStore("store", 0, False, wiz.fields["folderpath"].value) elif wiz.fields["storagetype"].value == _("FTP Server"): server = wiz.fields["ftpserver"].value login = wiz.fields["ftplogin"].value password = wiz.fields["ftppassword"].value root = wiz.fields["ftproot"].value sftp = wiz.fields["sftp"].value store = FTPStore("store", 0, False, server, root, login, password, sftp) elif wiz.fields["storagetype"].value == _("DropBox"): login = wiz.fields["dblogin"].value password = wiz.fields["dbpassword"].value root = wiz.fields["dbroot"].value store = DropBoxStore("store", 0, False, root, login, password) elif wiz.fields["storagetype"].value == _("Server Share"): mountcmd = wiz.fields["mountcmd"].value umountcmd = wiz.fields["umountcmd"].value shareroot = wiz.fields["shareroot"].value store = ShareStore("store", 0, False, shareroot, mountcmd, umountcmd) else: raise Exception("Internal error: bad store type") log.debug("Store = ", store) # In case we need to revert our config later orig_config = Config.get_config() try: store.connect() folders = [] # List all backups backups = store.list(".") for backup in backups: # Make sure its not a system folder if backup[0] != "_": try: runs = store.list(backup + "/") for run in runs: folders.append((backup, run)) except: pass log.debug("Folders", folders) if len(folders) == 0: raise Exception(_("There are no backup runs in this store")) # Sort them based on the path name folders.sort(key=lambda item: item[1], reverse=True) # Now the first item is the one to use (as it is the most recent). backupname, backuprun = folders[0] config = os.path.join(backupname, backuprun, const.ConfigName) configenc = config + const.EncryptionSuffix # Check if the config exists. if store.exists(config): src = config encrypted = False elif store.exists(configenc): src = configenc encrypted = True else: raise Exception(_("The backup runs are missing or corrupt (no config files)")) if not encrypted: store.get(src, const.ConfigDir+os.sep) else: # Fetch the file. enc_file = const.ConfigFile + const.EncryptionSuffix clear_file = const.ConfigFile store.get(src, const.ConfigDir+os.sep) # ENCRYPTED bad = True # keep going until we get a good password while bad: password = GetPassword(wiz, backupname, backuprun) if password == None: # User is quitting return # Lets check the file is good. try: log.debug("Decrypting", enc_file, clear_file, password) ret = cryptor.decrypt_file(password, enc_file, clear_file) log.debug("Return from decrypt", ret) if ret != 0: raise Exception(_("Failed encryption")) bad = False if os.path.exists(enc_file): os.remove(enc_file) # Looks like this password is a good one. except: log.info("Invalid backup password") dlg.Warn(wiz, _("Invalid password. Please enter the correct backup password.")) os.remove(clear_file) # Revert the old config orig_config.save() dlg.Info(wiz, _("Your configuration has been restored.\nClick OK to restart the UI..."), _("Restore")) python = sys.executable log.debug("Starting:", const.UIProgram) subprocess.Popen(const.UIProgram) app.quit() except Exception as e: dlg.Warn(wiz, str(e), _("Configuration restore failed")) finally: store.disconnect()
def sendemail(subject, message_text): config = Config.get_config() if not (config.mail_server and config.mail_port and config.mail_to and config.mail_from): raise Exception("Mail has not been configured") sendemail2(config.mail_server, config.mail_port, config.mail_ssl, config.mail_from, config.mail_to, config.mail_auth, config.mail_login, config.mail_password, subject, message_text)
def setUp(self): self.config = Config.get_config() self.db = DB() self.db.check_upgrade() self.mark_db_ids() self.test_folder = tempfile.mkdtemp() self.files_folder = os.path.join(self.test_folder, "files") self.store_folder = os.path.join(self.test_folder, "store") self.restore_folder = os.path.join(self.test_folder, "restore") utils.makedirs(self.files_folder) utils.makedirs(self.store_folder) utils.makedirs(self.restore_folder) # Build the base set of files with open(os.path.join(self.files_folder, "base"), "w") as f: f.write("base") with open(os.path.join(self.files_folder, "incr"), "w") as f: f.write("0") config_file = os.path.expanduser("~/.vault") if not os.path.exists(config_file): raise Exception("Vault test configuration file (~/.vault) does not exist") self.store_config = ConfigParser.RawConfigParser() self.store_config.read(config_file) # FOLDER STORE self.store = FolderStore("teststore", "50MB", True, self.store_folder) # DROPBOX STORE # self.login = self.store_config.get("DropBox", "login") # self.password = self.store_config.get("DropBox", "password") # self.folder = self.store_config.get("DropBox", "folder") # self.app_key = self.store_config.get("DropBox", "app_key") # self.app_secret_key = self.store_config.get("DropBox", "app_secret_key") # self.store = DropBoxStore("teststore", 0, False, self.folder, self.login, self.password, # self.app_key, self.app_secret_key) # S3 STORE # self.key = self.store_config.get("Amazon", "aws_access_key_id") # self.secret_key = self.store_config.get("Amazon", "aws_secret_access_key") # self.bucket = self.store_config.get("Amazon", "bucket") # self.store = S3Store("teststore", 0, False, bucket=self.bucket, key=self.key, secret_key=self.secret_key) # Now record the existance of this store self.config.storage[self.store.name] = self.store # Build the backup object (dont save config) self.backup = Backup("testbackup") self.backup.include_folders = [self.files_folder] self.backup.store = self.store.name self.backup.notify_msg = False self.old_pass = self.config.data_passphrase self.config.data_passphrase = "goofy" self.backup.encrypt = True self.config.backups[self.backup.name] = self.backup # build an options object for use with the backup self.options = BlankClass() self.options.dry_run = False self.options.message = False self.options.email = False self.options.shutdown = False self.options.norecurse = False # How many cycles? self.cycles = 20
import gettext gettext.bindtextdomain(const.AppTitle, const.LocaleDir) gettext.textdomain(const.AppTitle) _ = gettext.gettext gettext.install(const.AppTitle) # Do this first (of the app imports) from lib.logger import LogManager LogManager(const.LogFile) # This next line sets up defaults from lib.config import Config Config.get_config() from lib.db import DB from server.run import Run from server.restore import Restore from server.tester import Tester # Do this last! from lib.logger import Logger log = Logger("server")
def __init__(self): self.host = Config.get_config("cassandra", "host") self.key_space = Config.get_config("cassandra", "key_space") self.operators = {"==":pycassa.index.EQ} self.types = {"UTF8Type":pycassa.system_manager.UTF8_TYPE}