Ejemplo n.º 1
0
    def load(self,
             node_name_list=None,
             name="corosync_conf.load",
             filename="corosync.conf",
             auto_tie_breaker=None,
             instead=None):
        content = open(rc(filename)).read()
        corosync_conf = None
        if node_name_list:
            corosync_conf = ConfigFacade.from_string(content).config
            for nodelist in corosync_conf.get_sections(name="nodelist"):
                corosync_conf.del_section(nodelist)

            nodelist_section = Section("nodelist")
            corosync_conf.add_section(nodelist_section)
            for i, node_name in enumerate(node_name_list):
                node_section = Section("node")
                node_section.add_attribute("ring0_addr", node_name)
                node_section.add_attribute("nodeid", i)
                node_section.add_attribute("name", node_name)
                nodelist_section.add_section(node_section)

        if auto_tie_breaker is not None:
            corosync_conf = (corosync_conf if corosync_conf else
                             ConfigFacade.from_string(content).config)
            for quorum in corosync_conf.get_sections(name="quorum"):
                quorum.set_attribute("auto_tie_breaker",
                                     "1" if auto_tie_breaker else "0")

        if corosync_conf:
            content = corosync_conf.export()

        self.load_content(content, name=name, instead=instead)
Ejemplo n.º 2
0
def _check_if_atb_can_be_disabled(
    service_manager: ServiceManagerInterface,
    report_processor: ReportProcessor,
    corosync_conf: CorosyncConfFacade,
    was_enabled: bool,
    force: bool = False,
) -> None:
    """
    Check whenever auto_tie_breaker can be changed without affecting SBD.
    Raises LibraryError if change of ATB will affect SBD functionality.

    service_manager --
    report_processor -- report processor
    corosync_conf -- corosync conf facade
    was_enabled -- True if ATB was enabled, False otherwise
    force -- force change
    """
    if (was_enabled and not corosync_conf.is_enabled_auto_tie_breaker() and
            sbd.is_auto_tie_breaker_needed(service_manager, corosync_conf)):
        report_processor.report(
            ReportItem(
                severity=reports.item.get_severity(
                    reports.codes.FORCE,
                    force,
                ),
                message=(reports.messages.
                         CorosyncQuorumAtbCannotBeDisabledDueToSbd()),
            ))
        if report_processor.has_errors:
            raise LibraryError()
Ejemplo n.º 3
0
    def fixture_corosync_conf(self, node1_name=True, node2_name=True):
        # nodelist is enough, nothing else matters for the tests
        config = dedent("""\
            nodelist {
                node {
                    ring0_addr: node-1-addr
                    nodeid: 1
                    name: node-1
                }

                node {
                    ring0_addr: node-2-addr
                    nodeid: 2
                    name: node-2
                }
            }
            """
        )
        if not node1_name:
            config = re.sub(r"\s+name: node-1\n", "\n", config)
        if not node2_name:
            config = re.sub(r"\s+name: node-2\n", "\n", config)
        self.corosync_conf_text = config
        self.corosync_conf_facade = CorosyncConfigFacade.from_string(config)
        CorosyncConfigFacade.need_stopped_cluster = False
        CorosyncConfigFacade.need_qdevice_reload = False
Ejemplo n.º 4
0
    def test_corosync_conf_not_set_need_offline_success(
            self, mock_get_corosync, mock_distribute, mock_is_running,
            mock_reload, mock_check_offline, mock_qdevice_reload):
        corosync_data = open(rc("corosync.conf")).read()
        new_corosync_data = corosync_data.replace("version: 2", "version: 3")
        mock_get_corosync.return_value = corosync_data
        mock_is_running.return_value = False
        env = LibraryEnvironment(self.mock_logger, self.mock_reporter)

        self.assertTrue(env.is_corosync_conf_live)

        self.assertEqual(corosync_data, env.get_corosync_conf_data())
        self.assertEqual(corosync_data,
                         env.get_corosync_conf().config.export())
        self.assertEqual(2, mock_get_corosync.call_count)

        conf_facade = CorosyncConfigFacade.from_string(new_corosync_data)
        conf_facade._need_stopped_cluster = True
        env.push_corosync_conf(conf_facade)
        mock_check_offline.assert_called_once_with("mock node communicator",
                                                   self.mock_reporter,
                                                   "mock node list", False)
        mock_distribute.assert_called_once_with("mock node communicator",
                                                self.mock_reporter,
                                                "mock node list",
                                                new_corosync_data, False)
        mock_reload.assert_not_called()
        mock_qdevice_reload.assert_not_called()
