133 lines
4.6 KiB
Python
133 lines
4.6 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 logging
|
|
import shutil
|
|
import yaml
|
|
|
|
from octane.handlers.backup_restore import base
|
|
from octane import magic_consts
|
|
from octane.util import docker
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class AstuteArchivator(base.PathArchivator):
|
|
path = "/etc/fuel/astute.yaml"
|
|
name = "astute/astute.yaml"
|
|
|
|
keys_to_restore = [
|
|
("HOSTNAME", None),
|
|
("DNS_DOMAIN", None),
|
|
("DNS_SEARCH", None),
|
|
("DNS_UPSTREAM", None),
|
|
("ADMIN_NETWORK", [
|
|
"ipaddress",
|
|
"netmask",
|
|
"dhcp_pool_start",
|
|
"dhcp_pool_end",
|
|
"dhcp_gateway",
|
|
]),
|
|
("astute", ["user", "password"]),
|
|
("cobbler", ["user", "password"]),
|
|
("keystone", [
|
|
"admin_token",
|
|
"ostf_user",
|
|
"ostf_password",
|
|
"nailgun_user",
|
|
"nailgun_password",
|
|
"monitord_user",
|
|
"monitord_password",
|
|
]),
|
|
("mcollective", ["user", "password"]),
|
|
("postgres", [
|
|
"keystone_dbname",
|
|
"keystone_user",
|
|
"keystone_password",
|
|
"nailgun_dbname",
|
|
"nailgun_user",
|
|
"nailgun_password",
|
|
"ostf_dbname",
|
|
"ostf_user",
|
|
"ostf_password",
|
|
]),
|
|
("FUEL_ACCESS", ["user", "password"]),
|
|
]
|
|
|
|
def get_backup_dict(self):
|
|
return yaml.load(self.archive.extractfile(self.name))
|
|
|
|
def get_current_dict(self):
|
|
with open(self.path, "r") as current:
|
|
return yaml.load(current)
|
|
|
|
def pre_restore_check(self):
|
|
names = docker.get_docker_container_names(status="running")
|
|
containers = set(magic_consts.RUNNING_REQUIRED_CONTAINERS) - set(names)
|
|
if containers:
|
|
raise Exception(
|
|
"Required running containers: {0}".format(
|
|
", ".join(containers)))
|
|
backup_ip = self.get_backup_dict()["ADMIN_NETWORK"]["ipaddress"]
|
|
current_ip = self.get_current_dict()["ADMIN_NETWORK"]["ipaddress"]
|
|
if backup_ip != current_ip:
|
|
raise Exception(
|
|
"Restore allowed on machine with same ipaddress. "
|
|
"Use fuel-menu to set up ipaddress to {0}".format(backup_ip))
|
|
|
|
def restore(self):
|
|
backup_yaml = self.get_backup_dict()
|
|
current_yaml = self.get_current_dict()
|
|
not_found_keys = []
|
|
for key, subkeys in self.keys_to_restore:
|
|
if not subkeys and key not in backup_yaml:
|
|
not_found_keys.append(key)
|
|
continue
|
|
if not subkeys:
|
|
current_yaml[key] = backup_yaml[key]
|
|
continue
|
|
backup_values = backup_yaml.get(key, {})
|
|
current_yaml[key] = current_yaml.get(key, {})
|
|
for subkey in subkeys:
|
|
if subkey not in backup_values:
|
|
not_found_keys.append("{0}/{1}".format(key, subkey))
|
|
else:
|
|
current_yaml[key][subkey] = backup_values[subkey]
|
|
if not_found_keys:
|
|
raise Exception(
|
|
"Not found values in backup for keys: {0}".format(
|
|
",".join(not_found_keys)))
|
|
old_path_name = "{0}.old".format(self.path)
|
|
new_path_name = "{0}.new".format(self.path)
|
|
shutil.copy2(self.path, old_path_name)
|
|
with open(new_path_name, "w") as new:
|
|
yaml.safe_dump(current_yaml, new, default_flow_style=False)
|
|
shutil.move(new_path_name, self.path)
|
|
self._post_restore_action()
|
|
|
|
def _post_restore_action(self):
|
|
# restart all running containers
|
|
for name in magic_consts.RUNNING_REQUIRED_CONTAINERS:
|
|
docker.stop_container(name)
|
|
# FIXME: when astute container restart corrent this may be removed
|
|
if "astute" == name:
|
|
try:
|
|
docker.start_container(name)
|
|
except Exception:
|
|
LOG.warn(
|
|
"Failed to start astute container for the first time")
|
|
docker.stop_container(name)
|
|
else:
|
|
continue
|
|
docker.start_container(name)
|