+++ /dev/null
-# low_backup_manager module
-# Authors: Nicholas Alexander && Otacilio Lacerda
-# Backup_manager class:
-# Class responsible for backup functions like creating and removing backups
-
-import os.path
-import os
-import zlib
-import pickle
-
-from PyQt4.QtCore import *
-from zipfile import *
-
-from pcsbackupparser import *
-from pcsbackupinfo import *
-from pcsbackupmanager import *
-from pcsbackupxml import *
-
-import pcsbackuputils as utils
-
-HOME = os.path.expanduser("~")
-BACKUP_FILES_PATH = os.path.join(HOME, ".pcsuite/Backup")
-DEFAULT_CONFIG_PATH = "%s/.pcsuite/config" % HOME
-BACKUPS_FILE = os.path.join(HOME, ".pcsuite/Backup/.backups")
-
-
-class PcsPcBackupManager(PcsBackupManager):
-
- def __init__(self):
- PcsBackupManager.__init__(self)
- self._backupList = []
- self.backupInProgress = False
- self.restoreInProgress = False
- self.copyInProgress = False
-
- self.myDocsPath = "Root/home/user/MyDocs/"
- self.backupPath = ""
- self.currentCategory = ""
- self.totalSize = 0
-
- def loadBackups(self):
- # 'XX Loading the backup list available in the PC'
- try:
- if os.path.exists(BACKUPS_FILE):
- file = open(BACKUPS_FILE)
- self._backupList = pickle.load(file)
- file.close()
- except IOError:
- print "IOError while loading the PC backups"
- # FIXME
- #raise Exception("Error while reading backups")
- return False
-
- return True
-
- def saveBackups(self):
- # 'XX Saving the backup list in the config file'
- try:
- obj = self._backupList
- file = open(BACKUPS_FILE, "w")
- pickle.dump(obj, file)
- file.close()
- except:
- #raise Exception("Error while saving backups")
- return False
-
- return True
-
- def getBackupList(self):
- """Return a list with the name of all done backups. """
- self.loadBackups()
- return self._backupList[:]
-
- def createBackup(self, backup_name, path, host_ip, categories, comment=""):
- self.backupThread = NewBackupThread(self, backup_name, path, host_ip,
- categories, comment)
- self.backupThread.start()
-
-
- def renameBackup(self, backupName, newName):
- self.loadBackups()
-
- backupInfo = self.getBackupInfo(backupName)
- if backupInfo != None:
- try:
- old = os.path.join(str(backupInfo.getPath()), str(backupName))
- new = os.path.join(str(backupInfo.getPath()), str(newName))
- os.rename(old, new)
- backupInfo.setName(newName)
- except:
- print "Error while changing backup name"
- return False
- else:
- # "Backup not found"
- return False
-
- self.saveBackups()
- return True
-
- def removeBackup(self, backupName):
- """
- Remove a backup from pc and from _backupList.
- """
- self.loadBackups()
- backupInfo = self.getBackupInfo(backupName)
- completePath = os.path.join(str(backupInfo.getPath()),
- str(backupInfo.getName()))
- if os.path.exists(completePath):
- utils.removePath(completePath)
- self._backupList.remove(backupInfo)
- self.saveBackups()
-
- return True
-
- def copyBackupToDevice(self, deviceIp, backupName, memoryStick):
- """ Copy a backup in the PC to some memory card inside the chosen device.
-
- Attributes:
- String deviceIp - String with ip address of device.
- String backupName - Name of backup to be copied.
- Int memoryStick - Integer representing which memory stick backup
- should be copied to.
- 0 - Removable memory stick
- 1 - Internal memory stick
- """
- try:
- self.loadBackups()
- mountPoint = os.path.join(DEVICES_POINT, "%s/Root" % deviceIp)
- utils.mountDevice(USER_HOST, deviceIp, mountPoint)
-
- backup = self.getBackupInfo(backupName)
- backupPath = os.path.join(str(backup.getPath()), str(backupName))
- if memoryStick != 0 and memoryStick != 1:
- return -1
- destination = os.path.join(mountPoint, 'media/mmc%s' %
- (memoryStick+1), 'backups', backupName)
-
- self.setCopyInProgress(True)
- if self.copy(backupPath, destination) == 0:
- return 0
- self.setCopyInProgress(False)
- finally:
- utils.unmountDevice(mountPoint)
-
-
- def getBackupInfo(self, backupName):
- for backupInfo in self._backupList:
- if backupInfo.getName() == backupName:
- return backupInfo
- return None
-
- def startBackupRestore(self, backupInfo, device_ip, categories):
- return self.restoreBackup(backupInfo, device_ip, categories)
-
- def setCopyInProgress(self, status):
- self.copyInProgress = status
-
- def setBackupInProgress(self, status):
- self.backupInProgress = status
-
-
- def setRestoreInProgress(self, status):
- self.restoreInProgress = status
-
- # FIXME: rewrite this method. Add error handling, some more reliable code
- def _runCreateBackup(self, backup_name, path, host_ip, categories, comment=""):
- """Create a backup and add it to _backupList.
-
- Backup all files and directories of categories chosen. The device
- system file is mounted on PC and them files are compressed in a zip
- format. All zip files from each category are saved in the given path.
-
- Arguments:
- backup_name -- Backup's name. This name will be the name of the backup
- folder.
- path -- Location to save Backup file
- host_ip -- The device IP address.
- categories -- A python dictonary where the keys are the categories from
- osso-backup, and the value can be either True or False, to identify
- which categories to backup.
- comment -- Any comment about the backup. It will be saved in Backup
- object.
-
- """
-
- backupInfo = None
- self.setBackupInProgress(True)
- self.currentCategory = ""
-
- try:
- # Mount device folders
- self.loadBackups()
- mountPoint = os.path.join(DEVICES_POINT, "%s/Root" % host_ip)
- utils.mountDevice(USER_HOST, host_ip, mountPoint)
-
- # Create backup folder in the given path
- self.backupPath = os.path.join(str(path), backup_name)
- self._createBackupFolder(self.backupPath)
-
- # Copying osso-backup configuration files to TabletSuite folder and
- # parsing backup information from these files.
- # ( Information = which paths should be in each backup category)
- utils.copyOssoBackupConfigFiles(DEFAULT_CONFIG_PATH, mountPoint)
- xmlParser = PcsBackupParser()
- xmlParser.fillLocationsDict(DEFAULT_CONFIG_PATH)
- backupItemDict = xmlParser.getLocationsDict()
-
- # Changing work directory to ease file search. Keeping previous
- # folder to come back after backup process.
- current_dir = os.getcwd()
- workPath = DEVICES_POINT + str(host_ip)
- os.chdir(workPath)
-
- # Computing total size that this backup will have.
- self.totalSize = self._getTotalSize(backupItemDict, categories)
-
-
- # Start backup process. Create backup of paths for each locations
- # category
- self.backedUpNumber = 0
- filesByCategory = {}
- for category in backupItemDict.keys():
- self.currentCategory = category
-
- for backupItem in backupItemDict[category]:
- self._emitProgress()
- # If current backupInfo category is valid and it's value is
- # True in categories dictionary, add it to current backup.
- if (category in categories) and (categories[category]):
- categoryFilesNumber = 0
- categoryFile = os.path.join(self.backupPath,
- category + '.zip')
-
- if os.path.exists(categoryFile):
- zipfile = utils.openZip(categoryFile, 'a')
- else:
- zipfile = utils.openZip(categoryFile, 'w')
-
- objPath = backupItem.path.replace('/','Root/',1)
- backupFolder = os.path.join(workPath, objPath)
- categoryFilesNumber = self.zipFolder(backupFolder,
- zipfile, objPath,
- category)
- if categoryFilesNumber == -1:
- os.chdir(current_dir)
- return 0
- self.backedUpNumber += categoryFilesNumber
- self._emitProgress()
-
- # Update the filesByCategory dictionary with the
- # current number of files from current category that
- # were already copied.
- self._updateCategoryCount(filesByCategory, category,
- categoryFilesNumber)
- utils.closeZip(zipfile)
- # If category had no file to copy remove its folder
- if int(utils.getSize(categoryFile) == 0):
- os.remove(categoryFile)
-
-
- # Copying media files from device user folder if media category is
- # True in categories dictionary.
- if ("media" in categories) and (categories["media"]):
- self.currentCategory = "media"
- result = self._backupMedias(workPath)
- if result == -1:
- os.chdir(current_dir)
- return 0
- # Update backup files number count
- self.backedUpNumber += result
- self._updateCategoryCount(filesByCategory, "media", result)
- zipPath = os.path.join(self.backupPath,'media.zip')
- if int(utils.getSize(zipPath) == 0):
- os.remove(zipPath)
-
-
- # Copying documents files from device user folder if documents
- # category is True in categories dictionary.
- if ("documents" in categories) and (categories["documents"]):
- self.currentCategory = "documents"
- result = self._backupDocuments(workPath)
- # Update backup files number count
- self.backedUpNumber += result
- if result == -1:
- os.chdir(current_dir)
- return 0
- self._updateCategoryCount(filesByCategory, "documents",
- result)
- zipPath = os.path.join(self.backupPath, 'documents.zip')
- if int(utils.getSize(zipPath) == 0):
- os.remove(zipPath)
-
-
- # Change to previous work directory
- os.chdir(current_dir)
-
- if self.backedUpNumber == 0:
- utils.removePath(self.backupPath)
- return -1
-
- # Create Backup Object, add it to this manager backup list and save
- # the list in the backup file.
- backup_size = utils.getSize(self.backupPath)
- backupInfo = PcsBackupInfo(backup_name, path, backup_size, comment)
- backupInfo.setFilesNumber(self.backedUpNumber)
- self._backupList.append(backupInfo)
- self.saveBackups()
-
- createXml(backupInfo, filesByCategory, host_ip)
- self.setBackupInProgress(False)
- finally:
- utils.unmountDevice(mountPoint)
-
- return backupInfo
-
-
- def _backupDocuments(self, workPath):
- """ Create backup of documents files in user folder. """
- categoryFilesNumber = 0
- destinationPath = os.path.join(self.backupPath,'documents.zip')
- if os.path.exists(destinationPath):
- zipfile = utils.openZip(destinationPath, 'a')
- else:
- zipfile = utils.openZip(destinationPath, 'w')
-
- docsPath = os.path.join(self.myDocsPath, ".documents")
-
- if os.path.exists(docsPath):
- backupPath = os.path.join(workPath, docsPath)
- categoryFilesNumber = self.zipFolder(backupPath, zipfile, docsPath,
- "documents")
-
- utils.closeZip(zipfile)
- return categoryFilesNumber
-
-
- def _backupMedias(self, workPath):
- """ Create backup of media files in user folder. """
- categoryFilesNumber = 0
- destinationPath = os.path.join(self.backupPath,'media.zip')
- if os.path.exists(destinationPath):
- zipfile = utils.openZip(destinationPath, 'a')
- else:
- zipfile = utils.openZip(destinationPath, 'w')
-
- userFilesPath = self.myDocsPath
- if os.path.exists(os.path.join(userFilesPath)):
- for folder in os.listdir(userFilesPath):
- if folder != '.documents':
- objPath = os.path.join(userFilesPath, folder)
- backupDir = os.path.join(workPath, objPath)
- result = self.zipFolder(backupDir, zipfile,
- objPath, "media")
- if result != -1:
- categoryFilesNumber += result
- else:
- return result
-
- utils.closeZip(zipfile)
- return categoryFilesNumber
-
-
- def _createBackupFolder(self, newBackupPath):
- if not utils.createFolder(newBackupPath):
- return False
-
-
- def _emitProgress(self):
- currentSize = utils.getSize(self.backupPath)
- percentage = self.computePercentage(self.totalSize, currentSize)
- self.emit(SIGNAL("backupProgress"), (percentage, self.currentCategory))
-
-
- def _getTotalSize(self, backupFileDict, categories):
- size = 0
- for category in backupFileDict.keys():
- for backupItem in backupFileDict[category]:
- if (category in categories) and (categories[category]):
- objPath = backupItem.path.replace('/','Root/',1)
- size += utils.getSize(objPath)
-
- if categories["documents"]:
- size += utils.getSize(os.path.join(self.myDocsPath,
- ".documents"))
- if categories["media"]:
- for folder in os.listdir(self.myDocsPath):
- if folder != '.documents':
- objPath = os.path.join(self.myDocsPath, folder)
- size += utils.getSize(objPath)
- return size
-
- def _updateCategoryCount(self, filesByCategory, category, backed_up_number):
- if str(category) not in filesByCategory.keys():
- filesByCategory[category] = backed_up_number
- else:
- filesByCategory[category] += backed_up_number
-
-
- def _verify_backup_name(self, backup_name):
- """ Check if already exists any backup with the given name inside the
- pc backup list. In case there is one, this function will return another
- name to be set as the new backup name, else it will return the same
- name that was given.
-
- """
- if self.getBackupInfo(backup_name) != None:
- counter = 1
- new_name = backup_name + "%02d" % counter
- while(self.getBackupInfo(new_name)) != None:
- counter += 1
- new_name = backup_name + "%02d" % counter
-
- backup_name = new_name
- return backup_name
-
- def zipFolder(self, path, zipfile, obj_path, category):
- # Compress the folder from the given path, with all directories and
- # files inside it
- # zipfile: The ZipFile object to append the folder
- # obj_path: The ZipFile path
- count = 0
- self._emitProgress()
- if os.path.exists(path):
- if os.path.isdir(path):
- files = os.listdir(path)
- for node in files:
- if os.path.isdir(os.path.join(path, node)):
- zipCount = self.zipFolder(os.path.join(path, node), zipfile,
- os.path.join(obj_path, node), category)
- if zipCount == -1:
- return -1
- else:
- count += zipCount
- else:
- # Check if backup was canceled and return -1 case positive
- if not self.backupInProgress:
- utils.removePath(self.backupPath)
- return -1
-
- if utils.zip(zipfile, os.path.join(obj_path, node)):
- count += 1
- self._emitProgress()
- else:
- # Check if backup was canceled and return -1 case positive
- if not self.backupInProgress:
- utils.removePath(self.backupPath)
- return -1
-
- if utils.zip(zipfile, obj_path):
- count += 1
- self._emitProgress()
- return count
-
-
-
-class NewBackupThread(QThread):
- def __init__(self, manager, backupName, path, hostIp, categories, comment):
- QThread.__init__(self)
-
- self.manager = manager
- self.backupName = backupName
- self.path = path
- self.hostIp = hostIp
- self.categories = categories
- self.comment = comment
-
- def run(self):
- ret = self.manager._runCreateBackup (self.backupName, self.path,
- self.hostIp, self.categories,
- str(self.comment))
- self.manager.emit(SIGNAL("backupDone"), ret,
- (self.manager.totalSize, self.manager.backedUpNumber))
-
-
-
\ No newline at end of file