Ejemplo n.º 5
0
    def test_corosync_conf_set(self, mock_get_corosync, mock_distribute,
                               mock_reload, mock_check_offline,
                               mock_qdevice_reload):
        corosync_data = "totem {\n    version: 2\n}\n"
        new_corosync_data = "totem {\n    version: 3\n}\n"
        env = LibraryEnvironment(self.mock_logger,
                                 self.mock_reporter,
                                 corosync_conf_data=corosync_data)

        self.assertFalse(env.is_corosync_conf_live)

        self.assertEqual(corosync_data, env.get_corosync_conf_data())
        self.assertEqual(corosync_data,
                         env.get_corosync_conf().config.export())
        self.assertEqual(0, mock_get_corosync.call_count)

        env.push_corosync_conf(
            CorosyncConfigFacade.from_string(new_corosync_data))
        self.assertEqual(0, mock_distribute.call_count)

        self.assertEqual(new_corosync_data, env.get_corosync_conf_data())
        self.assertEqual(0, mock_get_corosync.call_count)
        mock_check_offline.assert_not_called()
        mock_reload.assert_not_called()
        mock_qdevice_reload.assert_not_called()
Ejemplo n.º 6
0
    def test_corosync_conf_not_set_need_offline_success(
        self, mock_get_corosync, mock_distribute, mock_is_running, mock_reload,
        mock_check_offline, mock_qdevice_reload
    ):
        corosync_data = open(rc("corosync.conf")).read()
        new_corosync_data = corosync_data.replace("version: 2", "version: 3")
        mock_get_corosync.return_value = corosync_data
        mock_is_running.return_value = False
        env = LibraryEnvironment(self.mock_logger, self.mock_reporter)

        self.assertTrue(env.is_corosync_conf_live)

        self.assertEqual(corosync_data, env.get_corosync_conf_data())
        self.assertEqual(corosync_data, env.get_corosync_conf().config.export())
        self.assertEqual(2, mock_get_corosync.call_count)

        conf_facade = CorosyncConfigFacade.from_string(new_corosync_data)
        conf_facade._need_stopped_cluster = True
        env.push_corosync_conf(conf_facade)
        mock_check_offline.assert_called_once_with(
            "mock node communicator",
            self.mock_reporter,
            "mock node list",
            False
        )
        mock_distribute.assert_called_once_with(
            "mock node communicator",
            self.mock_reporter,
            "mock node list",
            new_corosync_data,
            False
        )
        mock_reload.assert_not_called()
        mock_qdevice_reload.assert_not_called()
Ejemplo n.º 7
0
    def test_corosync_conf_set(
        self, mock_get_corosync, mock_distribute, mock_reload,
        mock_check_offline, mock_qdevice_reload
    ):
        corosync_data = "totem {\n    version: 2\n}\n"
        new_corosync_data = "totem {\n    version: 3\n}\n"
        env = LibraryEnvironment(
            self.mock_logger,
            self.mock_reporter,
            corosync_conf_data=corosync_data
        )

        self.assertFalse(env.is_corosync_conf_live)

        self.assertEqual(corosync_data, env.get_corosync_conf_data())
        self.assertEqual(corosync_data, env.get_corosync_conf().config.export())
        self.assertEqual(0, mock_get_corosync.call_count)

        env.push_corosync_conf(
            CorosyncConfigFacade.from_string(new_corosync_data)
        )
        self.assertEqual(0, mock_distribute.call_count)

        self.assertEqual(new_corosync_data, env.get_corosync_conf_data())
        self.assertEqual(0, mock_get_corosync.call_count)
        mock_check_offline.assert_not_called()
        mock_reload.assert_not_called()
        mock_qdevice_reload.assert_not_called()
