You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
291 lines
20 KiB
291 lines
20 KiB
# Copyright (C) 2005-2024 Splunk Inc. All Rights Reserved.
|
|
from itsi.objects.model.itsi_model_validator import ItsiModelValidator
|
|
from migration.migration_precheck import MigrationPreCheck
|
|
|
|
|
|
class SIMigrationPreCheck(MigrationPreCheck):
|
|
"""
|
|
SI migration prechecks. The checks being performed are:
|
|
* Check for service templates that are not synced
|
|
* Check for service templates that have dangling linked service refs
|
|
* Check that a service template's linked services have a reciprocating base_service_template_id backref
|
|
* Check that a service's base_service_template_id has have a reciprocating linked_services backref
|
|
* Check for service objects that have dangling depends_on and/or depends_on_me service refs
|
|
* Check for KPIs that have dangling shared_base search refs
|
|
* Check for KPIs that have dangling kpi_threshold_template_id refs
|
|
"""
|
|
def __init__(self, session_key, logger, pre_checks, skip_pre_checks=[]):
|
|
MigrationPreCheck.__init__(self, session_key, logger, pre_checks, skip_pre_checks)
|
|
self.itsi_model_validator = ItsiModelValidator(session_key, logger)
|
|
|
|
@staticmethod
|
|
def collect_service_depends_info_strings(service_obj, services_depends_attr):
|
|
"""
|
|
Get a service's service dependency ids for the given service dependency attribute.
|
|
:param service_obj: the service object to get service dependency ids for
|
|
:param services_depends_attr: the service dependency attribute
|
|
:return: list of service dependency ids
|
|
"""
|
|
service_depends_info_strings = ["%s (%s)" % (services_depend_obj['identifying_name'], services_depend_obj['_key']) for
|
|
services_depend_obj in service_obj.get(services_depends_attr, [])]
|
|
return service_depends_info_strings
|
|
|
|
def precheck_SVC_SVCTMPL(self):
|
|
"""
|
|
* Check for service templates that are not synced
|
|
* Check for service templates that have dangling linked service refs
|
|
* Check that a service template's linked services have a reciprocating base_service_template_id backref
|
|
* Check that a service's base_service_template_id has have a reciprocating linked_services backref
|
|
* Check for service objects that have dangling depends_on and/or depends_on_me service refs
|
|
:return: None
|
|
"""
|
|
# Loop through all service templates
|
|
self.itsi_model_validator.check_service_templates()
|
|
|
|
# Loop through all services in chunks
|
|
self.itsi_model_validator.check_services()
|
|
|
|
ret_list = []
|
|
|
|
# service templates with bad sync_status
|
|
|
|
self.logger.info('Service templates with bad sync_status count: %s',
|
|
len(self.itsi_model_validator.service_template_bad_sync_status))
|
|
for service_template_obj in self.itsi_model_validator.service_template_bad_sync_status:
|
|
ret_list.append(self._make_result(False, "Service template: %s (%s) is not synced: %s" % (
|
|
service_template_obj.get('identifying_name', ''), service_template_obj['_key'],
|
|
service_template_obj['sync_status']), "Error"))
|
|
|
|
# service templates with dangling linked service ids
|
|
self.logger.info('Service templates with dangling linked_services count: %s',
|
|
len(self.itsi_model_validator.service_template_id_to_missing_linked_services_map))
|
|
for service_template_id in self.itsi_model_validator.service_template_id_to_missing_linked_services_map:
|
|
service_template_obj = self.itsi_model_validator.service_template_id_to_missing_linked_services_map[
|
|
service_template_id]
|
|
service_ids_missing = service_template_obj['linked_services']
|
|
ret_list.append(self._make_result(False, "Service template: %s (%s) has %s dangling linked_services" % (
|
|
service_template_obj.get('identifying_name', ''), service_template_obj['_key'], len(service_ids_missing)
|
|
), "Warn"))
|
|
self.logger.warn("Service template: %s (%s) has %s dangling linked_services: %s" % (
|
|
service_template_obj.get('identifying_name', ''), service_template_obj['_key'],
|
|
len(service_ids_missing), ','.join(service_ids_missing)))
|
|
|
|
# check that a service template's linked services have a reciprocating base_service_template_id backref
|
|
self.logger.info('Services with missing expected base_service_template_id count: %s',
|
|
len(self.itsi_model_validator.service_objects_missing_expected_service_template_id))
|
|
for service_object_missing_expected_service_template_id in \
|
|
self.itsi_model_validator.service_objects_missing_expected_service_template_id:
|
|
base_service_template_id = service_object_missing_expected_service_template_id.get(
|
|
'base_service_template_id', '')
|
|
base_service_template_expected = service_object_missing_expected_service_template_id[
|
|
'base_service_template_expected']
|
|
base_service_template_expected_id = base_service_template_expected['_key']
|
|
base_service_template_expected_name = base_service_template_expected['identifying_name']
|
|
ret_list.append(
|
|
self._make_result(
|
|
False,
|
|
"Service: %s (%s) is missing expected base service template: %s (%s)\
|
|
where actual base_service_template_id is: %s" % (
|
|
service_object_missing_expected_service_template_id.get(
|
|
'identifying_name', ''),
|
|
service_object_missing_expected_service_template_id['_key'],
|
|
base_service_template_expected_name, base_service_template_expected_id,
|
|
base_service_template_id), "Warn"))
|
|
|
|
# check that a service's base_service_template_id has have a reciprocating linked_services backref
|
|
self.logger.info('Service templates with missing expected linked_services count: %s',
|
|
len(self.itsi_model_validator.service_template_objects_missing_expected_linked_services_map))
|
|
for service_template_id in \
|
|
self.itsi_model_validator.service_template_objects_missing_expected_linked_services_map:
|
|
service_template_object_missing_expected_linked_services =\
|
|
self.itsi_model_validator.\
|
|
service_template_objects_missing_expected_linked_services_map[service_template_id]
|
|
missing_linked_services = service_template_object_missing_expected_linked_services['linked_services']
|
|
ret_list.append(
|
|
self._make_result(
|
|
False, "Service template: %s (%s) is missing %s expected linked_services" % (
|
|
service_template_object_missing_expected_linked_services.get(
|
|
'identifying_name', ''),
|
|
service_template_object_missing_expected_linked_services['_key'],
|
|
len(missing_linked_services)), "Warn"))
|
|
self.logger.warn("Service template: %s (%s) is missing %s expected linked_services: %s" % (
|
|
service_template_object_missing_expected_linked_services.get(
|
|
'identifying_name', ''),
|
|
service_template_object_missing_expected_linked_services['_key'],
|
|
len(missing_linked_services), ','.join(
|
|
["%s (%s)" % (missing_linked_service['identifying_name'], missing_linked_service['_key'])
|
|
for missing_linked_service in missing_linked_services])))
|
|
|
|
# services with dangling service template id
|
|
self.logger.info('Services with dangling base_service_template_id count: %s',
|
|
len(self.itsi_model_validator.service_objs_missing_service_template_id))
|
|
for service_obj_missing_service_template_id in \
|
|
self.itsi_model_validator.service_objs_missing_service_template_id:
|
|
ret_list.append(self._make_result(False, "Service: %s (%s) has a dangling base_service_template_id: %s" % (
|
|
service_obj_missing_service_template_id.get('identifying_name', ''),
|
|
service_obj_missing_service_template_id['_key'],
|
|
service_obj_missing_service_template_id['base_service_template_id']), "Warn"))
|
|
|
|
# Check service bidirectional dependencies for each service, lookup services using services_depends_on.
|
|
# For each of those services, ensure that services_depending_on_me contains the original service.
|
|
# Remove verified ids from services_depends_on and services_depending_on_me.
|
|
# Loop through services and for those that have non-empty services_depends_on or services_depending_on_me,
|
|
# mark as error because they are dangling references
|
|
self.logger.info('Services with dangling services_depends_on and/or services_depending_on_me count: %s',
|
|
len(self.itsi_model_validator.service_objects_with_dangling_service_refs))
|
|
for service_obj in self.itsi_model_validator.service_objects_with_dangling_service_refs:
|
|
services_depends_on_info_strings = set()
|
|
self.itsi_model_validator.collect_service_depends_service_ids(service_obj, 'services_depends_on',
|
|
services_depends_on_info_strings)
|
|
services_depending_on_me_info_strings = set()
|
|
self.itsi_model_validator.collect_service_depends_service_ids(service_obj, 'services_depending_on_me',
|
|
services_depending_on_me_info_strings)
|
|
if services_depends_on_info_strings:
|
|
ret_list.append(self._make_result(False, "Service: %s (%s) has %s dangling services_depends_on" % (
|
|
service_obj.get('identifying_name', ''), service_obj['_key'], len(services_depends_on_info_strings)), "Warn"))
|
|
self.logger.warn("Service: %s (%s) has %s dangling services_depends_on: %s" % (
|
|
service_obj.get('identifying_name', ''), service_obj['_key'], len(services_depends_on_info_strings),
|
|
','.join(services_depends_on_info_strings)))
|
|
if services_depending_on_me_info_strings:
|
|
ret_list.append(self._make_result(False,
|
|
"Service: %s (%s) has %s dangling services_depending_on_me" % (
|
|
service_obj.get('identifying_name', ''), service_obj['_key'],
|
|
len(services_depending_on_me_info_strings)), "Warn"))
|
|
self.logger.warn("Service: %s (%s) has %s dangling services_depending_on_me: %s" % (
|
|
service_obj.get('identifying_name', ''), service_obj['_key'],
|
|
len(services_depending_on_me_info_strings),
|
|
','.join(services_depending_on_me_info_strings)))
|
|
|
|
self.logger.info('Services with missing expected services_depends_on and/or services_depending_on_me count: %s',
|
|
len(self.itsi_model_validator.service_objects_with_missing_depends_service_refs_map))
|
|
for reverse_service_id in self.itsi_model_validator.service_objects_with_missing_depends_service_refs_map:
|
|
reverse_service_obj = self.itsi_model_validator.\
|
|
service_objects_with_missing_depends_service_refs_map[reverse_service_id]
|
|
services_depends_on_info_strings = self.collect_service_depends_info_strings(
|
|
reverse_service_obj, 'services_depends_on')
|
|
services_depending_on_me_info_strings = self.collect_service_depends_info_strings(
|
|
reverse_service_obj, 'services_depending_on_me')
|
|
if services_depends_on_info_strings:
|
|
ret_list.append(self._make_result(False, "Service: %s (%s) has %s missing services_depends_on" % (
|
|
reverse_service_obj.get('identifying_name', ''), reverse_service_obj['_key'],
|
|
len(services_depends_on_info_strings)), "Warn"))
|
|
self.logger.warn("Service: %s (%s) has %s missing services_depends_on: %s" % (
|
|
reverse_service_obj.get('identifying_name', ''), reverse_service_obj['_key'],
|
|
len(services_depends_on_info_strings), ','.join(services_depends_on_info_strings)))
|
|
if services_depending_on_me_info_strings:
|
|
ret_list.append(self._make_result(False,
|
|
"Service: %s (%s) had missing services_depending_on_me refs: %s" % (
|
|
reverse_service_obj.get('identifying_name', ''),
|
|
reverse_service_obj['_key'],
|
|
','.join(services_depending_on_me_info_strings)), "Warn"))
|
|
self.logger.warn("Service: %s (%s) has %s missing services_depending_on_me: %s" % (
|
|
reverse_service_obj.get('identifying_name', ''), reverse_service_obj['_key'],
|
|
len(services_depending_on_me_info_strings), ','.join(services_depending_on_me_info_strings)))
|
|
|
|
if ret_list:
|
|
return ret_list
|
|
return [self._make_result(True, "Services and service template ref checks passed", "Success")]
|
|
|
|
def _make_obj_with_corrupt_kpis_results(self, obj_with_corrupt_kpis):
|
|
"""
|
|
Make precheck failed results for object whose KPIs that have a mismatch of base_search_id and search_type.
|
|
:param obj_with_corrupt_kpis: object with list of KPIs with corrupt base search
|
|
:return: list of precheck results
|
|
"""
|
|
return [self._make_result(
|
|
False,
|
|
"%s: %s (%s) has KPI: %s that has mismatch of base_search_id: %s and search_type: %s" % (
|
|
obj_with_corrupt_kpis['object_type'],
|
|
obj_with_corrupt_kpis.get('identifying_name', ''),
|
|
obj_with_corrupt_kpis['_key'],
|
|
kpi_object_corrupt_search.get('title', ''),
|
|
kpi_object_corrupt_search.get('base_search_id', ''),
|
|
kpi_object_corrupt_search.get('search_type', '')
|
|
), "Warn") for kpi_object_corrupt_search in obj_with_corrupt_kpis['kpis']]
|
|
|
|
def _make_obj_with_dangling_shared_base_search_kpis_results(self, obj_with_dangling_shared_base_search_kpis):
|
|
"""
|
|
Make precheck failed results for object with KPIs whose base search id is dangling.
|
|
:param obj_with_dangling_shared_base_search_kpis: object with list of KPIs with dangling base search ids
|
|
:return: list of precheck results
|
|
"""
|
|
return [self._make_result(False,
|
|
"%s: %s (%s) has KPI: %s that has a dangling base_search_id: %s" % (
|
|
obj_with_dangling_shared_base_search_kpis['object_type'],
|
|
obj_with_dangling_shared_base_search_kpis.get('identifying_name', ''),
|
|
obj_with_dangling_shared_base_search_kpis['_key'],
|
|
dangling_shared_base_search_kpi.get('title', ''),
|
|
dangling_shared_base_search_kpi.get('base_search_id', '')
|
|
), "Warn") for dangling_shared_base_search_kpi in
|
|
obj_with_dangling_shared_base_search_kpis['kpis']]
|
|
|
|
def _make_obj_with_dangling_kpi_threshold_templates_results(self, obj_with_dangling_kpi_threshold_templates):
|
|
"""
|
|
Make precheck failed results for object with KPIs whose KPI threshold template is dangling.
|
|
:param obj_with_dangling_kpi_threshold_templates: object with list of KPIs with dangling KPI threshold templates
|
|
:return: list of precheck results
|
|
"""
|
|
return [self._make_result(False,
|
|
"%s: %s (%s) has KPI: %s that has a dangling kpi_threshold_template_id: %s" % (
|
|
obj_with_dangling_kpi_threshold_templates['object_type'],
|
|
obj_with_dangling_kpi_threshold_templates.get('identifying_name', ''),
|
|
obj_with_dangling_kpi_threshold_templates['_key'],
|
|
dangling_kpi_threshold_template_kpi.get('title', ''),
|
|
dangling_kpi_threshold_template_kpi.get('kpi_threshold_template_id', '')
|
|
), "Warn") for dangling_kpi_threshold_template_kpi in
|
|
obj_with_dangling_kpi_threshold_templates['kpis']]
|
|
|
|
def precheck_KPI(self):
|
|
"""
|
|
* Check for KPIs that have dangling shared_base search refs
|
|
* Check for KPIs that have dangling kpi_threshold_template_id refs
|
|
* Check for KPIs with empty threshold field
|
|
:return: results of check
|
|
"""
|
|
self.itsi_model_validator.check_kpis_in_collections()
|
|
self.itsi_model_validator.get_kpi_with_empty_threshold_field()
|
|
|
|
ret_list = []
|
|
|
|
# KPI search type mismatch with base search id
|
|
self.logger.info('Objects with corrupt KPI searches count: %s',
|
|
len(self.itsi_model_validator.objs_with_corrupt_kpis))
|
|
ret_list.extend([result for obj_with_corrupt_kpis in
|
|
self.itsi_model_validator.objs_with_corrupt_kpis for result in
|
|
self._make_obj_with_corrupt_kpis_results(obj_with_corrupt_kpis)])
|
|
|
|
# KPIs missing base search object
|
|
self.logger.info('Objects with KPIs that have dangling base_search_id count: %s',
|
|
len(self.itsi_model_validator.objs_with_dangling_shared_base_search_kpis))
|
|
ret_list.extend(
|
|
[result for obj_with_dangling_shared_base_search_kpis in
|
|
self.itsi_model_validator.objs_with_dangling_shared_base_search_kpis for
|
|
result in
|
|
self._make_obj_with_dangling_shared_base_search_kpis_results(obj_with_dangling_shared_base_search_kpis)])
|
|
|
|
# KPIs missing kpi threshold template object
|
|
self.logger.info('Objects with KPIs that have dangling kpi_threshold_template_id count: %s',
|
|
len(self.itsi_model_validator.objs_with_dangling_kpi_threshold_templates))
|
|
ret_list.extend(
|
|
[result for obj_with_dangling_kpi_threshold_templates in
|
|
self.itsi_model_validator.objs_with_dangling_kpi_threshold_templates for
|
|
result in
|
|
self._make_obj_with_dangling_kpi_threshold_templates_results(obj_with_dangling_kpi_threshold_templates)])
|
|
|
|
# KPIs with empty threshold field
|
|
self.logger.info('Objects with KPIs that have empty threshold field count: %s',
|
|
len(self.itsi_model_validator.kpi_with_empty_threshold_field))
|
|
make_result_list = [self._make_result(
|
|
False, "KPI: %s (%s) of %s type in service %s (%s) has empty threshold field" % (
|
|
kpi_with_empty_threshold.get('title', ''),
|
|
kpi_with_empty_threshold.get('_key', ''),
|
|
kpi_with_empty_threshold.get('search_type', ''),
|
|
kpi_with_empty_threshold.get('service_title', ''),
|
|
kpi_with_empty_threshold.get('service_id', '')
|
|
), "Warn") for kpi_with_empty_threshold in
|
|
self.itsi_model_validator.kpi_with_empty_threshold_field]
|
|
ret_list.extend(make_result_list)
|
|
if ret_list:
|
|
return ret_list
|
|
return [self._make_result(True, "KPI checks passed", "Success")]
|