freezer/freezer/engine/tar/tar_builders.py

165 lines
6.0 KiB
Python

"""
(c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Freezer Tar related functions
"""
from freezer.utils import utils
class TarCommandBuilder(object):
"""
Building a tar cmd command. To build command invoke method build.
"""
UNIX_TEMPLATE = (
"{gnutar_path} --create {algo} --warning=none --no-check-device "
"--one-file-system --preserve-permissions --same-owner "
"--seek --ignore-failed-read")
# local windows template
WINDOWS_TEMPLATE = (
"{gnutar_path} -c {algo} --incremental --unlink-first "
"--ignore-zeros")
LISTED_TEMPLATE = "{tar_command} --listed-incremental={listed_incremental}"
DEREFERENCE_MODE = {'soft': '--dereference',
'hard': '--hard-dereference',
'all': '--hard-dereference --dereference'}
def __init__(self, filepath, compression_algo, is_windows, tar_path=None):
self.tar_path = tar_path or utils.tar_path()
self.dereference = ''
self.listed_incremental = None
self.exclude = ''
self.openssl_path = None
self.encrypt_pass_file = None
self.output_file = None
self.filepath = filepath
self.compression_algo = get_tar_flag_from_algo(compression_algo)
self.is_windows = is_windows
def set_listed_incremental(self, absolute_path):
self.listed_incremental = absolute_path
def set_exclude(self, exclude):
self.exclude = exclude
def set_dereference(self, mode):
"""
Dereference hard and soft links according option choices.
'soft' dereference soft links,
'hard' dereference hardlinks,
'all' dereference both.
Default 'none'.
"""
self.dereference = self.DEREFERENCE_MODE[mode]
def set_encryption(self, encrypt_pass_file, openssl_path=None):
self.openssl_path = openssl_path or utils.openssl_path()
self.encrypt_pass_file = encrypt_pass_file
def build(self):
if self.is_windows:
tar_command = self.WINDOWS_TEMPLATE.format(
gnutar_path=self.tar_path, algo=self.compression_algo)
else:
tar_command = self.UNIX_TEMPLATE.format(
gnutar_path=self.tar_path, algo=self.compression_algo)
if self.dereference:
tar_command = "{0} {1}".format(tar_command, self.dereference)
if self.listed_incremental:
tar_command = self.LISTED_TEMPLATE.format(
tar_command=tar_command,
listed_incremental=self.listed_incremental)
if self.exclude:
tar_command = '{tar_command} --exclude="{exclude}"'.format(
tar_command=tar_command, exclude=self.exclude)
tar_command = '{0} {1}'.format(tar_command, self.filepath)
if self.encrypt_pass_file:
openssl_cmd = "{openssl_path} enc -aes-256-cfb -pass file:{file}"\
.format(openssl_path=self.openssl_path,
file=self.encrypt_pass_file)
tar_command = '{0} | {1}'.format(tar_command, openssl_cmd)
return tar_command
class TarCommandRestoreBuilder(object):
WINDOWS_TEMPLATE = '{0} -x {1} --incremental --unlink-first ' \
'--ignore-zeros'
DRY_RUN_TEMPLATE = '{0} {1} --incremental --list ' \
'--ignore-zeros --warning=none'
UNIX_TEMPLATE = '{0} {1} --incremental --extract --unlink-first ' \
'--ignore-zeros --warning=none --directory {2}'
OPENSSL_DEC = "{openssl_path} enc -d -aes-256-cfb -pass file:{file}"
def __init__(self, restore_path, compression_algo, is_windows,
tar_path=None):
self.dry_run = False
self.is_windows = False
self.openssl_path = None
self.encrypt_pass_file = None
self.tar_path = tar_path or utils.tar_path()
self.restore_path = restore_path
self.compression_algo = get_tar_flag_from_algo(compression_algo)
self.is_windows = is_windows
def set_dry_run(self):
self.dry_run = True
def set_encryption(self, encrypt_pass_file, openssl_path=None):
self.openssl_path = openssl_path or utils.openssl_path()
self.encrypt_pass_file = encrypt_pass_file
def build(self):
if self.dry_run:
tar_command = self.DRY_RUN_TEMPLATE.format(self.tar_path,
self.compression_algo)
elif self.is_windows:
tar_command = self.WINDOWS_TEMPLATE.format(self.tar_path,
self.compression_algo)
else:
tar_command = self.UNIX_TEMPLATE.format(self.tar_path,
self.compression_algo,
self.restore_path)
# Check if encryption file is provided and set the openssl decrypt
# command accordingly
if self.encrypt_pass_file:
openssl_cmd = self.OPENSSL_DEC.format(
openssl_path=self.openssl_path,
file=self.encrypt_pass_file)
tar_command = '{0} | {1}'.format(openssl_cmd, tar_command)
return tar_command
def get_tar_flag_from_algo(compression):
algo = {
'gzip': '-z',
'bzip2': '-j',
'xz': '-J',
}
compression_exec = utils.get_executable_path(compression)
if not compression_exec:
raise Exception("Critical Error: {0} executable not found ".
format(compression))
return algo.get(compression)