Ejemplo n.º 8
0
    def test_corosync_conf_not_set(
        self, mock_get_corosync, mock_distribute, mock_reload
    ):
        corosync_data = open(rc("corosync.conf")).read()
        new_corosync_data = corosync_data.replace("version: 2", "version: 3")
        mock_get_corosync.return_value = corosync_data
        env = LibraryEnvironment(self.mock_logger, self.mock_reporter)

        self.assertTrue(env.is_corosync_conf_live)

        self.assertEqual(corosync_data, env.get_corosync_conf_data())
        self.assertEqual(corosync_data, env.get_corosync_conf().config.export())
        self.assertEqual(2, mock_get_corosync.call_count)

        env.push_corosync_conf(
            CorosyncConfigFacade.from_string(new_corosync_data)
        )
        mock_distribute.assert_called_once_with(
            "mock node communicator",
            self.mock_reporter,
            "mock node list",
            new_corosync_data,
            False
        )
        mock_reload.assert_called_once_with("mock cmd runner")
Ejemplo n.º 9
0
 def test_success(self):
     new_corosync_conf_data = "totem {\n    version: 3\n}\n"
     self.config.env.push_corosync_conf(
         corosync_conf_text=new_corosync_conf_data)
     env = self.env_assistant.get_env()
     env.push_corosync_conf(
         CorosyncConfigFacade.from_string(new_corosync_conf_data))
Ejemplo n.º 10
0
    def fixture_corosync_conf(self, node1_name=True, node2_name=True):
        # nodelist is enough, nothing else matters for the tests
        config = dedent("""\
            nodelist {
                node {
                    ring0_addr: node-1-addr
                    nodeid: 1
                    name: node-1
                }

                node {
                    ring0_addr: node-2-addr
                    nodeid: 2
                    name: node-2
                }
            }
            """
        )
        if not node1_name:
            config = re.sub(r"\s+name: node-1\n", "\n", config)
        if not node2_name:
            config = re.sub(r"\s+name: node-2\n", "\n", config)
        self.corosync_conf_text = config
        self.corosync_conf_facade = CorosyncConfigFacade.from_string(config)
        CorosyncConfigFacade.need_stopped_cluster = False
        CorosyncConfigFacade.need_qdevice_reload = False
Ejemplo n.º 11
0
 def test_success(self):
     new_corosync_conf_data = "totem {\n    version: 3\n}\n"
     self.config.env.push_corosync_conf(
         corosync_conf_text=new_corosync_conf_data
     )
     env = self.env_assistant.get_env()
     env.push_corosync_conf(
         CorosyncConfigFacade.from_string(new_corosync_conf_data)
     )
Ejemplo n.º 12
0
    def load(
        self,
        node_name_list=None,
        name="corosync_conf.load",
        filename="corosync.conf",
        auto_tie_breaker=None,
        instead=None,
    ):
        # pylint: disable=too-many-locals
        with open(rc(filename)) as a_file:
            content = a_file.read()
        corosync_conf = None
        if node_name_list:
            corosync_conf = ConfigFacade(
                Parser.parse(content.encode("utf-8"))
            ).config
            for nodelist in corosync_conf.get_sections(name="nodelist"):
                corosync_conf.del_section(nodelist)

            nodelist_section = Section("nodelist")
            corosync_conf.add_section(nodelist_section)
            for i, node_name in enumerate(node_name_list):
                node_section = Section("node")
                node_section.add_attribute("ring0_addr", node_name)
                node_section.add_attribute("nodeid", i)
                node_section.add_attribute("name", node_name)
                nodelist_section.add_section(node_section)

        if auto_tie_breaker is not None:
            corosync_conf = (
                corosync_conf
                if corosync_conf
                else ConfigFacade(Parser.parse(content.encode("utf-8"))).config
            )
            for quorum in corosync_conf.get_sections(name="quorum"):
                quorum.set_attribute(
                    "auto_tie_breaker", "1" if auto_tie_breaker else "0"
                )

        if corosync_conf:
            content = corosync_conf.export()

        self.load_content(content, name=name, instead=instead)
