def _find_resource_elements_for_operation( report_processor: ReportProcessor, resources_section, booth_env, allow_multiple, ): booth_element_list = resource.find_for_config( resources_section, booth_env.config_path, ) if not booth_element_list: report_processor.report( ReportItem.error( reports.messages.BoothNotExistsInCib(booth_env.instance_name) ) ) elif len(booth_element_list) > 1: report_processor.report( ReportItem( severity=get_severity( report_codes.FORCE_BOOTH_REMOVE_FROM_CIB, allow_multiple, ), message=reports.messages.BoothMultipleTimesInCib( booth_env.instance_name, ), ) ) if report_processor.has_errors: raise LibraryError() return booth_element_list
def test_returns_empty_list_when_no_matching_booth_element(self): self.assertEqual( [], booth_resource.find_for_config( fixture_resources_with_booth("/ANOTHER/PATH/TO/CONF"), "/PATH/TO/CONF", ), )
def test_returns_all_found_resource_elements(self): resources = etree.fromstring('<resources/>') first = fixture_booth_element("first", "/PATH/TO/CONF") second = fixture_booth_element("second", "/ANOTHER/PATH/TO/CONF") third = fixture_booth_element("third", "/PATH/TO/CONF") for element in [first, second, third]: resources.append(element) self.assertEqual([first, third], booth_resource.find_for_config( resources, "/PATH/TO/CONF"))
def config_destroy(env, ignore_config_load_problems=False): env.booth.command_expect_live_env() if not env.is_cib_live: raise LibraryError(reports.live_environment_required(["CIB"])) name = env.booth.name config_is_used = partial(booth_reports.booth_config_is_used, name) report_list = [] if resource.find_for_config( get_resources(env.get_cib()), get_config_file_name(name), ): report_list.append(config_is_used("in cluster resource")) #Only systemd is currently supported. Initd does not supports multiple #instances (here specified by name) if external.is_systemctl(): if external.is_service_running(env.cmd_runner(), "booth", name): report_list.append(config_is_used("(running in systemd)")) if external.is_service_enabled(env.cmd_runner(), "booth", name): report_list.append(config_is_used("(enabled in systemd)")) if report_list: raise LibraryError(*report_list) authfile_path = None try: authfile_path = config_structure.get_authfile( parse(env.booth.get_config_content()) ) except LibraryError: if not ignore_config_load_problems: raise LibraryError(booth_reports.booth_cannot_identify_keyfile()) #if content not received, not valid,... still remove config needed env.report_processor.process( booth_reports.booth_cannot_identify_keyfile( severity=ReportItemSeverity.WARNING ) ) if( authfile_path and os.path.dirname(authfile_path) == settings.booth_config_dir ): env.booth.set_key_path(authfile_path) env.booth.remove_key() env.booth.remove_config()
def create_in_cluster(env, ip, allow_absent_resource_agent=False): """ Create group with ip resource and booth resource LibraryEnvironment env provides all for communication with externals string ip determines float ip for the operation of the booth bool allow_absent_resource_agent is flag allowing create booth resource even if its agent is not installed """ resources_section = get_resources(env.get_cib()) id_provider = IdProvider(resources_section) name = env.booth.name booth_config_file_path = get_config_file_name(name) if resource.find_for_config(resources_section, booth_config_file_path): raise LibraryError(booth_reports.booth_already_in_cib(name)) create_id = partial( resource.create_resource_id, resources_section, name ) get_agent = partial( find_valid_resource_agent_by_name, env.report_processor, env.cmd_runner(), allowed_absent=allow_absent_resource_agent ) create_primitive = partial( primitive.create, env.report_processor, resources_section, id_provider ) into_booth_group = partial( group.place_resource, group.provide_group(resources_section, create_id("group")), ) into_booth_group(create_primitive( create_id("ip"), get_agent("ocf:heartbeat:IPaddr2"), instance_attributes={"ip": ip}, )) into_booth_group(create_primitive( create_id("service"), get_agent("ocf:pacemaker:booth-site"), instance_attributes={"config": booth_config_file_path}, )) env.push_cib()
def create_in_cluster(env, name, ip, resource_create, resource_remove): #TODO resource_create is provisional hack until resources are not moved to #lib resources_section = get_resources(env.get_cib()) booth_config_file_path = get_config_file_name(name) if resource.find_for_config(resources_section, booth_config_file_path): raise LibraryError(booth_reports.booth_already_in_cib(name)) resource.get_creator(resource_create, resource_remove)( ip, booth_config_file_path, create_id=partial(resource.create_resource_id, resources_section, name))
def test_returns_all_found_resource_elements(self): resources = etree.fromstring('<resources/>') first = fixture_booth_element("first", "/PATH/TO/CONF") second = fixture_booth_element("second", "/ANOTHER/PATH/TO/CONF") third = fixture_booth_element("third", "/PATH/TO/CONF") for element in [first, second,third]: resources.append(element) self.assertEqual( [first, third], booth_resource.find_for_config( resources, "/PATH/TO/CONF" ) )
def create_in_cluster(env, name, ip, resource_create): #TODO resource_create is provisional hack until resources are not moved to #lib resources_section = get_resources(env.get_cib()) booth_config_file_path = get_config_file_name(name) if resource.find_for_config(resources_section, booth_config_file_path): raise LibraryError(booth_reports.booth_already_in_cib(name)) resource.get_creator(resource_create)( ip, booth_config_file_path, create_id = partial( resource.create_resource_id, resources_section, name ) )
def _find_resource_elements_for_operation(env, name, allow_multiple): booth_element_list = resource.find_for_config( get_resources(env.get_cib()), get_config_file_name(name), ) if not booth_element_list: raise LibraryError(booth_reports.booth_not_exists_in_cib(name)) if len(booth_element_list) > 1: if not allow_multiple: raise LibraryError(booth_reports.booth_multiple_times_in_cib(name)) env.report_processor.process( booth_reports.booth_multiple_times_in_cib( name, severity=ReportItemSeverity.WARNING, )) return booth_element_list
def _find_resource_elements_for_operation(report_processor, resources_section, booth_env, allow_multiple): booth_element_list = resource.find_for_config( resources_section, booth_env.config_path, ) if not booth_element_list: report_processor.report( booth_reports.booth_not_exists_in_cib(booth_env.instance_name)) elif len(booth_element_list) > 1: report_processor.report( booth_reports.booth_multiple_times_in_cib( booth_env.instance_name, severity=(ReportItemSeverity.WARNING if allow_multiple else ReportItemSeverity.ERROR))) if report_processor.has_errors: raise LibraryError() return booth_element_list
def _find_resource_elements_for_operation(env, name, allow_multiple): booth_element_list = resource.find_for_config( get_resources(env.get_cib()), get_config_file_name(name), ) if not booth_element_list: raise LibraryError(booth_reports.booth_not_exists_in_cib(name)) if len(booth_element_list) > 1: if not allow_multiple: raise LibraryError(booth_reports.booth_multiple_times_in_cib(name)) env.report_processor.process( booth_reports.booth_multiple_times_in_cib( name, severity=ReportItemSeverity.WARNING, ) ) return booth_element_list
def config_destroy( env: LibraryEnvironment, instance_name: Optional[str] = None, ignore_config_load_problems: bool = False, ) -> None: # pylint: disable=too-many-branches """ remove booth configuration files env instance_name -- booth instance name ignore_config_load_problems -- delete as much as possible when unable to read booth configs for the given booth instance """ report_processor = env.report_processor booth_env = env.get_booth_env(instance_name) found_instance_name = booth_env.instance_name _ensure_live_env(env, booth_env) booth_resource_list = resource.find_for_config( get_resources(env.get_cib()), booth_env.config_path, ) if booth_resource_list: report_processor.report( ReportItem.error( reports.messages.BoothConfigIsUsed( found_instance_name, reports.const.BOOTH_CONFIG_USED_IN_CLUSTER_RESOURCE, resource_name=str(booth_resource_list[0].get("id", "")), ) ) ) # Only systemd is currently supported. Initd does not supports multiple # instances (here specified by name) if is_systemd(env.service_manager): if env.service_manager.is_running("booth", found_instance_name): report_processor.report( ReportItem.error( reports.messages.BoothConfigIsUsed( found_instance_name, reports.const.BOOTH_CONFIG_USED_RUNNING_IN_SYSTEMD, ) ) ) if env.service_manager.is_enabled("booth", found_instance_name): report_processor.report( ReportItem.error( reports.messages.BoothConfigIsUsed( found_instance_name, reports.const.BOOTH_CONFIG_USED_ENABLED_IN_SYSTEMD, ) ) ) if report_processor.has_errors: raise LibraryError() try: authfile_path = None booth_conf = booth_env.config.read_to_facade() authfile_path = booth_conf.get_authfile() except RawFileError as e: report_processor.report( raw_file_error_report( e, force_code=report_codes.FORCE, is_forced_or_warning=ignore_config_load_problems, ) ) except ParserErrorException as e: report_processor.report_list( booth_env.config.parser_exception_to_report_list( e, force_code=report_codes.FORCE, is_forced_or_warning=ignore_config_load_problems, ) ) if report_processor.has_errors: raise LibraryError() if authfile_path: authfile_dir, authfile_name = os.path.split(authfile_path) if (authfile_dir == settings.booth_config_dir) and authfile_name: try: key_file = FileInstance.for_booth_key(authfile_name) key_file.raw_file.remove(fail_if_file_not_found=False) except RawFileError as e: report_processor.report( raw_file_error_report( e, force_code=report_codes.FORCE, is_forced_or_warning=ignore_config_load_problems, ) ) else: report_processor.report( ReportItem.warning( reports.messages.BoothUnsupportedFileLocation( authfile_path, settings.booth_config_dir, file_type_codes.BOOTH_KEY, ) ) ) if report_processor.has_errors: raise LibraryError() try: booth_env.config.raw_file.remove() except RawFileError as e: report_processor.report(raw_file_error_report(e)) if report_processor.has_errors: raise LibraryError()
def test_returns_empty_list_when_no_matching_booth_element(self): self.assertEqual([], booth_resource.find_for_config( fixture_resources_with_booth("/ANOTHER/PATH/TO/CONF"), "/PATH/TO/CONF" ))
def config_destroy( env: LibraryEnvironment, instance_name=None, ignore_config_load_problems=False, ): # pylint: disable=too-many-branches """ remove booth configuration files env string instance_name -- booth instance name bool ignore_config_load_problems -- delete as much as possible when unable to read booth configs for the given booth instance """ report_processor = env.report_processor booth_env = env.get_booth_env(instance_name) instance_name = booth_env.instance_name _ensure_live_env(env, booth_env) # TODO use constants in reports if resource.find_for_config( get_resources(env.get_cib()), booth_env.config_path, ): report_processor.report( ReportItem.error( reports.messages.BoothConfigIsUsed( instance_name, "in cluster resource", ) ) ) # Only systemd is currently supported. Initd does not supports multiple # instances (here specified by name) if external.is_systemctl(): if external.is_service_running( env.cmd_runner(), "booth", instance_name ): report_processor.report( ReportItem.error( reports.messages.BoothConfigIsUsed( instance_name, "(running in systemd)", ) ) ) if external.is_service_enabled( env.cmd_runner(), "booth", instance_name ): report_processor.report( ReportItem.error( reports.messages.BoothConfigIsUsed( instance_name, "(enabled in systemd)", ) ) ) if report_processor.has_errors: raise LibraryError() try: authfile_path = None booth_conf = booth_env.config.read_to_facade() authfile_path = booth_conf.get_authfile() except RawFileError as e: report_processor.report( raw_file_error_report( e, force_code=report_codes.FORCE_BOOTH_DESTROY, is_forced_or_warning=ignore_config_load_problems, ) ) except ParserErrorException as e: report_processor.report_list( booth_env.config.parser_exception_to_report_list( e, force_code=report_codes.FORCE_BOOTH_DESTROY, is_forced_or_warning=ignore_config_load_problems, ) ) if report_processor.has_errors: raise LibraryError() if authfile_path: authfile_dir, authfile_name = os.path.split(authfile_path) if (authfile_dir == settings.booth_config_dir) and authfile_name: try: key_file = FileInstance.for_booth_key(authfile_name) key_file.raw_file.remove(fail_if_file_not_found=False) except RawFileError as e: report_processor.report( raw_file_error_report( e, force_code=report_codes.FORCE_BOOTH_DESTROY, is_forced_or_warning=ignore_config_load_problems, ) ) else: report_processor.report( ReportItem.warning( reports.messages.BoothUnsupportedFileLocation( authfile_path, settings.booth_config_dir, file_type_codes.BOOTH_KEY, ) ) ) if report_processor.has_errors: raise LibraryError() try: booth_env.config.raw_file.remove() except RawFileError as e: report_processor.report(raw_file_error_report(e)) if report_processor.has_errors: raise LibraryError()
def create_in_cluster( env: LibraryEnvironment, ip, instance_name=None, allow_absent_resource_agent=False, ): """ Create group with ip resource and booth resource env -- provides all for communication with externals string ip -- float ip address for the operation of the booth string instance_name -- booth instance name bool allow_absent_resource_agent -- allowing creating booth resource even if its agent is not installed """ report_processor = env.report_processor booth_env = env.get_booth_env(instance_name) # Booth config path goes to CIB. Working with a mocked booth configs would # not work coorectly as the path would point to a mock file (the path to a # mock file is unknown to us in the lib anyway) # It makes sense to work with a mocked CIB, though. Users can do other # changes to the CIB and push them to the cluster at once. _ensure_live_booth_env(booth_env) resources_section = get_resources(env.get_cib()) id_provider = IdProvider(resources_section) instance_name = booth_env.instance_name # validate if resource.find_for_config(resources_section, booth_env.config_path): report_processor.report( ReportItem.error(reports.messages.BoothAlreadyInCib(instance_name)) ) # verify the config exists and is readable try: booth_env.config.raw_file.read() except RawFileError as e: report_processor.report(raw_file_error_report(e)) if report_processor.has_errors: raise LibraryError() # validation done create_id = partial( resource.create_resource_id, resources_section, instance_name ) get_agent = partial( find_valid_resource_agent_by_name, env.report_processor, env.cmd_runner(), allowed_absent=allow_absent_resource_agent, ) create_primitive = partial( primitive.create, env.report_processor, resources_section, id_provider ) into_booth_group = partial( group.place_resource, group.provide_group(resources_section, create_id("group")), ) into_booth_group( create_primitive( create_id("ip"), get_agent("ocf:heartbeat:IPaddr2"), instance_attributes={"ip": ip}, ) ) into_booth_group( create_primitive( create_id("service"), get_agent("ocf:pacemaker:booth-site"), instance_attributes={"config": booth_env.config_path}, ) ) env.push_cib()
def create_in_cluster( env: LibraryEnvironment, ip: str, instance_name: Optional[str] = None, allow_absent_resource_agent: bool = False, ): """ Create group with ip resource and booth resource env -- provides all for communication with externals ip -- float ip address for the operation of the booth instance_name -- booth instance name allow_absent_resource_agent -- allowing creating booth resource even if its agent is not installed """ report_processor = env.report_processor booth_env = env.get_booth_env(instance_name) # Booth config path goes to CIB. Working with a mocked booth configs would # not work coorectly as the path would point to a mock file (the path to a # mock file is unknown to us in the lib anyway) # It makes sense to work with a mocked CIB, though. Users can do other # changes to the CIB and push them to the cluster at once. _ensure_live_booth_env(booth_env) resources_section = get_resources(env.get_cib()) id_provider = IdProvider(resources_section) instance_name = booth_env.instance_name # validate if resource.find_for_config(resources_section, booth_env.config_path): report_processor.report( ReportItem.error(reports.messages.BoothAlreadyInCib(instance_name)) ) # verify the config exists and is readable try: booth_env.config.raw_file.read() except RawFileError as e: report_processor.report(raw_file_error_report(e)) if report_processor.has_errors: raise LibraryError() # validation done create_id = partial( resource.create_resource_id, resources_section, instance_name ) create_primitive = partial( primitive.create, env.report_processor, resources_section, id_provider ) agent_factory = ResourceAgentFacadeFactory( env.cmd_runner(), report_processor ) # Group id validation is not needed since create_id creates a new unique # booth group identifier hierarchy.move_resources_to_group( group.append_new(resources_section, create_id("group")), [ create_primitive( create_id("ip"), _get_agent_facade( env.report_processor, agent_factory, allow_absent_resource_agent, ResourceAgentName("ocf", "heartbeat", "IPaddr2"), ), instance_attributes={"ip": ip}, ), create_primitive( create_id("service"), _get_agent_facade( env.report_processor, agent_factory, allow_absent_resource_agent, ResourceAgentName("ocf", "pacemaker", "booth-site"), ), instance_attributes={"config": booth_env.config_path}, ), ], ) env.push_cib()