From: Eduardo Robles Elvira Date: Sun, 28 Jul 2013 08:44:10 +0000 (+0200) Subject: fixing and unit testing multivolume support X-Git-Tag: v2.2~141 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=d5361dac9c34391e51672cc201bf2b8174df4e0d;p=python-delta-tar fixing and unit testing multivolume support --- diff --git a/deltatar/deltatar.py b/deltatar/deltatar.py index bd8ccab..fa57ac0 100644 --- a/deltatar/deltatar.py +++ b/deltatar/deltatar.py @@ -266,8 +266,8 @@ class DeltaTar(object): - source_path: source path to the directory to back up. - backup_path: path where the back up will be stored. Backup path will be created if not existent. - - max_volume_size: maximum volume size. Used to split the backup in - volumes. Optional (won't split in volumes by default). + - max_volume_size: maximum volume size in megabytes. Used to split the + backup in volumes. Optional (won't split in volumes by default). ''' # check input if not isinstance(source_path, basestring): @@ -280,6 +280,11 @@ class DeltaTar(object): raise Exception('Source path "%s" does not exist or is not a '\ 'directory' % source_path) + if max_volume_size != None and not isinstance(max_volume_size, int): + raise Exception('max_volume_size must be an integer') + if max_volume_size != None: + max_volume_size = max_volume_size*1024*1024 + if not os.access(source_path, os.R_OK): raise Exception('Source path "%s" is not readable' % source_path) @@ -315,13 +320,25 @@ class DeltaTar(object): # TODO: encrypt or compress it if necessary index_fd = open(index_path, 'w') - def new_volume_handler(deltarobj, tarobj, base_name, volume_number): + cwd = os.getcwd() + + def new_volume_handler(deltarobj, cwd, backup_path, tarobj, base_name, volume_number): ''' Handles the new volumes ''' - volume_path = deltarobj.volume_name_func(True, volume_number) - tarobj.open_volume(volume_path) - new_volume_handler = partial(new_volume_handler, self) + volume_name = deltarobj.volume_name_func(backup_path, True, volume_number) + volume_path = os.path.join(backup_path, volume_name) + + # we convert relative paths into absolute because CWD is changed + if not os.path.isabs(volume_path): + volume_path = os.path.join(cwd, volume_path) + try: + tarobj.open_volume(volume_path) + except Exception, e: + import ipdb; ipdb.set_trace() + + # wraps some args from context into the handler + new_volume_handler = partial(new_volume_handler, self, cwd, backup_path) index_fd.write('{"type": "python-delta-tar-index", version: "1" }\n') @@ -339,7 +356,7 @@ class DeltaTar(object): max_volume_size=max_volume_size, new_volume_handler=new_volume_handler) - cwd = os.getcwd() + os.chdir(source_path) for path in self._recursive_walk_dir('.'): # TODO: reduce paths length using previous dir entries @@ -413,13 +430,22 @@ class DeltaTar(object): if not os.path.exists(target_path): os.makedirs(target_path) - def new_volume_handler(deltarobj, tarobj, base_name, volume_number): + backup_path = os.path.dirname(backup_tar_path) + cwd = os.getcwd() + def new_volume_handler(deltarobj, cwd, backup_path, tarobj, base_name, volume_number): ''' Handles the new volumes ''' - volume_path = deltarobj.volume_name_func(True, volume_number) + volume_name = deltarobj.volume_name_func(backup_path, True, volume_number) + volume_path = os.path.join(backup_path, volume_name) + + # we convert relative paths into absolute because CWD is changed + if not os.path.isabs(volume_path): + volume_path = os.path.join(cwd, volume_path) tarobj.open_volume(volume_path) - new_volume_handler = partial(new_volume_handler, self) + + # wraps some args from context into the handler + new_volume_handler = partial(new_volume_handler, self, cwd, backup_path) tarobj = tarfile.TarFile.open(backup_tar_path, mode='r' + self.mode, @@ -427,7 +453,6 @@ class DeltaTar(object): concat_compression='#gz' in self.mode, password=self.password, new_volume_handler=new_volume_handler) - cwd = os.getcwd() os.chdir(target_path) tarobj.extractall() os.chdir(cwd) diff --git a/deltatar/tarfile.py b/deltatar/tarfile.py index 1734c7b..879597a 100644 --- a/deltatar/tarfile.py +++ b/deltatar/tarfile.py @@ -1714,7 +1714,8 @@ class TarFile(object): else: if name is None and hasattr(fileobj, "name"): name = fileobj.name - if hasattr(fileobj, "mode"): + # when fileobj is a gzip.GzipFile, fileobj.mode is an int (not valid for us) + if hasattr(fileobj, "mode") and isinstance(fileobj.mode, basestring): self._mode = fileobj.mode self._extfileobj = True self.base_name = self.name = os.path.abspath(name) if name else None diff --git a/testing/test_deltatar.py b/testing/test_deltatar.py index d2d04e3..c5ba719 100644 --- a/testing/test_deltatar.py +++ b/testing/test_deltatar.py @@ -39,12 +39,14 @@ class DeltaTarTest(BaseTest): ''' Create base test data ''' + os.system('rm -rf source_dir backup_dir') os.makedirs('source_dir/test/test2') self.hash = dict() self.hash["source_dir/test/test2"] = '' self.hash["source_dir/big"] = self.create_file("source_dir/big", 50000) self.hash["source_dir/small"] = self.create_file("source_dir/small", 100) self.hash["source_dir/test/huge"] = self.create_file("source_dir/test/huge", 700000) + self.hash["source_dir/test/huge2"] = self.create_file("source_dir/test/huge2", 800000) self.consoleLogger = logging.StreamHandler() self.consoleLogger.setLevel(logging.DEBUG) @@ -119,6 +121,41 @@ class DeltaTarTest(BaseTest): elif began_list: crc = binascii.crc32(l, crc) & 0xffffffff + def test_create_multivol(self): + ''' + Creates a full backup without any filtering with multiple volumes. + ''' + deltatar = DeltaTar(mode=self.MODE, password=self.PASSWORD, + logger=self.consoleLogger) + + # create first backup + deltatar.create_full_backup( + source_path="source_dir", + backup_path="backup_dir", + max_volume_size=1) + + assert os.path.exists("backup_dir") + assert os.path.exists(os.path.join("backup_dir", + deltatar.volume_name_func("backup_dir", True, 0))) + assert os.path.exists(os.path.join("backup_dir", + deltatar.volume_name_func("backup_dir", True, 1))) + assert os.path.exists(os.path.join("backup_dir", + deltatar.volume_name_func("backup_dir", True, 2))) + + shutil.rmtree("source_dir") + + tar_filename = deltatar.volume_name_func('backup_dir', True, 0) + tar_path = os.path.join("backup_dir", tar_filename) + + # this should automatically restore all volumes + deltatar.restore_backup(target_path="source_dir", + backup_tar_path=tar_path) + + for key, value in self.hash.iteritems(): + assert os.path.exists(key) + if value: + assert value == self.md5sum(key) +