def update_device(lib_env, model_options, generic_options, heuristics_options, force_options=False, skip_offline_nodes=False): """ Change quorum device settings, distribute and reload configs if live 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 bool skip_offline_nodes -- continue even if not all nodes are accessible """ cfg = lib_env.get_corosync_conf() if not cfg.has_quorum_device(): raise LibraryError(reports.qdevice_not_defined()) lib_env.report_processor.process_list( corosync_conf_validators.update_quorum_device( cfg.get_quorum_device_model(), model_options, generic_options, heuristics_options, [node.nodeid for node in cfg.get_nodes()], force_options=force_options)) cfg.update_quorum_device(model_options, generic_options, heuristics_options) if cfg.is_quorum_device_heuristics_enabled_with_no_exec(): lib_env.report_processor.process( reports.corosync_quorum_heuristics_enabled_with_no_exec()) lib_env.push_corosync_conf(cfg, skip_offline_nodes)
def update_device( lib_env, model_options, generic_options, heuristics_options, force_options=False, skip_offline_nodes=False ): """ Change quorum device settings, distribute and reload configs if live 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 bool skip_offline_nodes -- continue even if not all nodes are accessible """ cfg = lib_env.get_corosync_conf() if not cfg.has_quorum_device(): raise LibraryError(reports.qdevice_not_defined()) lib_env.report_processor.process_list( corosync_conf_validators.update_quorum_device( cfg.get_quorum_device_model(), model_options, generic_options, heuristics_options, [node.nodeid for node in cfg.get_nodes()], force_options=force_options ) ) cfg.update_quorum_device( model_options, generic_options, heuristics_options ) if cfg.is_quorum_device_heuristics_enabled_with_no_exec(): lib_env.report_processor.process( reports.corosync_quorum_heuristics_enabled_with_no_exec() ) lib_env.push_corosync_conf(cfg, skip_offline_nodes)
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_device(lib_env, model, model_options, generic_options, heuristics_options, force_model=False, force_options=False, skip_offline_nodes=False): """ Add a quorum device to a cluster, distribute and reload configs if live 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 bool skip_offline_nodes -- continue even if not all nodes are accessible """ cfg = lib_env.get_corosync_conf() if cfg.has_quorum_device(): raise LibraryError(reports.qdevice_already_defined()) lib_env.report_processor.process_list( corosync_conf_validators.add_quorum_device( model, model_options, generic_options, heuristics_options, [node.nodeid for node in cfg.get_nodes()], force_model=force_model, force_options=force_options)) cfg.add_quorum_device( model, model_options, generic_options, heuristics_options, ) if cfg.is_quorum_device_heuristics_enabled_with_no_exec(): lib_env.report_processor.process( reports.corosync_quorum_heuristics_enabled_with_no_exec()) # First setup certificates for qdevice, then send corosync.conf to nodes. # If anything fails, nodes will not have corosync.conf with qdevice in it, # so there is no effect on the cluster. if lib_env.is_corosync_conf_live: target_factory = lib_env.get_node_target_factory() target_list = target_factory.get_target_list( cfg.get_nodes_names(), skip_non_existing=skip_offline_nodes, ) # Do model specific configuration. # If the model is not known to pcs and was forced, do not configure # anything else than corosync.conf, as we do not know what to do # anyway. if model == "net": qdevice_net.set_up_client_certificates( lib_env.cmd_runner(), lib_env.report_processor, lib_env.communicator_factory, # We are sure the "host" key is there, it has been validated # above. target_factory.get_target_from_hostname(model_options["host"]), cfg.get_cluster_name(), target_list, skip_offline_nodes) lib_env.report_processor.process( reports.service_enable_started("corosync-qdevice")) com_cmd = qdevice_com.Enable(lib_env.report_processor, skip_offline_nodes) com_cmd.set_targets(target_list) run_and_raise(lib_env.get_node_communicator(), com_cmd) # everything set up, it's safe to tell the nodes to use qdevice lib_env.push_corosync_conf(cfg, skip_offline_nodes) # Now, when corosync.conf has been reloaded, we can start qdevice service. if lib_env.is_corosync_conf_live: lib_env.report_processor.process( reports.service_start_started("corosync-qdevice")) com_cmd = qdevice_com.Start(lib_env.report_processor, skip_offline_nodes) com_cmd.set_targets(target_list) run_and_raise(lib_env.get_node_communicator(), com_cmd)
def add_device( lib_env, model, model_options, generic_options, heuristics_options, force_model=False, force_options=False, skip_offline_nodes=False ): """ Add a quorum device to a cluster, distribute and reload configs if live 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 bool skip_offline_nodes -- continue even if not all nodes are accessible """ cfg = lib_env.get_corosync_conf() if cfg.has_quorum_device(): raise LibraryError(reports.qdevice_already_defined()) report_processor = SimpleReportProcessor(lib_env.report_processor) report_processor.report_list( corosync_conf_validators.add_quorum_device( model, model_options, generic_options, heuristics_options, [node.nodeid for node in cfg.get_nodes()], force_model=force_model, force_options=force_options ) ) if lib_env.is_corosync_conf_live: cluster_nodes_names, report_list = get_existing_nodes_names( cfg, # Pcs is unable to communicate with nodes missing names. It cannot # send new corosync.conf to them. That might break the cluster. # Hence we error out. error_on_missing_name=True ) report_processor.report_list(report_list) if report_processor.has_errors: raise LibraryError() cfg.add_quorum_device( model, model_options, generic_options, heuristics_options, ) if cfg.is_quorum_device_heuristics_enabled_with_no_exec(): lib_env.report_processor.process( reports.corosync_quorum_heuristics_enabled_with_no_exec() ) # First setup certificates for qdevice, then send corosync.conf to nodes. # If anything fails, nodes will not have corosync.conf with qdevice in it, # so there is no effect on the cluster. if lib_env.is_corosync_conf_live: target_factory = lib_env.get_node_target_factory() target_list = target_factory.get_target_list( cluster_nodes_names, skip_non_existing=skip_offline_nodes, ) # Do model specific configuration. # If the model is not known to pcs and was forced, do not configure # anything else than corosync.conf, as we do not know what to do # anyway. if model == "net": qdevice_net.set_up_client_certificates( lib_env.cmd_runner(), lib_env.report_processor, lib_env.communicator_factory, # We are sure the "host" key is there, it has been validated # above. target_factory.get_target_from_hostname(model_options["host"]), cfg.get_cluster_name(), target_list, skip_offline_nodes ) lib_env.report_processor.process( reports.service_enable_started("corosync-qdevice") ) com_cmd = qdevice_com.Enable( lib_env.report_processor, skip_offline_nodes ) com_cmd.set_targets(target_list) run_and_raise(lib_env.get_node_communicator(), com_cmd) # everything set up, it's safe to tell the nodes to use qdevice lib_env.push_corosync_conf(cfg, skip_offline_nodes) # Now, when corosync.conf has been reloaded, we can start qdevice service. if lib_env.is_corosync_conf_live: lib_env.report_processor.process( reports.service_start_started("corosync-qdevice") ) com_cmd = qdevice_com.Start( lib_env.report_processor, skip_offline_nodes ) com_cmd.set_targets(target_list) run_and_raise(lib_env.get_node_communicator(), com_cmd)