Ejemplo n.º 13
0
    def load(
        self, node_name_list=None, name="corosync_conf.load",
        filename="corosync.conf", auto_tie_breaker=None, instead=None
    ):
        content = open(rc(filename)).read()
        corosync_conf = None
        if node_name_list:
            corosync_conf = ConfigFacade.from_string(content).config
            for nodelist in corosync_conf.get_sections(name="nodelist"):
                corosync_conf.del_section(nodelist)

            nodelist_section = Section("nodelist")
            corosync_conf.add_section(nodelist_section)
            for i, node_name in enumerate(node_name_list):
                node_section = Section("node")
                node_section.add_attribute("ring0_addr", node_name)
                node_section.add_attribute("nodeid", i)
                node_section.add_attribute("name", node_name)
                nodelist_section.add_section(node_section)


        if auto_tie_breaker is not None:
            corosync_conf = (
                corosync_conf if corosync_conf
                else ConfigFacade.from_string(content).config
            )
            for quorum in corosync_conf.get_sections(name="quorum"):
                quorum.set_attribute(
                    "auto_tie_breaker",
                    "1" if auto_tie_breaker else  "0"
                )

        if corosync_conf:
            content = corosync_conf.export()

        self.load_content(content, name=name, instead=instead)
Ejemplo n.º 14
0
Archivo: sbd.py Proyecto: mirecheck/pcs
def atb_has_to_be_enabled(
    service_manager: ServiceManagerInterface,
    corosync_conf_facade: CorosyncConfFacade,
    node_number_modifier: int = 0,
) -> bool:
    """
    Return True whenever quorum option auto tie breaker has to be enabled for
    proper working of SBD fencing. False if it's not needed or it is already
    enabled.

    service_manager --
    corosync_conf_facade --
    node_number_modifier -- this value vill be added to current number of nodes.
        This can be useful to test whenever is ATB needed when adding/removeing
        node.
    """
    return (not corosync_conf_facade.is_enabled_auto_tie_breaker()
            and is_auto_tie_breaker_needed(
                service_manager, corosync_conf_facade, node_number_modifier))
Ejemplo n.º 15
0
    def test_corosync_conf_not_set_need_offline_fail(
        self, mock_get_corosync, mock_distribute, mock_reload,
        mock_check_offline, mock_qdevice_reload
    ):
        corosync_data = open(rc("corosync.conf")).read()
        new_corosync_data = corosync_data.replace("version: 2", "version: 3")
        mock_get_corosync.return_value = corosync_data
        def raiser(dummy_communicator, dummy_reporter, dummy_nodes, dummy_force):
            raise LibraryError(
                reports.corosync_not_running_check_node_error("test node")
            )
        mock_check_offline.side_effect = raiser
        env = LibraryEnvironment(self.mock_logger, self.mock_reporter)

        self.assertTrue(env.is_corosync_conf_live)

        self.assertEqual(corosync_data, env.get_corosync_conf_data())
        self.assertEqual(corosync_data, env.get_corosync_conf().config.export())
        self.assertEqual(2, mock_get_corosync.call_count)

        conf_facade = CorosyncConfigFacade.from_string(new_corosync_data)
        conf_facade._need_stopped_cluster = True
        assert_raise_library_error(
            lambda: env.push_corosync_conf(conf_facade),
            (
                severity.ERROR,
                report_codes.COROSYNC_NOT_RUNNING_CHECK_NODE_ERROR,
                {"node": "test node"}
            )
        )
        mock_check_offline.assert_called_once_with(
            "mock node communicator",
            self.mock_reporter,
            "mock node list",
            False
        )
        mock_distribute.assert_not_called()
        mock_reload.assert_not_called()
        mock_qdevice_reload.assert_not_called()
Ejemplo n.º 16
0
    def test_corosync_conf_not_set_need_offline_fail(self, mock_get_corosync,
                                                     mock_distribute,
                                                     mock_reload,
                                                     mock_check_offline,
                                                     mock_qdevice_reload):
        corosync_data = open(rc("corosync.conf")).read()
        new_corosync_data = corosync_data.replace("version: 2", "version: 3")
        mock_get_corosync.return_value = corosync_data

        def raiser(dummy_communicator, dummy_reporter, dummy_nodes,
                   dummy_force):
            raise LibraryError(
                reports.corosync_not_running_check_node_error("test node"))

        mock_check_offline.side_effect = raiser
        env = LibraryEnvironment(self.mock_logger, self.mock_reporter)

        self.assertTrue(env.is_corosync_conf_live)

        self.assertEqual(corosync_data, env.get_corosync_conf_data())
        self.assertEqual(corosync_data,
                         env.get_corosync_conf().config.export())
        self.assertEqual(2, mock_get_corosync.call_count)

        conf_facade = CorosyncConfigFacade.from_string(new_corosync_data)
        conf_facade._need_stopped_cluster = True
        assert_raise_library_error(
            lambda: env.push_corosync_conf(conf_facade),
            (severity.ERROR,
             report_codes.COROSYNC_NOT_RUNNING_CHECK_NODE_ERROR, {
                 "node": "test node"
             }))
        mock_check_offline.assert_called_once_with("mock node communicator",
                                                   self.mock_reporter,
                                                   "mock node list", False)
        mock_distribute.assert_not_called()
        mock_reload.assert_not_called()
        mock_qdevice_reload.assert_not_called()
