def _process_components(self, instance_info): """ Gets SNOW components name, external_id and other identifiers :param instance_info: :return: """ collected_components = self._batch_collect(self._batch_collect_components, instance_info) for component in collected_components: data = {} component = self._filter_empty_metadata(component) identifiers = [] comp_name = component.get('name') comp_type = component.get('sys_class_name') external_id = component.get('sys_id') if component.get('fqdn'): identifiers.append(Identifiers.create_host_identifier(to_string(component['fqdn']))) if component.get('host_name'): identifiers.append(Identifiers.create_host_identifier(to_string(component['host_name']))) else: identifiers.append(Identifiers.create_host_identifier(to_string(comp_name))) identifiers.append(external_id) identifiers = Identifiers.append_lowercase_identifiers(identifiers) data.update(component) data.update({"identifiers": identifiers, "tags": instance_info.instance_tags}) self.component(external_id, comp_type, data)
def test_create_custom_identifier(self): self.assertEqual(Identifiers.create_custom_identifier('namespace', 'hostname'), 'urn:namespace:/hostname') self.assertEqual(Identifiers.create_custom_identifier('namespace', 'ABCDë.com'), 'urn:namespace:/ABCDë.com') self.assertEqual(Identifiers.create_custom_identifier('namespace', ''), 'urn:namespace:/')
def test_create_integration_identifier(self): self.assertEqual(Identifiers.create_integration_identifier('hostname', 'integration-name'), 'urn:agent-integration:/hostname:integration-name') self.assertEqual(Identifiers.create_integration_identifier('hostname', 'ABCDë.com'), 'urn:agent-integration:/hostname:ABCDë.com') self.assertEqual(Identifiers.create_integration_identifier('hostname', ''), 'urn:agent-integration:/hostname:')
def _process_components(self, instance_info): """ Gets SNOW components name, external_id and other identifiers :param instance_info: :return: None """ collected_components = self._batch_collect( self._batch_collect_components, instance_info) for component in collected_components: try: config_item = ConfigurationItem(component, strict=False) config_item.validate() except DataError as e: self.log.warning( "Error while processing properties of CI {} having sys_id {} - {}" .format(config_item.sys_id.value, config_item.name.value, e)) continue data = {} component = self.select_metadata_field( component, instance_info.component_display_value_list) identifiers = [] comp_name = config_item.name.value comp_type = config_item.sys_class_name.value external_id = config_item.sys_id.value if config_item.fqdn.value: identifiers.append( Identifiers.create_host_identifier( to_string(config_item.fqdn.value))) if config_item.host_name.value: identifiers.append( Identifiers.create_host_identifier( to_string(config_item.host_name.value))) else: identifiers.append( Identifiers.create_host_identifier(to_string(comp_name))) identifiers.append(external_id) identifiers = Identifiers.append_lowercase_identifiers(identifiers) data.update(component) tags = instance_info.instance_tags sys_tags = config_item.sys_tags.display_value if sys_tags: sys_tags = list(map(lambda x: x.strip(), sys_tags.split(","))) tags = tags + sys_tags data.update({"identifiers": identifiers, "tags": tags}) self.component(external_id, comp_type, data)
def _create_event_from_change_request(self, change_request): host = Identifiers.create_host_identifier( to_string(change_request.custom_cmdb_ci.display_value)) identifiers = [change_request.custom_cmdb_ci.value, host] identifiers = Identifiers.append_lowercase_identifiers(identifiers) timestamp = (change_request.sys_updated_on.value - datetime.datetime.utcfromtimestamp(0)).total_seconds() msg_title = '%s: %s' % (change_request.number.display_value, change_request.short_description.display_value) tags = [ 'number:%s' % change_request.number.display_value, 'priority:%s' % change_request.priority.display_value, 'risk:%s' % change_request.risk.display_value, 'state:%s' % change_request.state.display_value, 'category:%s' % change_request.category.display_value, 'conflict_status:%s' % change_request.conflict_status.display_value, 'assigned_to:%s' % change_request.assigned_to.display_value, ] event_type = 'Change Request %s' % change_request.type.display_value self.log.debug('Creating event from CR %s', change_request.number.display_value) self.event({ 'timestamp': timestamp, 'event_type': event_type, 'msg_title': msg_title, 'msg_text': change_request.description.display_value, 'context': { 'source': 'servicenow', 'category': 'change_request', 'element_identifiers': identifiers, 'source_links': [], 'data': { 'impact': change_request.impact.display_value, 'requested_by': change_request.requested_by.display_value, 'conflict_last_run': change_request.conflict_last_run.display_value, 'assignment_group': change_request.assignment_group.display_value, 'service_offering': change_request.service_offering.display_value, }, }, 'tags': tags })
def test_append_lowercase_identifiers(self): identifiers = [ 'A9C0C8D2C6112276018F7705562F9CB0', 'urn:host:/Some Host', 'urn:dynatrace:/HOST-AA6A5D81A0006807', 'urn:process:/Some process', 'urn:container:/ABC', 'urn:service:/Some Service', 'urn:service-instance:/Some Service Instance', 'urn:host:/ABCDë.com' ] fixed_identifiers = Identifiers.append_lowercase_identifiers(identifiers) expected_identifiers = [ 'A9C0C8D2C6112276018F7705562F9CB0', 'urn:host:/Some Host', 'urn:dynatrace:/HOST-AA6A5D81A0006807', 'urn:process:/Some process', 'urn:container:/ABC', 'urn:service:/Some Service', 'urn:service-instance:/Some Service Instance', 'urn:host:/ABCDë.com', 'urn:host:/some host', 'urn:process:/some process', 'urn:container:/abc', 'urn:service:/some service', 'urn:service-instance:/some service instance', 'urn:host:/abcdë.com' ] self.assertEqual(expected_identifiers, fixed_identifiers)
def _process_events(self, dynatrace_client, instance_info): """ Wrapper to collect events, filters those events and persist the state """ severity_levels_that_maps_to_deviating_health_state = [ "PERFORMANCE", "RESOURCE_CONTENTION", "MONITORING_UNAVAILABLE", "ERROR" ] severity_levels_that_maps_to_critical_health_state = [ "AVAILABILITY", "CUSTOM_ALERT" ] events, events_limit_reached = self._collect_events( dynatrace_client, instance_info) open_events = [e for e in events if e.get('eventStatus') == 'OPEN'] closed_events = len(events) - len(open_events) self.log.info("Collected %d events, %d are open and %d are closed.", len(events), len(open_events), closed_events) self.health.start_snapshot() for event in open_events: if event.severityLevel == 'INFO': # Events with a info severity are send as topology events link_to_entity = self.link_to_dynatrace( str(event.entityId), instance_info.url) self._create_topology_event(event, link_to_entity) else: # Create health state for other events if event.severityLevel in severity_levels_that_maps_to_deviating_health_state: health_value = Health.DEVIATING elif event.severityLevel in severity_levels_that_maps_to_critical_health_state: health_value = Health.CRITICAL else: health_value = Health.CLEAR identifier = Identifiers.create_custom_identifier( "dynatrace", event.entityId) self.health.check_state( check_state_id=event.entityId, name='Dynatrace event', health_value=health_value, topology_element_identifier=identifier, message= 'Event: {} Severity: {} Impact: {} Open Since: {} Source: {}' .format(event.eventType, event.severityLevel, event.impactLevel, event.startTime, event.source)) self.health.stop_snapshot() if events_limit_reached: raise EventLimitReachedException(events_limit_reached)
def test_create_agent_identifier(self): self.assertEqual(Identifiers.create_agent_identifier('hostname'), 'urn:stackstate-agent:/hostname') self.assertEqual(Identifiers.create_agent_identifier('ABCDë.com'), 'urn:stackstate-agent:/ABCDë.com') self.assertEqual(Identifiers.create_agent_identifier(''), 'urn:stackstate-agent:/')
def test_create_trace_service_instance_identifier(self): self.assertEqual(Identifiers.create_trace_service_instance_identifier('service-name'), 'urn:service-instance:/service-name') self.assertEqual(Identifiers.create_trace_service_instance_identifier('ABCDë.com'), 'urn:service-instance:/ABCDë.com') self.assertEqual(Identifiers.create_trace_service_instance_identifier(''), 'urn:service-instance:/')
def test_create_container_identifier(self): self.assertEqual(Identifiers.create_container_identifier('hostname', 123), 'urn:container:/hostname:123') self.assertEqual(Identifiers.create_container_identifier('ABCDë.com', '123'), 'urn:container:/ABCDë.com:123') self.assertEqual(Identifiers.create_container_identifier('', long(123)), 'urn:container:/:123')
def test_create_process_identifier(self): self.assertEqual(Identifiers.create_process_identifier('hostname', 1, 123), 'urn:process:/hostname:1:123') self.assertEqual(Identifiers.create_process_identifier('ABCDë.com', 1, '123'), 'urn:process:/ABCDë.com:1:123') self.assertEqual(Identifiers.create_process_identifier('ABCDë.com', 1, long(123)), 'urn:process:/ABCDë.com:1:123') self.assertEqual(Identifiers.create_process_identifier('', 1, float(123)), 'urn:process:/:1:123.0')
def _create_event_from_change_request(self, change_request): """ StackState topology event is created from ServiceNow Change Request (CR). Time of event is based on when the CR was last time updated. :param change_request: ChangeRequest object :return: None """ host = Identifiers.create_host_identifier( to_string(change_request.custom_cmdb_ci.display_value)) identifiers = [change_request.custom_cmdb_ci.value, host] identifiers = Identifiers.append_lowercase_identifiers(identifiers) timestamp = (change_request.sys_updated_on.value - datetime.datetime.utcfromtimestamp(0)).total_seconds() msg_title = '%s: %s' % (change_request.number.display_value, change_request.short_description.display_value or 'No short description') msg_txt = change_request.description.display_value or 'No description' tags = [ 'number:%s' % change_request.number.display_value, 'priority:%s' % change_request.priority.display_value, 'risk:%s' % change_request.risk.display_value, 'impact:%s' % change_request.impact.display_value, 'state:%s' % change_request.state.display_value, 'category:%s' % change_request.category.display_value, ] event_type = 'Change Request %s' % change_request.type.display_value self.log.debug('Creating STS topology event from SNOW CR %s', change_request.number.display_value) self.event({ 'timestamp': timestamp, 'event_type': event_type, 'msg_title': msg_title, 'msg_text': msg_txt, 'context': { 'source': 'servicenow', 'category': 'change_request', 'element_identifiers': identifiers, 'source_links': [], 'data': { 'requested_by': change_request.requested_by.display_value, 'assignment_group': change_request.assignment_group.display_value, 'assigned_to': change_request.assigned_to.display_value, 'conflict_status': change_request.conflict_status.display_value, 'conflict_last_run': change_request.conflict_last_run.display_value, 'service_offering': change_request.service_offering.display_value, 'start_date': change_request.custom_planned_start_date.display_value, 'end_date': change_request.custom_planned_end_date.display_value, }, }, 'tags': tags })