def test_attribute_value(self): section = config_parser.Section("mySection") self.assertEqual(section.get_attribute_value("name"), None) section = config_parser.Section("mySection") section.add_attribute("name1", "value1") section.add_attribute("name2", "value2") self.assertEqual(section.get_attribute_value("name", "value"), "value") section = config_parser.Section("mySection") section.add_attribute("name", "value") section.add_attribute("name1", "value1") section.add_attribute("name", "valueA") section.add_attribute("name1", "value1A") self.assertEqual(section.get_attribute_value("name"), "valueA")
def test_attribute_del(self): section = config_parser.Section("mySection") section.add_attribute("name1", "value1") section.add_attribute("name2", "value2") section.add_attribute("name3", "value3") section.add_attribute("name2", "value2") section.del_attribute(section.get_attributes()[1]) self.assertEqual( section.get_attributes(), [ ["name1", "value1"], ["name3", "value3"], ] ) section.del_attribute(["name3", "value3"]) self.assertEqual( section.get_attributes(), [ ["name1", "value1"], ] ) section.del_attribute(["name3", "value3"]) self.assertEqual( section.get_attributes(), [ ["name1", "value1"], ] )
def test_attribute_add(self): section = config_parser.Section("mySection") section.add_attribute("name1", "value1") self.assertEqual( section.get_attributes(), [ ["name1", "value1"], ], ) section.add_attribute("name2", "value2") self.assertEqual( section.get_attributes(), [ ["name1", "value1"], ["name2", "value2"], ], ) section.add_attribute("name2", "value2") self.assertEqual( section.get_attributes(), [ ["name1", "value1"], ["name2", "value2"], ["name2", "value2"], ], )
def test_attribute_get(self): section = config_parser.Section("mySection") section.add_attribute("name1", "value1") section.add_attribute("name2", "value2") section.add_attribute("name3", "value3") section.add_attribute("name2", "value2a") self.assertEqual( section.get_attributes(), [ ["name1", "value1"], ["name2", "value2"], ["name3", "value3"], ["name2", "value2a"], ] ) self.assertEqual( section.get_attributes("name1"), [ ["name1", "value1"], ] ) self.assertEqual( section.get_attributes("name2"), [ ["name2", "value2"], ["name2", "value2a"], ] ) self.assertEqual( section.get_attributes("nameX"), [] )
def add_link(self, options): """ Add a new link dict options -- link options """ options_translate = { "link_priority": "knet_link_priority", "ping_interval": "knet_ping_interval", "ping_precision": "knet_ping_precision", "ping_timeout": "knet_ping_timeout", "pong_count": "knet_pong_count", "transport": "knet_transport", } totem_section = self.__ensure_section(self.config, "totem")[-1] new_link_section = config_parser.Section("interface") options_to_set = {} for name, value in options.items(): if name == "broadcast": # If broadcast == 1, transform it to broadcast == yes. Else do # not put the option to the config at all. if value in ("1", 1): value = "yes" else: continue options_to_set[options_translate.get(name, name)] = value self.__set_section_options([new_link_section], options_to_set) totem_section.add_section(new_link_section) self.__remove_empty_sections(self.config)
def _set_link_options(self, options, interface_section_list=None, linknumber=None): """ Add a new or change an existing interface section with link options dict options -- link options list interface_section_list -- list of existing sections to be changed string linknumber -- linknumber to set to a newly created section """ # If the only option is "linknumber" then there is no point in adding # the options at all. It would mean there are no options for the # particular link. if not [name for name in options if name != "linknumber"]: return options_to_set = self.__translate_link_options(options) if not interface_section_list: new_section = config_parser.Section("interface") if linknumber: new_section.set_attribute("linknumber", linknumber) totem_section = self.__ensure_section(self.config, "totem")[-1] totem_section.add_section(new_section) interface_section_list = [new_section] self.__set_section_options(interface_section_list, options_to_set) self.__remove_empty_sections(self.config)
def _create_node_section(node_id, node_options, link_ids): node_section = config_parser.Section("node") for link_id, link_addr in zip(link_ids, node_options["addrs"]): node_section.add_attribute("ring{}_addr".format(link_id), link_addr) node_section.add_attribute("name", node_options["name"]) node_section.add_attribute("nodeid", node_id) return node_section
def __ensure_section(self, parent_section, section_name): section_list = parent_section.get_sections(section_name) if not section_list: new_section = config_parser.Section(section_name) parent_section.add_section(new_section) section_list.append(new_section) return section_list
def test_section_add(self): root = config_parser.Section("root") child1 = config_parser.Section("child1") child1a = config_parser.Section("child1a") child2 = config_parser.Section("child2") root.add_section(child1) child1.add_section(child1a) root.add_section(child2) self.assertEqual(root.parent, None) self.assertEqual(child1.parent.name, "root") self.assertEqual(child1a.parent.name, "child1") self.assertEqual(child2.parent.name, "root") ac(str(root), """\ child1 { child1a { } } child2 { } """) child2.add_section(child1a) self.assertEqual(child1a.parent.name, "child2") ac(str(root), """\ child1 { } child2 { child1a { } } """) self.assertRaises( config_parser.CircularParentshipException, child1a.add_section, child1a ) self.assertRaises( config_parser.CircularParentshipException, child1a.add_section, child2 ) self.assertRaises( config_parser.CircularParentshipException, child1a.add_section, root )
def test_bad_attr_value(self): section = config_parser.Section("mySection") section.add_attribute("bad_value", "va{l}ue1") section.add_attribute("good_value", "value2") self.assertEqual( config_parser.verify_section(section), ([], [], [("mySection.bad_value", "va{l}ue1")]), )
def update_quorum_device( self, model_options, generic_options, heuristics_options ): """ Update existing quorum device configuration dict model_options -- model specific options dict generic_options -- generic quorum device options dict heuristics_options -- heuristics options """ if not self.has_quorum_device(): raise LibraryError( ReportItem.error(reports.messages.QdeviceNotDefined()) ) model = self.get_quorum_device_model() # set new configuration device_sections = [] model_sections = [] heuristics_sections = [] for quorum in self.config.get_sections("quorum"): device_sections.extend(quorum.get_sections("device")) for device in quorum.get_sections("device"): model_sections.extend(device.get_sections(model)) heuristics_sections.extend(device.get_sections("heuristics")) # we know device sections exist, otherwise the function would exit at # has_quorum_device line above if not model_sections: new_model = config_parser.Section(model) device_sections[-1].add_section(new_model) model_sections.append(new_model) if not heuristics_sections: new_heuristics = config_parser.Section("heuristics") device_sections[-1].add_section(new_heuristics) heuristics_sections.append(new_heuristics) self.__set_section_options(device_sections, generic_options) self.__set_section_options(model_sections, model_options) self.__set_section_options(heuristics_sections, heuristics_options) self.__update_qdevice_votes() self.__update_two_node() self.__remove_empty_sections(self.config) self._need_qdevice_reload = True
def test_empty_section(self): section = config_parser.Section("mySection") self.assertEqual(section.parent, None) self.assertEqual(section.get_root(), section) self.assertEqual(section.name, "mySection") self.assertEqual(section.get_attributes(), []) self.assertEqual(section.get_sections(), []) self.assertTrue(section.empty) ac(str(section), "")
def create(cls, cluster_name, node_list, transport): """ Create a minimal config string cluster_name -- a name of a cluster list node_list -- list of dict: name, addrs string transport -- corosync transport """ root = config_parser.Section("") totem_section = config_parser.Section("totem") nodelist_section = config_parser.Section("nodelist") quorum_section = config_parser.Section("quorum") logging_section = config_parser.Section("logging") root.add_section(totem_section) root.add_section(nodelist_section) root.add_section(quorum_section) root.add_section(logging_section) totem_section.add_attribute("version", "2") totem_section.add_attribute("cluster_name", cluster_name) totem_section.add_attribute("transport", transport) quorum_section.add_attribute("provider", "corosync_votequorum") logging_section.add_attribute("to_logfile", "yes") logging_section.add_attribute("logfile", settings.corosync_log_file) logging_section.add_attribute("to_syslog", "yes") logging_section.add_attribute("timestamp", "on") for node_id, node_options in enumerate(node_list, 1): nodelist_section.add_section( cls._create_node_section( node_id, node_options, range(constants.LINKS_MAX) ) ) self = cls(root) # pylint: disable=protected-access self.__update_two_node() return self
def test_attribute_get_dict(self): section = config_parser.Section("mySection") self.assertEqual(section.get_attributes_dict(), {}) section = config_parser.Section("mySection") section.add_attribute("name1", "value1") section.add_attribute("name2", "value2") section.add_attribute("name3", "value3") self.assertEqual( section.get_attributes_dict(), {"name1": "value1", "name2": "value2", "name3": "value3", } ) section = config_parser.Section("mySection") section.add_attribute("name1", "value1") section.add_attribute("name2", "value2") section.add_attribute("name3", "value3") section.add_attribute("name1", "value1A") section.add_attribute("name3", "value3A") section.add_attribute("name1", "") self.assertEqual( section.get_attributes_dict(), {"name1": "", "name2": "value2", "name3": "value3A", } )
def test_attribute_change(self): section = config_parser.Section("mySection") section.add_attribute("name1", "value1") section.add_attribute("name2", "value2") section.add_attribute("name3", "value3") section.add_attribute("name2", "value2") attr = section.get_attributes()[1] attr[0] = "name2a" attr[1] = "value2a" self.assertEqual(section.get_attributes(), [ ["name1", "value1"], ["name2a", "value2a"], ["name3", "value3"], ["name2", "value2"], ])
def add_link(self, options): """ Add a new link dict options -- link options """ totem_section = self.__ensure_section(self.config, "totem")[-1] new_link_section = config_parser.Section("interface") options_to_set = {} for name, value in options.items(): if name == "broadcast": # If broadcast == 1, transform it to broadcast == yes. Else do # not put the option to the config at all. if value in ("1", 1): options_to_set[name] = "yes" continue options_to_set[name] = value self.__set_section_options([new_link_section], options_to_set) totem_section.add_section(new_link_section) self.__remove_empty_sections(self.config)
def test_is_section_empty(self): section = config_parser.Section("mySection") self.assertTrue(section.empty) section = config_parser.Section("mySection") section.add_attribute("name", "value") self.assertFalse(section.empty) section = config_parser.Section("mySection") section.add_section(config_parser.Section("subSection")) self.assertFalse(section.empty) section = config_parser.Section("mySection") section.add_attribute("name", "value") section.add_section(config_parser.Section("subSection")) self.assertFalse(section.empty)
def test_bad_attr_name(self): section = config_parser.Section("mySection") section.add_attribute("bad#name", "value1") section.add_attribute("good_name", "value2") self.assertEqual(config_parser.verify_section(section), ([], ["mySection.bad#name"], []))
def update_quorum_device( self, report_processor, model_options, generic_options, heuristics_options, force_options=False ): """ Update existing quorum device configuration dict model_options -- model specific options dict generic_options -- generic quorum device options dict heuristics_options -- heuristics options bool force_options -- continue even if options are not valid """ # validation if not self.has_quorum_device(): raise LibraryError(reports.qdevice_not_defined()) model = None for quorum in self.config.get_sections("quorum"): for device in quorum.get_sections("device"): for dummy_name, value in device.get_attributes("model"): model = value report_processor.process_list( self.__validate_quorum_device_model_options( model, model_options, need_required=False, force=force_options ) + self.__validate_quorum_device_generic_options( generic_options, force=force_options ) + self.__validate_quorum_device_update_heuristics( heuristics_options, force_options=force_options ) ) # set new configuration device_sections = [] model_sections = [] heuristics_sections = [] for quorum in self.config.get_sections("quorum"): device_sections.extend(quorum.get_sections("device")) for device in quorum.get_sections("device"): model_sections.extend(device.get_sections(model)) heuristics_sections.extend(device.get_sections("heuristics")) # we know device sections exist, otherwise the function would exit at # has_quorum_device line above if not model_sections: new_model = config_parser.Section(model) device_sections[-1].add_section(new_model) model_sections.append(new_model) if not heuristics_sections: new_heuristics = config_parser.Section("heuristics") device_sections[-1].add_section(new_heuristics) heuristics_sections.append(new_heuristics) self.__set_section_options(device_sections, generic_options) self.__set_section_options(model_sections, model_options) self.__set_section_options(heuristics_sections, heuristics_options) if self.__is_heuristics_enabled_with_no_exec(): report_processor.process( reports.corosync_quorum_heuristics_enabled_with_no_exec() ) self.__update_qdevice_votes() self.__update_two_node() self.__remove_empty_sections(self.config) self._need_qdevice_reload = True
def add_quorum_device( self, report_processor, model, model_options, generic_options, heuristics_options, force_model=False, force_options=False, ): """ Add quorum device configuration string model -- quorum device model dict model_options -- model specific options dict generic_options -- generic quorum device options dict heuristics_options -- heuristics options bool force_model -- continue even if the model is not valid bool force_options -- continue even if options are not valid """ # validation if self.has_quorum_device(): raise LibraryError(reports.qdevice_already_defined()) report_processor.process_list( self.__validate_quorum_device_model(model, force_model) + self.__validate_quorum_device_model_options( model, model_options, need_required=True, force=force_options ) + self.__validate_quorum_device_generic_options( generic_options, force=force_options ) + self.__validate_quorum_device_add_heuristics( heuristics_options, force_options=force_options ) ) # configuration cleanup remove_need_stopped_cluster = dict([ (name, "") for name in self.__class__.QUORUM_OPTIONS_INCOMPATIBLE_WITH_QDEVICE ]) # remove old device settings quorum_section_list = self.__ensure_section(self.config, "quorum") for quorum in quorum_section_list: for device in quorum.get_sections("device"): quorum.del_section(device) for name, value in quorum.get_attributes(): if ( name in remove_need_stopped_cluster and value not in ["", "0"] ): self._need_stopped_cluster = True # remove conflicting quorum options attrs_to_remove = { "allow_downscale": "", "two_node": "", } attrs_to_remove.update(remove_need_stopped_cluster) self.__set_section_options(quorum_section_list, attrs_to_remove) # remove nodes' votes for nodelist in self.config.get_sections("nodelist"): for node in nodelist.get_sections("node"): node.del_attributes_by_name("quorum_votes") # add new configuration quorum = quorum_section_list[-1] new_device = config_parser.Section("device") quorum.add_section(new_device) self.__set_section_options([new_device], generic_options) new_device.set_attribute("model", model) new_model = config_parser.Section(model) self.__set_section_options([new_model], model_options) new_device.add_section(new_model) new_heuristics = config_parser.Section("heuristics") self.__set_section_options([new_heuristics], heuristics_options) new_device.add_section(new_heuristics) if self.__is_heuristics_enabled_with_no_exec(): report_processor.process( reports.corosync_quorum_heuristics_enabled_with_no_exec() ) self.__update_qdevice_votes() self.__update_two_node() self.__remove_empty_sections(self.config)
def add_quorum_device( self, model, model_options, generic_options, heuristics_options ): # pylint: disable=too-many-locals """ Add quorum device configuration string model -- quorum device model dict model_options -- model specific options dict generic_options -- generic quorum device options dict heuristics_options -- heuristics options """ if self.has_quorum_device(): raise LibraryError( ReportItem.error(reports.messages.QdeviceAlreadyDefined()) ) # configuration cleanup remove_need_stopped_cluster = { name: "" for name in constants.QUORUM_OPTIONS_INCOMPATIBLE_WITH_QDEVICE } # remove old device settings quorum_section_list = self.__ensure_section(self.config, "quorum") for quorum in quorum_section_list: for device in quorum.get_sections("device"): quorum.del_section(device) for name, value in quorum.get_attributes(): if name in remove_need_stopped_cluster and value not in [ "", "0", ]: self._need_stopped_cluster = True # remove conflicting quorum options attrs_to_remove = { "allow_downscale": "", "two_node": "", } attrs_to_remove.update(remove_need_stopped_cluster) self.__set_section_options(quorum_section_list, attrs_to_remove) # remove nodes' votes for nodelist in self.config.get_sections("nodelist"): for node_section in nodelist.get_sections("node"): node_section.del_attributes_by_name("quorum_votes") # add new configuration quorum = quorum_section_list[-1] new_device = config_parser.Section("device") quorum.add_section(new_device) self.__set_section_options([new_device], generic_options) new_device.set_attribute("model", model) new_model = config_parser.Section(model) self.__set_section_options([new_model], model_options) new_device.add_section(new_model) new_heuristics = config_parser.Section("heuristics") self.__set_section_options([new_heuristics], heuristics_options) new_device.add_section(new_heuristics) self.__update_qdevice_votes() self.__update_two_node() self.__remove_empty_sections(self.config)
def test_empty_section(self): section = config_parser.Section("mySection") self.assertEqual(config_parser.verify_section(section), ([], [], []))
def test_str(self): root = config_parser.Section("root") ac(str(root), "") root.add_attribute("name1", "value1") ac(str(root), "name1: value1\n") root.add_attribute("name2", "value2") root.add_attribute("name2", "value2a") root.add_attribute("name3", "value3") ac(str(root), """\ name1: value1 name2: value2 name2: value2a name3: value3 """) child1 = config_parser.Section("child1") root.add_section(child1) ac(str(root), """\ name1: value1 name2: value2 name2: value2a name3: value3 child1 { } """) child1.add_attribute("name1.1", "value1.1") child1.add_attribute("name1.2", "value1.2") ac(str(root), """\ name1: value1 name2: value2 name2: value2a name3: value3 child1 { name1.1: value1.1 name1.2: value1.2 } """) child2 = config_parser.Section("child2") child2.add_attribute("name2.1", "value2.1") root.add_section(child2) ac(str(root), """\ name1: value1 name2: value2 name2: value2a name3: value3 child1 { name1.1: value1.1 name1.2: value1.2 } child2 { name2.1: value2.1 } """) child2a = config_parser.Section("child2a") child2a.add_attribute("name2.a.1", "value2.a.1") child2.add_section(child2a) ac(str(root), """\ name1: value1 name2: value2 name2: value2a name3: value3 child1 { name1.1: value1.1 name1.2: value1.2 } child2 { name2.1: value2.1 child2a { name2.a.1: value2.a.1 } } """) child3 = config_parser.Section("child3") root.add_section(child3) child3.add_section(config_parser.Section("child3a")) child3.add_section(config_parser.Section("child3b")) ac(str(root), """\ name1: value1 name2: value2 name2: value2a name3: value3 child1 { name1.1: value1.1 name1.2: value1.2 } child2 { name2.1: value2.1 child2a { name2.a.1: value2.a.1 } } child3 { child3a { } child3b { } } """)
def test_section_del(self): root = config_parser.Section("") child1 = config_parser.Section("child1") child2 = config_parser.Section("child2") childa1 = config_parser.Section("childA") childa2 = config_parser.Section("childA") childa3 = config_parser.Section("childA") childa4 = config_parser.Section("childA") childb1 = config_parser.Section("childB") childb2 = config_parser.Section("childB") childa1.add_attribute("id", "1") childa2.add_attribute("id", "2") childa3.add_attribute("id", "3") childa4.add_attribute("id", "4") childb1.add_attribute("id", "5") childb2.add_attribute("id", "6") root.add_section(child1) root.add_section(child2) child1.add_section(childa1) child1.add_section(childa2) child1.add_section(childb1) child2.add_section(childa3) child2.add_section(childb2) child2.add_section(childa4) ac(str(root), """\ child1 { childA { id: 1 } childA { id: 2 } childB { id: 5 } } child2 { childA { id: 3 } childB { id: 6 } childA { id: 4 } } """) child2.del_section(childb2) self.assertEqual(childb2.parent, None) ac(str(root), """\ child1 { childA { id: 1 } childA { id: 2 } childB { id: 5 } } child2 { childA { id: 3 } childA { id: 4 } } """) root.del_section(child2) self.assertEqual(child2.parent, None) ac(str(root), """\ child1 { childA { id: 1 } childA { id: 2 } childB { id: 5 } } """) self.assertRaises(ValueError, root.del_section, child2) self.assertEqual(childa1.parent.name, "child1") self.assertRaises(ValueError, child2.del_section, childa1) self.assertEqual(childa1.parent.name, "child1") child1.del_section(childb1) self.assertEqual(childb1.parent, None) ac(str(root), """\ child1 { childA { id: 1 } childA { id: 2 } } """) child1.del_section(childa1) self.assertEqual(childa1.parent, None) child1.del_section(childa2) self.assertEqual(childa2.parent, None) ac(str(root), """\ child1 { } """) root.del_section(child1) self.assertEqual(child1.parent, None) ac(str(root), "")
def test_section_get(self): root = config_parser.Section("") child1 = config_parser.Section("child1") child2 = config_parser.Section("child2") childa1 = config_parser.Section("childA") childa2 = config_parser.Section("childA") childa3 = config_parser.Section("childA") childa4 = config_parser.Section("childA") childb1 = config_parser.Section("childB") childb2 = config_parser.Section("childB") childa1.add_attribute("id", "1") childa2.add_attribute("id", "2") childa3.add_attribute("id", "3") childa4.add_attribute("id", "4") childb1.add_attribute("id", "5") childb2.add_attribute("id", "6") root.add_section(child1) root.add_section(child2) child1.add_section(childa1) child1.add_section(childa2) child1.add_section(childb1) child2.add_section(childa3) child2.add_section(childb2) child2.add_section(childa4) ac(str(root), """\ child1 { childA { id: 1 } childA { id: 2 } childB { id: 5 } } child2 { childA { id: 3 } childB { id: 6 } childA { id: 4 } } """) ac( "---\n".join([str(x) for x in root.get_sections()]), """\ child1 { childA { id: 1 } childA { id: 2 } childB { id: 5 } } --- child2 { childA { id: 3 } childB { id: 6 } childA { id: 4 } } """) ac( "---\n".join([str(x) for x in root.get_sections("child1")]), """\ child1 { childA { id: 1 } childA { id: 2 } childB { id: 5 } } """) ac( "---\n".join([str(x) for x in child1.get_sections("childA")]), """\ childA { id: 1 } --- childA { id: 2 } """) ac( "---\n".join([str(x) for x in child1.get_sections("child2")]), "" )
def test_bad_section(self): section = config_parser.Section("my#section") self.assertEqual(config_parser.verify_section(section), (["my#section"], [], []))