Ejemplo n.º 17
0
 def get_corosync_conf(self):
     return CorosyncConfigFacade.from_string(self.get_corosync_conf_data())
Ejemplo n.º 18
0
 def get_corosync_conf(self):
     return CorosyncConfigFacade.from_string(self.get_corosync_conf_data())
Ejemplo n.º 19
0
def set_recovery_site(env: LibraryEnvironment, node_name: str) -> None:
    """
    Set up disaster recovery with the local cluster being the primary site

    env
    node_name -- a known host from the recovery site
    """
    if env.ghost_file_codes:
        raise LibraryError(
            reports.live_environment_required(env.ghost_file_codes))
    report_processor = SimpleReportProcessor(env.report_processor)
    dr_env = env.get_dr_env()
    if dr_env.config.raw_file.exists():
        report_processor.report(reports.dr_config_already_exist())
    target_factory = env.get_node_target_factory()

    local_nodes, report_list = get_existing_nodes_names(
        env.get_corosync_conf(), error_on_missing_name=True)
    report_processor.report_list(report_list)

    if node_name in local_nodes:
        report_processor.report(reports.node_in_local_cluster(node_name))

    report_list, local_targets = target_factory.get_target_list_with_reports(
        local_nodes, allow_skip=False, report_none_host_found=False)
    report_processor.report_list(report_list)

    report_list, remote_targets = (target_factory.get_target_list_with_reports(
        [node_name], allow_skip=False, report_none_host_found=False))
    report_processor.report_list(report_list)

    if report_processor.has_errors:
        raise LibraryError()

    com_cmd = GetCorosyncConf(env.report_processor)
    com_cmd.set_targets(remote_targets)
    remote_cluster_nodes, report_list = get_existing_nodes_names(
        CorosyncConfigFacade.from_string(
            run_and_raise(env.get_node_communicator(), com_cmd)),
        error_on_missing_name=True)
    if report_processor.report_list(report_list):
        raise LibraryError()

    # ensure we have tokens for all nodes of remote cluster
    report_list, remote_targets = target_factory.get_target_list_with_reports(
        remote_cluster_nodes, allow_skip=False, report_none_host_found=False)
    if report_processor.report_list(report_list):
        raise LibraryError()
    dr_config_exporter = (get_file_toolbox(
        file_type_codes.PCS_DR_CONFIG).exporter)
    # create dr config for remote cluster
    remote_dr_cfg = dr_env.create_facade(DrRole.RECOVERY)
    remote_dr_cfg.add_site(DrRole.PRIMARY, local_nodes)
    # send config to all node of remote cluster
    distribute_file_cmd = DistributeFilesWithoutForces(
        env.report_processor,
        node_communication_format.pcs_dr_config_file(
            dr_config_exporter.export(remote_dr_cfg.config)))
    distribute_file_cmd.set_targets(remote_targets)
    run_and_raise(env.get_node_communicator(), distribute_file_cmd)
    # create new dr config, with local cluster as primary site
    local_dr_cfg = dr_env.create_facade(DrRole.PRIMARY)
    local_dr_cfg.add_site(DrRole.RECOVERY, remote_cluster_nodes)
    distribute_file_cmd = DistributeFilesWithoutForces(
        env.report_processor,
        node_communication_format.pcs_dr_config_file(
            dr_config_exporter.export(local_dr_cfg.config)))
    distribute_file_cmd.set_targets(local_targets)
    run_and_raise(env.get_node_communicator(), distribute_file_cmd)
Ejemplo n.º 20
0
 def test_success(self):
     env = self.env_assistant.get_env()
     new_corosync_conf_data = "totem {\n    version: 3\n}\n"
     env.push_corosync_conf(
         CorosyncConfigFacade.from_string(new_corosync_conf_data))
     self.assertEqual(new_corosync_conf_data, env.get_corosync_conf_data())