fuel-octane/octane/handlers/backup_restore/base.py

145 lines
4.2 KiB
Python

# 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.
import os
import re
from octane.util import archivate
from octane.util import docker
from octane.util import subprocess
class Base(object):
def __init__(self, archive, context=None):
self.archive = archive
self.context = context
@property
def archivator_name(self):
name = re.sub(
'([A-Z]+)', r' \1', self.__class__.__name__
).lower().strip()
for replacer in ["archivator", "backup"]:
if name.endswith(replacer):
name = name[:-len(replacer)].strip()
return name
def backup(self):
raise NotImplemented
def restore(self):
raise NotImplemented
def pre_restore_check(self):
pass
class ContainerArchivator(Base):
banned_files = []
backup_directory = None
allowed_files = None
container = None
def backup(self):
assert self.container
assert self.backup_directory
stdout, _ = docker.run_in_container(
self.container,
["find", self.backup_directory, "-type", "f"],
stdout=subprocess.PIPE)
filenames = stdout.strip().split()
for filename in filenames:
filename = filename[len(self.backup_directory):].lstrip("\/")
if filename in self.banned_files:
continue
if self.allowed_files is not None \
and filename not in self.allowed_files:
continue
path = os.path.join(self.backup_directory, filename)
archivate.archivate_container_cmd_output(
self.archive,
self.container,
["cat", path],
"{0}/{1}".format(self.container, filename)
)
def restore(self):
assert self.container
assert self.backup_directory
for member in archivate.filter_members(self.archive, self.container):
dump = self.archive.extractfile(member.name).read()
name = member.name.split("/", 1)[-1]
docker.write_data_in_docker_file(
self.container,
os.path.join(self.backup_directory, name),
dump
)
class CmdArchivator(Base):
container = None
cmd = None
filename = None
def backup(self):
assert self.cmd
assert self.container
assert self.filename
archivate.archivate_container_cmd_output(
self.archive, self.container, self.cmd, self.filename)
class DirsArchivator(Base):
path = None
tag = None
def backup(self):
assert self.path
assert self.tag
archivate.archive_dirs(self.archive, self.path, self.tag)
def restore(self):
assert self.path
assert self.tag
for member in archivate.filter_members(self.archive, self.tag):
member.name = member.name.split("/", 1)[-1]
self.archive.extract(member, self.path)
class PathArchivator(Base):
path = None
name = None
def backup(self):
assert self.path
assert self.name
self.archive.add(self.path, self.name)
def pre_restore_check(self):
members = list(archivate.filter_members(self.archive, self.name))
if os.path.isfile(self.path) and len(members) > 1:
raise Exception("try to restore in file more than 1 member")
def restore(self):
for member in archivate.filter_members(self.archive, self.name):
if os.path.isfile(self.path):
path, member.name = os.path.split(self.path)
else:
member.name = member.name.split("/", 1)[-1]
path = self.path
self.archive.extract(member, path)