From 6347638461113a45cf97fcd80656c6af64237a4d Mon Sep 17 00:00:00 2001 From: Sergey Abramov Date: Fri, 18 Mar 2016 13:01:59 +0300 Subject: [PATCH] move remote logs and create links on it After restore there are no logs on existent nodes in Nailgun UI. In /var/log/docker-logs/remote they exists and have access by ip addr. Move logs from ip addr path to FQDN path and create symlink ip addr path to fqdn path. If ip addr path doesn't exists create empty fqdn path dir and create link to it with ip addr path name to this directory. Change-Id: Ic82fc30082c2a743e79d3495a6d87bab17e2c742 Closes-bug: 1552643 (cherry picked from commit ecbfd3fbc7973323c4cb0fb4dc62e7db4edbd0c0) --- octane/handlers/backup_restore/postgres.py | 26 ++++++++ octane/tests/test_archivators_restore.py | 78 ++++++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/octane/handlers/backup_restore/postgres.py b/octane/handlers/backup_restore/postgres.py index 1c0d7943..0699730d 100644 --- a/octane/handlers/backup_restore/postgres.py +++ b/octane/handlers/backup_restore/postgres.py @@ -12,11 +12,13 @@ import json import logging +import os import requests import six import urlparse import yaml +from fuelclient.objects import node from keystoneclient.v2_0 import Client as keystoneclient from octane.handlers.backup_restore import base @@ -95,6 +97,29 @@ class NailgunArchivator(PostgresArchivator): for args in magic_consts.NAILGUN_ARCHIVATOR_PATCHES: docker.apply_patches(*args, revert=True) + def _create_links_on_remote_logs(self): + with open("/etc/fuel/astute.yaml") as astute: + domain = yaml.load(astute)["DNS_DOMAIN"] + dirname = "/var/log/docker-logs/remote/" + pairs = [(n.data["meta"]["system"]["fqdn"], n.data["ip"]) + for n in node.Node.get_all()] + docker.run_in_container("rsyslog", ["service", "rsyslog", "stop"]) + try: + for fqdn, ip_addr in pairs: + if not fqdn.endswith(domain): + continue + ip_addr_path = os.path.join(dirname, ip_addr) + fqdn_path = os.path.join(dirname, fqdn) + if os.path.islink(ip_addr_path): + continue + if os.path.isdir(ip_addr_path): + os.rename(ip_addr_path, fqdn_path) + else: + os.mkdir(fqdn_path) + os.symlink(fqdn, ip_addr_path) + finally: + docker.run_in_container("rsyslog", ["service", "rsyslog", "start"]) + def _post_restore_action(self): data, _ = docker.run_in_container( "nailgun", @@ -141,6 +166,7 @@ class NailgunArchivator(PostgresArchivator): ','.join(["({0}, '{1}')".format(*v) for v in values])) docker.run_in_container( "postgres", sql_run_prams + [sql], stdout=subprocess.PIPE) + self._create_links_on_remote_logs() class KeystoneArchivator(PostgresArchivator): diff --git a/octane/tests/test_archivators_restore.py b/octane/tests/test_archivators_restore.py index 662aaeb6..cc6b5f92 100644 --- a/octane/tests/test_archivators_restore.py +++ b/octane/tests/test_archivators_restore.py @@ -476,6 +476,8 @@ def test_post_restore_action_astute(mocker): ), ]) def test_post_restore_nailgun(mocker, mock_open, dump, calls, data_for_update): + mock_links = mocker.patch.object( + postgres.NailgunArchivator, "_create_links_on_remote_logs") data = yaml.dump(dump) mock_subprocess_call = mocker.patch("octane.util.subprocess.call") run_in_container_mock = mocker.patch( @@ -533,6 +535,7 @@ def test_post_restore_nailgun(mocker, mock_open, dump, calls, data_for_update): stdout=subprocess.PIPE ) json_mock.assert_called_with({"deployed_before": {"value": True}}) + mock_links.assert_called_once_with() @pytest.mark.parametrize("exc_on_apply", [True, False]) @@ -576,3 +579,78 @@ def test_post_restore_puppet_apply_host(mocker, mock_open, exc_on_apply): "/etc/fuel/astute.yaml") mkstemp_mock.assert_called_once_with( dir="/etc/fuel", prefix=".astute.yaml.octane") + + +@pytest.mark.parametrize("nodes", [ + [("node_1", True), ("node_2", True), ("node_3", True)], + [("node_1", False)], + [("node_1", False), ("node_2", False), ("node_3", False)], + [("node_1", False), ("node_2", True), ("node_3", False)], +]) +@pytest.mark.parametrize("is_dir", [True, False]) +@pytest.mark.parametrize("exception", [True, False]) +def test_create_links_on_remote_logs( + mocker, mock_open, nodes, is_dir, exception): + domain_name = "test_domain" + mocker.patch("yaml.load", return_value={"DNS_DOMAIN": domain_name}) + domain_names = [] + fuel_client_values = [] + is_link_exists = [] + moved_nodes = [] + for idx, node_link_exits in enumerate(nodes): + node, link_exists = node_link_exits + node_domain_name = "{0}.{1}".format(node, domain_name) + domain_names.append(node_domain_name) + ip_addr = "10.21.10.{0}".format(idx + 1) + fuel_client_mock = mocker.Mock() + fuel_client_mock.data = { + "meta": { + "system": { + "fqdn": node_domain_name + } + }, + "ip": ip_addr, + } + fuel_client_values.append(fuel_client_mock) + is_link_exists.append(link_exists) + if not link_exists: + moved_nodes.append((node_domain_name, ip_addr)) + is_link_mock = mocker.patch("os.path.islink", side_effect=is_link_exists) + mocker.patch("os.path.isdir", return_value=is_dir) + mocker.patch("fuelclient.objects.node.Node.get_all", + return_value=fuel_client_values) + run_in_container_mock = mocker.patch( + "octane.util.docker.run_in_container") + rename_mock = mocker.patch("os.rename") + symlink_mock = mocker.patch("os.symlink") + mkdir_mock = mocker.patch("os.mkdir") + archivator = backup_restore.postgres.NailgunArchivator(None) + if not exception: + + class TestException(Exception): + pass + + is_link_mock.side_effect = TestException("test exc") + with pytest.raises(TestException): + archivator._create_links_on_remote_logs() + assert not mkdir_mock.called + assert not rename_mock.called + else: + archivator._create_links_on_remote_logs() + path = "/var/log/docker-logs/remote/" + path_pairs = [(os.path.join(path, d), os.path.join(path, i)) + for d, i in moved_nodes] + sym_calls = [mock.call(d, os.path.join(path, i)) + for d, i in moved_nodes] + if is_dir: + assert [mock.call(i, d) for d, i in path_pairs] == \ + rename_mock.call_args_list + assert not mkdir_mock.called + else: + assert [mock.call(d) for d, _ in path_pairs] == \ + mkdir_mock.call_args_list + assert not rename_mock.called + assert sym_calls == symlink_mock.call_args_list + assert [mock.call("rsyslog", ["service", "rsyslog", "stop"]), + mock.call("rsyslog", ["service", "rsyslog", "start"])] == \ + run_in_container_mock.call_args_list