def prepare_options_plain(cib, options, ticket, resource_id): options = options.copy() report = _validate_options_common(options) if not ticket: report.append(reports.required_option_is_missing(['ticket'])) options["ticket"] = ticket if not resource_id: report.append(reports.required_option_is_missing(['rsc'])) options["rsc"] = resource_id if "rsc-role" in options: if options["rsc-role"]: resource_role = options["rsc-role"].lower().capitalize() if resource_role not in ATTRIB_PLAIN["rsc-role"]: report.append( reports.invalid_option_value("rsc-role", options["rsc-role"], ATTRIB_PLAIN["rsc-role"])) options["rsc-role"] = resource_role else: del options["rsc-role"] if report: raise LibraryError(*report) return constraint.prepare_options( tuple(list(ATTRIB) + list(ATTRIB_PLAIN)), options, partial(_create_id, cib, options["ticket"], resource_id, options.get("rsc-role", "")), partial(tools.check_new_id_applicable, cib, DESCRIPTION))
def initialize_block_devices(lib_env, device_list, option_dict): """ Initialize SBD devices in device_list with options_dict. lib_env -- LibraryEnvironment device_list -- list of strings option_dict -- dictionary """ report_item_list = [] if not device_list: report_item_list.append(reports.required_option_is_missing(["device"])) supported_options = sbd.DEVICE_INITIALIZATION_OPTIONS_MAPPING.keys() report_item_list += names_in(supported_options, option_dict.keys()) validator_list = [ value_nonnegative_integer(key) for key in supported_options ] report_item_list += run_collection_of_option_validators( option_dict, validator_list ) lib_env.report_processor.process_list(report_item_list) sbd.initialize_block_devices( lib_env.report_processor, lib_env.cmd_runner(), device_list, option_dict )
def validate_parameters( self, parameters, parameters_type="resource", allow_invalid=False, update=False ): forceable = report_codes.FORCE_OPTIONS if not allow_invalid else None severity = ( ReportItemSeverity.ERROR if not allow_invalid else ReportItemSeverity.WARNING ) report_list = [] bad_opts, missing_req_opts = self.validate_parameters_values( parameters ) if bad_opts: report_list.append(reports.invalid_options( bad_opts, sorted([attr["name"] for attr in self.get_parameters()]), parameters_type, severity=severity, forceable=forceable, )) if not update and missing_req_opts: report_list.append(reports.required_option_is_missing( missing_req_opts, parameters_type, severity=severity, forceable=forceable, )) return report_list
def create_alert( lib_env, alert_id, path, instance_attribute_dict, meta_attribute_dict, description=None ): """ Create new alert. Raises LibraryError if path is not specified, or any other failure. lib_env -- LibraryEnvironment alert_id -- id of alert to be created, if None it will be generated path -- path to script for alert instance_attribute_dict -- dictionary of instance attributes meta_attribute_dict -- dictionary of meta attributes description -- alert description description """ if not path: raise LibraryError(reports.required_option_is_missing(["path"])) cib = lib_env.get_cib(REQUIRED_CIB_VERSION) alert_el = alert.create_alert(cib, alert_id, path, description) alert.update_instance_attributes(alert_el, instance_attribute_dict) alert.update_meta_attributes(alert_el, meta_attribute_dict) lib_env.push_cib(cib)
def add_recipient(lib_env, alert_id, recipient_value, instance_attribute_dict, meta_attribute_dict, recipient_id=None, description=None, allow_same_value=False): """ Add new recipient to alert witch id alert_id. lib_env -- LibraryEnvironment alert_id -- id of alert to which new recipient should be added recipient_value -- value of new recipient instance_attribute_dict -- dictionary of instance attributes to update meta_attribute_dict -- dictionary of meta attributes to update recipient_id -- id of new recipient, if None it will be generated description -- recipient description allow_same_value -- if True unique recipient value is not required """ if not recipient_value: raise LibraryError(reports.required_option_is_missing(["value"])) cib = lib_env.get_cib(REQUIRED_CIB_VERSION) recipient = alert.add_recipient(lib_env.report_processor, cib, alert_id, recipient_value, recipient_id=recipient_id, description=description, allow_same_value=allow_same_value) alert.update_instance_attributes(recipient, instance_attribute_dict) alert.update_meta_attributes(recipient, meta_attribute_dict) lib_env.push_cib(cib)
def create_alert( lib_env, alert_id, path, instance_attribute_dict, meta_attribute_dict, description=None ): """ Create new alert. Raises LibraryError if path is not specified, or any other failure. lib_env -- LibraryEnvironment alert_id -- id of alert to be created, if None it will be generated path -- path to script for alert instance_attribute_dict -- dictionary of instance attributes meta_attribute_dict -- dictionary of meta attributes description -- alert description description """ if not path: raise LibraryError(reports.required_option_is_missing(["path"])) alert_el = alert.create_alert( lib_env.get_cib(REQUIRED_CIB_VERSION), alert_id, path, description ) alert.update_instance_attributes(alert_el, instance_attribute_dict) alert.update_meta_attributes(alert_el, meta_attribute_dict) lib_env.push_cib()
def initialize_block_devices(lib_env, device_list, option_dict): """ Initialize SBD devices in device_list with options_dict. lib_env -- LibraryEnvironment device_list -- list of strings option_dict -- dictionary """ report_item_list = [] if not device_list: report_item_list.append(reports.required_option_is_missing(["device"])) supported_options = sbd.DEVICE_INITIALIZATION_OPTIONS_MAPPING.keys() report_item_list += names_in(supported_options, option_dict.keys()) validator_list = [ value_nonnegative_integer(key) for key in supported_options ] report_item_list += run_collection_of_option_validators( option_dict, validator_list ) lib_env.report_processor.process_list(report_item_list) sbd.initialize_block_devices( lib_env.report_processor, lib_env.cmd_runner(), device_list, option_dict )
def set_message(lib_env, device, node_name, message): """ Set message on device for node_name. lib_env -- LibrayEnvironment device -- string, absolute path to device node_name -- string message -- string, mesage type, should be one of settings.sbd_message_types """ report_item_list = [] missing_options = [] if not device: missing_options.append("device") if not node_name: missing_options.append("node") if missing_options: report_item_list.append( reports.required_option_is_missing(missing_options) ) supported_messages = settings.sbd_message_types if message not in supported_messages: report_item_list.append( reports.invalid_option_value("message", message, supported_messages) ) lib_env.report_processor.process_list(report_item_list) sbd.set_message(lib_env.cmd_runner(), device, node_name, message)
def validate(option_dict): if option_name not in option_dict: return [reports.required_option_is_missing( [option_name], option_type, )] return []
def _validate_devices( reporter, resources_el, devices, force_device=False, allow_force=True ): if not devices: reporter.append( reports.required_option_is_missing(["stonith devices"]) ) invalid_devices = [] for dev in devices: errors = reporter.errors_count validate_id(dev, description="device id", reporter=reporter) if reporter.errors_count > errors: continue # TODO use the new finding function if not is_stonith_resource(resources_el, dev): invalid_devices.append(dev) if invalid_devices: reporter.append( reports.stonith_resources_do_not_exist( invalid_devices, ReportItemSeverity.WARNING if force_device and allow_force else ReportItemSeverity.ERROR , None if force_device or not allow_force else report_codes.FORCE_STONITH_RESOURCE_DOES_NOT_EXIST ) )
def _validate_devices( reporter, resources_el, devices, force_device=False, allow_force=True ): if not devices: reporter.add( reports.required_option_is_missing(["stonith devices"]) ) invalid_devices = [] for dev in devices: errors = reporter.errors_count validate_id(dev, description="device id", reporter=reporter) if reporter.errors_count > errors: continue # TODO use the new finding function if not is_stonith_resource(resources_el, dev): invalid_devices.append(dev) if invalid_devices: reporter.add( reports.stonith_resources_do_not_exist( invalid_devices, ReportItemSeverity.WARNING if force_device and allow_force else ReportItemSeverity.ERROR , None if force_device or not allow_force else report_codes.FORCE_STONITH_RESOURCE_DOES_NOT_EXIST ) )
def validate_parameters_create(self, parameters, force=False): # This is just a basic validation checking that required parameters are # set and all set parameters are known to an agent. Missing checks are: # 1. values checks - if a param is an integer, then "abc" is not valid # 2. warnings should be emitted when a deprecated param is set # 3. errors should be emitted when a deprecated parameter and a # parameter obsoleting it are set at the same time # 4. possibly some other checks # All of these have been missing in pcs since ever (ad 1. agents have # never provided enough info for us to do such validations, ad 2. and # 3. there were no deprecated parameters before). The checks should be # implemented in agents themselves, so I'm not adding them now either. report_items = [] # report unknown parameters report_items.extend( validate.names_in( {param["name"] for param in self.get_parameters()}, parameters.keys(), self._agent_type_label, report_codes.FORCE_OPTIONS, force)) # report missing required parameters missing_parameters = self._find_missing_required_parameters(parameters) if missing_parameters: forcible, severity = self._validate_report_forcible_severity(force) report_items.append( reports.required_option_is_missing( sorted(missing_parameters), self._agent_type_label, severity=severity, forceable=forcible, )) return report_items
def set_message(lib_env, device, node_name, message): """ Set message on device for node_name. lib_env -- LibrayEnvironment device -- string, absolute path to device node_name -- string message -- string, mesage type, should be one of settings.sbd_message_types """ report_item_list = [] missing_options = [] if not device: missing_options.append("device") if not node_name: missing_options.append("node") if missing_options: report_item_list.append( reports.required_option_is_missing(missing_options) ) supported_messages = settings.sbd_message_types if message not in supported_messages: report_item_list.append( reports.invalid_option_value("message", message, supported_messages) ) lib_env.report_processor.process_list(report_item_list) sbd.set_message(lib_env.cmd_runner(), device, node_name, message)
def validate_parameters( self, parameters, parameters_type="resource agent parameter", allow_invalid=False ): forceable = report_codes.FORCE_OPTIONS if not allow_invalid else None severity = ( ReportItemSeverity.ERROR if not allow_invalid else ReportItemSeverity.WARNING ) report_list = [] bad_opts, missing_req_opts = self.validate_parameters_values( parameters ) if bad_opts: report_list.append(reports.invalid_option( bad_opts, sorted([attr["name"] for attr in self.get_parameters()]), parameters_type, severity=severity, forceable=forceable, )) if missing_req_opts: report_list.append(reports.required_option_is_missing( missing_req_opts, parameters_type, severity=severity, forceable=forceable, )) return report_list
def validate_parameters_update( self, current_parameters, new_parameters, force=False ): # This is just a basic validation checking that required parameters are # set and all set parameters are known to an agent. Missing checks are: # 1. values checks - if a param is an integer, then "abc" is not valid # 2. warnings should be emitted when a deprecated param is set # 3. errors should be emitted when a deprecated parameter and a # parameter obsoleting it are set at the same time # 4. possibly some other checks # All of these have been missing in pcs since ever (ad 1. agents have # never provided enough info for us to do such validations, ad 2. and # 3. there were no deprecated parameters before). The checks should be # implemented in agents themselves, so I'm not adding them now either. report_items = [] # get resulting set of agent's parameters final_parameters = dict(current_parameters) for name, value in new_parameters.items(): if value: final_parameters[name] = value else: if name in final_parameters: del final_parameters[name] # report unknown parameters report_items.extend( validate.names_in( {param["name"] for param in self.get_parameters()}, # Do not report unknown parameters already set in the CIB. They # have been reported already when the were added to the CIB. set(new_parameters.keys()) - set(current_parameters.keys()), self._agent_type_label, report_codes.FORCE_OPTIONS, force ) ) # report missing or removed required parameters missing_parameters = self._find_missing_required_parameters( final_parameters ) if missing_parameters: forcible, severity = self._validate_report_forcible_severity(force) report_items.append(reports.required_option_is_missing( sorted(missing_parameters), self._agent_type_label, severity=severity, forceable=forcible, )) return report_items
def validate_parameters_update(self, current_parameters, new_parameters, force=False): # This is just a basic validation checking that required parameters are # set and all set parameters are known to an agent. Missing checks are: # 1. values checks - if a param is an integer, then "abc" is not valid # 2. warnings should be emitted when a deprecated param is set # 3. errors should be emitted when a deprecated parameter and a # parameter obsoleting it are set at the same time # 4. possibly some other checks # All of these have been missing in pcs since ever (ad 1. agents have # never provided enough info for us to do such validations, ad 2. and # 3. there were no deprecated parameters before). The checks should be # implemented in agents themselves, so I'm not adding them now either. report_items = [] # get resulting set of agent's parameters final_parameters = dict(current_parameters) for name, value in new_parameters.items(): if len(value) < 1: if name in final_parameters: del final_parameters[name] else: final_parameters[name] = value # report unknown parameters report_items.extend( validate.names_in( {param["name"] for param in self.get_parameters()}, # Do not report unknown parameters already set in the CIB. They # have been reported already when the were added to the CIB. set(new_parameters.keys()) - set(current_parameters.keys()), self._agent_type_label, report_codes.FORCE_OPTIONS, force)) # report missing or removed required parameters missing_parameters = self._find_missing_required_parameters( final_parameters) if missing_parameters: forcible, severity = self._validate_report_forcible_severity(force) report_items.append( reports.required_option_is_missing( sorted(missing_parameters), self._agent_type_label, severity=severity, forceable=forcible, )) return report_items
def prepare_options_plain(cib, options, ticket, resource_id): options = options.copy() report = _validate_options_common(options) if not ticket: report.append(reports.required_option_is_missing(['ticket'])) options["ticket"] = ticket if not resource_id: report.append(reports.required_option_is_missing(['rsc'])) options["rsc"] = resource_id if "rsc-role" in options: if options["rsc-role"]: resource_role = options["rsc-role"].lower().capitalize() if resource_role not in ATTRIB_PLAIN["rsc-role"]: report.append(reports.invalid_option_value( "rsc-role", options["rsc-role"], ATTRIB_PLAIN["rsc-role"] )) options["rsc-role"] = resource_role else: del options["rsc-role"] if report: raise LibraryError(*report) return constraint.prepare_options( tuple(list(ATTRIB) + list(ATTRIB_PLAIN)), options, partial( _create_id, cib, options["ticket"], resource_id, options.get("rsc-role", "") ), partial(tools.check_new_id_applicable, cib, DESCRIPTION) )
def prepare_options_with_set(cib, options, resource_set_list): options = constraint.prepare_options( tuple(ATTRIB.keys()), options, create_id_fn=partial(constraint.create_id, cib, TAG_NAME, resource_set_list), validate_id=partial(tools.check_new_id_applicable, cib, DESCRIPTION), ) report = _validate_options_common(options) if "ticket" not in options or not options["ticket"].strip(): report.append(reports.required_option_is_missing(['ticket'])) if report: raise LibraryError(*report) return options
def prepare_options_with_set(cib, options, resource_set_list): options = constraint.prepare_options( tuple(ATTRIB.keys()), options, create_id_fn=partial( constraint.create_id, cib, TAG_NAME, resource_set_list ), validate_id=partial(tools.check_new_id_applicable, cib, DESCRIPTION), ) report = _validate_options_common(options) if "ticket" not in options or not options["ticket"].strip(): report.append(reports.required_option_is_missing(['ticket'])) if report: raise LibraryError(*report) return options
def add_recipient( lib_env, alert_id, recipient_value, instance_attribute_dict, meta_attribute_dict, recipient_id=None, description=None, allow_same_value=False ): """ Add new recipient to alert witch id alert_id. lib_env -- LibraryEnvironment alert_id -- id of alert to which new recipient should be added recipient_value -- value of new recipient instance_attribute_dict -- dictionary of instance attributes to update meta_attribute_dict -- dictionary of meta attributes to update recipient_id -- id of new recipient, if None it will be generated description -- recipient description allow_same_value -- if True unique recipient value is not required """ if not recipient_value: raise LibraryError( reports.required_option_is_missing(["value"]) ) cib = lib_env.get_cib(REQUIRED_CIB_VERSION) id_provider = IdProvider(cib) recipient = alert.add_recipient( lib_env.report_processor, cib, alert_id, recipient_value, recipient_id=recipient_id, description=description, allow_same_value=allow_same_value ) arrange_first_instance_attributes( recipient, instance_attribute_dict, id_provider ) arrange_first_meta_attributes( recipient, meta_attribute_dict, id_provider ) lib_env.push_cib()
def __validate_quorum_device_model_net_options( self, model_options, need_required, force=False ): required_options = frozenset(["host", "algorithm"]) optional_options = frozenset([ "connect_timeout", "force_ip_version", "port", "tie_breaker", ]) allowed_options = required_options | optional_options model_options_names = frozenset(model_options.keys()) missing_options = [] report_items = [] severity = ( ReportItemSeverity.WARNING if force else ReportItemSeverity.ERROR ) forceable = None if force else report_codes.FORCE_OPTIONS if need_required: missing_options += required_options - model_options_names for name, value in sorted(model_options.items()): if name not in allowed_options: report_items.append(reports.invalid_options( [name], allowed_options, "quorum device model", severity=severity, forceable=forceable )) continue if value == "": # do not allow to remove required options if name in required_options: missing_options.append(name) else: continue if name == "algorithm": allowed_values = ("ffsplit", "lms") if value not in allowed_values: report_items.append(reports.invalid_option_value( name, value, allowed_values, severity=severity, forceable=forceable )) if name == "connect_timeout": minimum, maximum = 1000, 2*60*1000 if not (value.isdigit() and minimum <= int(value) <= maximum): min_max = "{min}-{max}".format(min=minimum, max=maximum) report_items.append(reports.invalid_option_value( name, value, min_max, severity=severity, forceable=forceable )) if name == "force_ip_version": allowed_values = ("0", "4", "6") if value not in allowed_values: report_items.append(reports.invalid_option_value( name, value, allowed_values, severity=severity, forceable=forceable )) if name == "port": minimum, maximum = 1, 65535 if not (value.isdigit() and minimum <= int(value) <= maximum): min_max = "{min}-{max}".format(min=minimum, max=maximum) report_items.append(reports.invalid_option_value( name, value, min_max, severity=severity, forceable=forceable )) if name == "tie_breaker": node_ids = [node.id for node in self.get_nodes()] allowed_nonid = ["lowest", "highest"] if value not in allowed_nonid + node_ids: allowed_values = allowed_nonid + ["valid node id"] report_items.append(reports.invalid_option_value( name, value, allowed_values, severity=severity, forceable=forceable )) if missing_options: report_items.append( reports.required_option_is_missing(sorted(missing_options)) ) return report_items
def __validate_quorum_device_model_net_options( self, model_options, need_required, force=False ): required_options = frozenset(["host", "algorithm"]) optional_options = frozenset([ "connect_timeout", "force_ip_version", "port", "tie_breaker", ]) allowed_options = required_options | optional_options model_options_names = frozenset(model_options.keys()) missing_options = [] report_items = [] severity = ( ReportItemSeverity.WARNING if force else ReportItemSeverity.ERROR ) forceable = None if force else report_codes.FORCE_OPTIONS if need_required: missing_options += required_options - model_options_names for name, value in sorted(model_options.items()): if name not in allowed_options: report_items.append(reports.invalid_option( [name], allowed_options, "quorum device model", severity, forceable )) continue if value == "": # do not allow to remove required options if name in required_options: missing_options.append(name) else: continue if name == "algorithm": allowed_values = ("ffsplit", "lms") if value not in allowed_values: report_items.append(reports.invalid_option_value( name, value, allowed_values, severity, forceable )) if name == "connect_timeout": minimum, maximum = 1000, 2*60*1000 if not (value.isdigit() and minimum <= int(value) <= maximum): min_max = "{min}-{max}".format(min=minimum, max=maximum) report_items.append(reports.invalid_option_value( name, value, min_max, severity, forceable )) if name == "force_ip_version": allowed_values = ("0", "4", "6") if value not in allowed_values: report_items.append(reports.invalid_option_value( name, value, allowed_values, severity, forceable )) if name == "port": minimum, maximum = 1, 65535 if not (value.isdigit() and minimum <= int(value) <= maximum): min_max = "{min}-{max}".format(min=minimum, max=maximum) report_items.append(reports.invalid_option_value( name, value, min_max, severity, forceable )) if name == "tie_breaker": node_ids = [node.id for node in self.get_nodes()] allowed_nonid = ["lowest", "highest"] if value not in allowed_nonid + node_ids: allowed_values = allowed_nonid + ["valid node id"] report_items.append(reports.invalid_option_value( name, value, allowed_values, severity, forceable )) if missing_options: report_items.append( reports.required_option_is_missing(sorted(missing_options)) ) return report_items