diff --git a/vitrage/api/controllers/v1/topology.py b/vitrage/api/controllers/v1/topology.py index ad6ca4eab..d6b0de28c 100644 --- a/vitrage/api/controllers/v1/topology.py +++ b/vitrage/api/controllers/v1/topology.py @@ -22,9 +22,9 @@ from pecan.core import abort from vitrage.api.controllers.rest import RootRestController from vitrage.api.policy import enforce from vitrage.common.constants import VertexProperties as VProps -from vitrage.datasources import OPENSTACK_CLUSTER # noinspection PyProtectedMember +from vitrage.datasources.transformer_base import CLUSTER_ID from vitrage.i18n import _LI @@ -77,7 +77,7 @@ class TopologyController(RootRestController): if graph_type == 'graph': return graph if graph_type == 'tree': - node_id = OPENSTACK_CLUSTER + node_id = CLUSTER_ID if root: for node in graph['nodes']: if node[VProps.VITRAGE_ID] == root: diff --git a/vitrage/api_handler/apis/topology.py b/vitrage/api_handler/apis/topology.py index c8f088637..4be187eab 100644 --- a/vitrage/api_handler/apis/topology.py +++ b/vitrage/api_handler/apis/topology.py @@ -23,6 +23,7 @@ from vitrage.common.constants import VertexProperties as VProps from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE from vitrage.datasources import OPENSTACK_CLUSTER from vitrage.datasources.transformer_base import build_key +from vitrage.datasources.transformer_base import CLUSTER_ID from vitrage.graph import create_algorithm @@ -174,7 +175,9 @@ class TopologyApis(EntityGraphApisBase): entities = [] if not root: - root = build_key([EntityCategory.RESOURCE, OPENSTACK_CLUSTER]) + root = build_key([EntityCategory.RESOURCE, + OPENSTACK_CLUSTER, + CLUSTER_ID]) root_vertex = \ self.entity_graph.get_vertex(root) diff --git a/vitrage/cmd/graph.py b/vitrage/cmd/graph.py index c9e97f26b..42b19dd27 100644 --- a/vitrage/cmd/graph.py +++ b/vitrage/cmd/graph.py @@ -23,6 +23,7 @@ from vitrage.api_handler import service as api_handler_svc from vitrage.common.constants import EntityCategory from vitrage.datasources import launcher as datasource_launcher from vitrage.datasources import OPENSTACK_CLUSTER +from vitrage.datasources.transformer_base import CLUSTER_ID from vitrage.entity_graph.consistency import service as consistency_svc from vitrage.entity_graph.initialization_status import InitializationStatus from vitrage.entity_graph.processor import entity_graph @@ -68,7 +69,7 @@ def init(conf): evaluator_q = queue.Queue() e_graph = entity_graph.EntityGraph( 'Entity Graph', - '%s:%s' % (EntityCategory.RESOURCE, OPENSTACK_CLUSTER)) + '%s:%s:%s' % (EntityCategory.RESOURCE, OPENSTACK_CLUSTER, CLUSTER_ID)) scenario_repo = ScenarioRepository(conf) evaluator = ScenarioEvaluator(conf, e_graph, scenario_repo, evaluator_q) diff --git a/vitrage/datasources/alarm_transformer_base.py b/vitrage/datasources/alarm_transformer_base.py index 00b5b649a..c9fc8299c 100644 --- a/vitrage/datasources/alarm_transformer_base.py +++ b/vitrage/datasources/alarm_transformer_base.py @@ -16,16 +16,10 @@ from oslo_log import log as logging from vitrage.common.constants import DatasourceAction from vitrage.common.constants import DatasourceProperties as DSProps -from vitrage.common.constants import EdgeLabel -from vitrage.common.constants import EntityCategory from vitrage.common.constants import GraphAction -from vitrage.common.constants import VertexProperties as VProps from vitrage.common.exception import VitrageTransformerError from vitrage.datasources.alarm_properties import AlarmProperties as AlarmProps -from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE from vitrage.datasources import transformer_base as tbase -from vitrage.datasources.transformer_base import Neighbor -import vitrage.graph.utils as graph_utils LOG = logging.getLogger(__name__) @@ -59,45 +53,13 @@ class AlarmTransformerBase(tbase.TransformerBase): raise VitrageTransformerError('Invalid datasource action: (%s)' % datasource_action) - def create_placeholder_vertex(self, **kwargs): - LOG.info('An alarm cannot be a placeholder') - pass - - def _key_values(self, *args): - return (EntityCategory.ALARM,) + args - def _get_alarm_state(self, entity_event): event_type = entity_event.get(DSProps.EVENT_TYPE, None) - if event_type and event_type == GraphAction.DELETE_ENTITY: - return AlarmProps.INACTIVE_STATE + if event_type is not None: + return AlarmProps.INACTIVE_STATE if \ + GraphAction.DELETE_ENTITY == event_type else \ + AlarmProps.ACTIVE_STATE else: return AlarmProps.INACTIVE_STATE if \ self._ok_status(entity_event) else \ AlarmProps.ACTIVE_STATE - - def _create_neighbor(self, - vitrage_id, - sample_timestamp, - resource_type, - resource_name): - # Any resource transformer will do (nova for example) - transformer = self.transformers[NOVA_HOST_DATASOURCE] - - if transformer: - properties = { - VProps.TYPE: resource_type, - VProps.ID: resource_name, - VProps.SAMPLE_TIMESTAMP: sample_timestamp - } - resource_vertex = transformer.create_placeholder_vertex( - **properties) - - relationship_edge = graph_utils.create_edge( - source_id=vitrage_id, - target_id=resource_vertex.vertex_id, - relationship_type=EdgeLabel.ON) - - return Neighbor(resource_vertex, relationship_edge) - - LOG.warning('Cannot create neighbour, host transformer does not exist') - return None diff --git a/vitrage/datasources/aodh/transformer.py b/vitrage/datasources/aodh/transformer.py index c4aad9fbd..ff29a56d0 100644 --- a/vitrage/datasources/aodh/transformer.py +++ b/vitrage/datasources/aodh/transformer.py @@ -131,7 +131,7 @@ class AodhTransformer(AlarmTransformerBase): entity_type = entity_event[DSProps.ENTITY_TYPE] alarm_id = entity_event[AodhProps.ALARM_ID] - return tbase.build_key(self._key_values(entity_type, alarm_id)) + return tbase.build_key((EntityCategory.ALARM, entity_type, alarm_id)) @staticmethod def _timestamp(entity_event): diff --git a/vitrage/datasources/cinder/volume/transformer.py b/vitrage/datasources/cinder/volume/transformer.py index dd65d5834..52ce2d198 100644 --- a/vitrage/datasources/cinder/volume/transformer.py +++ b/vitrage/datasources/cinder/volume/transformer.py @@ -28,7 +28,6 @@ from vitrage.datasources.resource_transformer_base import \ from vitrage.datasources import transformer_base as tbase from vitrage.datasources.transformer_base import build_key from vitrage.datasources.transformer_base import extract_field_value -from vitrage.datasources.transformer_base import Neighbor import vitrage.graph.utils as graph_utils @@ -131,14 +130,14 @@ class CinderVolumeTransformer(ResourceTransformerBase): metadata=metadata) def _create_snapshot_neighbors(self, entity_event): - return self._create_instance_neighbors(entity_event, - 'attachments', - 'server_id') + return self._create_volume_neighbors(entity_event, + 'attachments', + 'server_id') def _create_update_neighbors(self, entity_event): - return self._create_instance_neighbors(entity_event, - 'volume_attachment', - 'instance_uuid') + return self._create_volume_neighbors(entity_event, + 'volume_attachment', + 'instance_uuid') def _create_entity_key(self, entity_event): @@ -149,47 +148,21 @@ class CinderVolumeTransformer(ResourceTransformerBase): key_fields = self._key_values(CINDER_VOLUME_DATASOURCE, volume_id) return build_key(key_fields) - def _create_instance_neighbors(self, - entity_event, - attachments_property, - instance_id_property): - transformer = self.transformers[NOVA_INSTANCE_DATASOURCE] + def _create_volume_neighbors(self, + entity_event, + attachments_property, + instance_id_property): + neighbors = [] - if transformer: - return [self._create_instance_neighbor(entity_event, - attachment, - transformer, - instance_id_property) - for attachment in entity_event[attachments_property]] - else: - LOG.warning('Cannot find instance transformer') + for attachment in entity_event[attachments_property]: + instance_neighbor_id = attachment[instance_id_property] + neighbors.append(self._create_neighbor(entity_event, + instance_neighbor_id, + NOVA_INSTANCE_DATASOURCE, + EdgeLabel.ATTACHED, + is_entity_source=True)) - def _create_instance_neighbor(self, - entity_event, - attachment, - instance_transformer, - instance_id_property): - volume_vitrage_id = self._create_entity_key(entity_event) - - instance_id = attachment[instance_id_property] - - sample_timestamp = entity_event[DSProps.SAMPLE_DATE] - - properties = { - VProps.ID: instance_id, - VProps.TYPE: NOVA_INSTANCE_DATASOURCE, - VProps.SAMPLE_TIMESTAMP: sample_timestamp - } - instance_vertex = \ - instance_transformer.create_placeholder_vertex( - **properties) - - relationship_edge = graph_utils.create_edge( - source_id=volume_vitrage_id, - target_id=instance_vertex.vertex_id, - relationship_type=EdgeLabel.ATTACHED) - - return Neighbor(instance_vertex, relationship_edge) + return neighbors def get_type(self): return CINDER_VOLUME_DATASOURCE diff --git a/vitrage/datasources/doctor/transformer.py b/vitrage/datasources/doctor/transformer.py index 863375910..cffc69393 100644 --- a/vitrage/datasources/doctor/transformer.py +++ b/vitrage/datasources/doctor/transformer.py @@ -15,6 +15,7 @@ from oslo_log import log as logging from vitrage.common.constants import DatasourceProperties as DSProps +from vitrage.common.constants import DatasourceProperties as EdgeLabel from vitrage.common.constants import EntityCategory from vitrage.common.constants import VertexProperties as VProps from vitrage.datasources.alarm_transformer_base import AlarmTransformerBase @@ -57,13 +58,15 @@ class DoctorTransformer(AlarmTransformerBase): def _create_update_neighbors(self, entity_event): return [self._create_neighbor( - self._create_entity_key(entity_event), - entity_event[DoctorProps.TIME], + entity_event, + get_detail(entity_event, DoctorDetails.HOSTNAME), DoctorProps.HOST_TYPE, - get_detail(entity_event, DoctorDetails.HOSTNAME))] + EdgeLabel.ON, + neighbor_category=EntityCategory.RESOURCE)] def _create_entity_key(self, entity_event): - return tbase.build_key(self._key_values( + return tbase.build_key(( + EntityCategory.ALARM, entity_event[DSProps.ENTITY_TYPE], entity_event[DoctorProps.TYPE], get_detail(entity_event, DoctorDetails.HOSTNAME))) diff --git a/vitrage/datasources/heat/stack/transformer.py b/vitrage/datasources/heat/stack/transformer.py index f573ac668..9982c56cc 100644 --- a/vitrage/datasources/heat/stack/transformer.py +++ b/vitrage/datasources/heat/stack/transformer.py @@ -27,7 +27,6 @@ from vitrage.datasources.resource_transformer_base import \ from vitrage.datasources import transformer_base as tbase from vitrage.datasources.transformer_base import build_key from vitrage.datasources.transformer_base import extract_field_value -from vitrage.datasources.transformer_base import Neighbor import vitrage.graph.utils as graph_utils @@ -105,10 +104,10 @@ class HeatStackTransformer(ResourceTransformerBase): metadata=metadata) def _create_snapshot_neighbors(self, entity_event): - return self._create_neighbors(entity_event) + return self._create_stack_neighbors(entity_event) def _create_update_neighbors(self, entity_event): - return self._create_neighbors(entity_event) + return self._create_stack_neighbors(entity_event) def _create_entity_key(self, entity_event): @@ -119,36 +118,20 @@ class HeatStackTransformer(ResourceTransformerBase): key_fields = self._key_values(HEAT_STACK_DATASOURCE, volume_id) return build_key(key_fields) - def _create_neighbors(self, entity_event): - return [self._create_neighbor(entity_event, neighbor) - for neighbor in entity_event['resources']] + def _create_stack_neighbors(self, entity_event): + neighbors = [] - def _create_neighbor(self, - entity_event, - neighbor): - datasource_type = \ - self.RESOURCE_TYPE_CONVERSION[neighbor['resource_type']] - transformer = self.transformers.get(datasource_type, None) + for neighbor in entity_event['resources']: + neighbor_id = neighbor['physical_resource_id'] + neighbor_datasource_type = \ + self.RESOURCE_TYPE_CONVERSION[neighbor['resource_type']] + neighbors.append(self._create_neighbor(entity_event, + neighbor_id, + neighbor_datasource_type, + EdgeLabel.COMPRISED, + is_entity_source=True)) - stack_vitrage_id = self._create_entity_key(entity_event) - - neighbor_id = neighbor['physical_resource_id'] - - sample_timestamp = entity_event[DSProps.SAMPLE_DATE] - - properties = { - VProps.ID: neighbor_id, - VProps.TYPE: datasource_type, - VProps.SAMPLE_TIMESTAMP: sample_timestamp - } - instance_vertex = transformer.create_placeholder_vertex(**properties) - - relationship_edge = graph_utils.create_edge( - source_id=stack_vitrage_id, - target_id=instance_vertex.vertex_id, - relationship_type=EdgeLabel.COMPRISED) - - return Neighbor(instance_vertex, relationship_edge) + return neighbors def get_type(self): return HEAT_STACK_DATASOURCE diff --git a/vitrage/datasources/nagios/transformer.py b/vitrage/datasources/nagios/transformer.py index fea6b2213..1c4cd253a 100644 --- a/vitrage/datasources/nagios/transformer.py +++ b/vitrage/datasources/nagios/transformer.py @@ -15,6 +15,7 @@ from oslo_log import log as logging from vitrage.common.constants import DatasourceProperties as DSProps +from vitrage.common.constants import EdgeLabel from vitrage.common.constants import EntityCategory from vitrage.common.constants import VertexProperties as VProps from vitrage.datasources.alarm_transformer_base import AlarmTransformerBase @@ -73,19 +74,14 @@ class NagiosTransformer(AlarmTransformerBase): return self._create_nagios_neighbors(entity_event) def _create_nagios_neighbors(self, entity_event): - vitrage_id = self._create_entity_key(entity_event) - timestamp = datetime_utils.change_time_str_format( - entity_event[NagiosProperties.LAST_CHECK], - '%Y-%m-%d %H:%M:%S', - tbase.TIMESTAMP_FORMAT) - resource_type = entity_event[NagiosProperties.RESOURCE_TYPE] if resource_type: return [self._create_neighbor( - vitrage_id, - timestamp, + entity_event, + entity_event[NagiosProperties.RESOURCE_NAME], resource_type, - entity_event[NagiosProperties.RESOURCE_NAME])] + EdgeLabel.ON, + neighbor_category=EntityCategory.RESOURCE)] return [] @@ -97,9 +93,10 @@ class NagiosTransformer(AlarmTransformerBase): entity_type = entity_event[DSProps.ENTITY_TYPE] alarm_name = entity_event[NagiosProperties.SERVICE] resource_name = entity_event[NagiosProperties.RESOURCE_NAME] - return tbase.build_key(self._key_values(entity_type, - resource_name, - alarm_name)) + return tbase.build_key((EntityCategory.ALARM, + entity_type, + resource_name, + alarm_name)) def get_type(self): return NAGIOS_DATASOURCE diff --git a/vitrage/datasources/neutron/port/transformer.py b/vitrage/datasources/neutron/port/transformer.py index db991ec54..4d4b3dadb 100644 --- a/vitrage/datasources/neutron/port/transformer.py +++ b/vitrage/datasources/neutron/port/transformer.py @@ -25,7 +25,6 @@ from vitrage.datasources.neutron.port import NEUTRON_PORT_DATASOURCE from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE from vitrage.datasources import transformer_base as tbase from vitrage.datasources.transformer_base import extract_field_value -from vitrage.datasources.transformer_base import Neighbor import vitrage.graph.utils as graph_utils @@ -134,64 +133,28 @@ class PortTransformer(ResourceTransformerBase): device_owner_property, device_id_property, network_id_property): - neighbors = [self._create_network_neighbor(entity_event, - network_id_property)] + network_neighbor_id = extract_field_value(entity_event, + *network_id_property) + neighbors = [self._create_neighbor(entity_event, + network_neighbor_id, + NEUTRON_NETWORK_DATASOURCE, + EdgeLabel.CONTAINS, + is_entity_source=False)] device_owner = \ extract_field_value(entity_event, *device_owner_property) if device_owner == 'compute:nova' or device_owner == 'compute:None': - instance = self._create_instance_neighbor( - entity_event, - device_id_property) + instance_neighbor_id = \ + extract_field_value(entity_event, *device_id_property) + instance = self._create_neighbor(entity_event, + instance_neighbor_id, + NOVA_INSTANCE_DATASOURCE, + EdgeLabel.ATTACHED, + is_entity_source=True) neighbors.append(instance) return neighbors - def _create_instance_neighbor(self, - entity_event, - instance_id_property): - port_vitrage_id = self._create_entity_key(entity_event) - - instance_id = extract_field_value(entity_event, *instance_id_property) - - sample_timestamp = entity_event[DSProps.SAMPLE_DATE] - - properties = { - VProps.ID: instance_id, - VProps.TYPE: NOVA_INSTANCE_DATASOURCE, - VProps.SAMPLE_TIMESTAMP: sample_timestamp - } - instance_vertex = self.create_placeholder_vertex(**properties) - - relationship_edge = graph_utils.create_edge( - source_id=port_vitrage_id, - target_id=instance_vertex.vertex_id, - relationship_type=EdgeLabel.ATTACHED) - - return Neighbor(instance_vertex, relationship_edge) - - def _create_network_neighbor(self, entity_event, net_id_property): - port_vitrage_id = self._create_entity_key(entity_event) - - net_id = extract_field_value(entity_event, *net_id_property) - - sample_timestamp = entity_event[DSProps.SAMPLE_DATE] - - properties = { - VProps.ID: net_id, - VProps.TYPE: NEUTRON_NETWORK_DATASOURCE, - VProps.SAMPLE_TIMESTAMP: sample_timestamp - } - - net_vertex = self.create_placeholder_vertex(**properties) - - relationship_edge = graph_utils.create_edge( - source_id=net_vertex.vertex_id, - target_id=port_vitrage_id, - relationship_type=EdgeLabel.CONTAINS) - - return Neighbor(net_vertex, relationship_edge) - def _create_entity_key(self, entity_event): event_type = entity_event.get(DSProps.EVENT_TYPE, None) port_id = extract_field_value(entity_event, diff --git a/vitrage/datasources/nova/host/transformer.py b/vitrage/datasources/nova/host/transformer.py index 073238230..c45670854 100644 --- a/vitrage/datasources/nova/host/transformer.py +++ b/vitrage/datasources/nova/host/transformer.py @@ -24,7 +24,6 @@ from vitrage.datasources.resource_transformer_base import \ ResourceTransformerBase from vitrage.datasources import transformer_base from vitrage.datasources.transformer_base import extract_field_value -from vitrage.datasources.transformer_base import Neighbor import vitrage.graph.utils as graph_utils @@ -63,55 +62,19 @@ class HostTransformer(ResourceTransformerBase): metadata=metadata) def _create_snapshot_neighbors(self, entity_event): - return self._create_nova_host_neighbors(entity_event) + return self._create_host_neighbors(entity_event) def _create_update_neighbors(self, entity_event): - return self._create_nova_host_neighbors(entity_event) + return self._create_host_neighbors(entity_event) - def _create_nova_host_neighbors(self, entity_event): - neighbors = [] - - # Support snapshot and snapshot_init events only - zone_neighbor = self._create_zone_neighbor( - entity_event, - entity_event[DSProps.SAMPLE_DATE], - self._create_entity_key(entity_event), - 'zone') - - if zone_neighbor is not None: - neighbors.append(zone_neighbor) - - return neighbors - - def _create_zone_neighbor(self, - entity_event, - sample_timestamp, - host_vertex_id, - zone_name_path): - - zone_transformer = self.transformers[NOVA_ZONE_DATASOURCE] - - if zone_transformer: - - zone_name = extract_field_value(entity_event, zone_name_path) - - properties = { - VProps.ID: zone_name, - VProps.TYPE: NOVA_ZONE_DATASOURCE, - VProps.SAMPLE_TIMESTAMP: sample_timestamp - } - zone_neighbor = zone_transformer.create_placeholder_vertex( - **properties) - - relation_edge = graph_utils.create_edge( - source_id=zone_neighbor.vertex_id, - target_id=host_vertex_id, - relationship_type=EdgeLabel.CONTAINS) - return Neighbor(zone_neighbor, relation_edge) - else: - LOG.warning('Cannot find zone transformer') - - return None + def _create_host_neighbors(self, entity_event): + zone_name = extract_field_value(entity_event, 'zone') + zone_neighbor = self._create_neighbor(entity_event, + zone_name, + NOVA_ZONE_DATASOURCE, + EdgeLabel.CONTAINS, + is_entity_source=False) + return [zone_neighbor] def _create_entity_key(self, entity_event): diff --git a/vitrage/datasources/nova/instance/transformer.py b/vitrage/datasources/nova/instance/transformer.py index 2fb12e627..b971a6562 100644 --- a/vitrage/datasources/nova/instance/transformer.py +++ b/vitrage/datasources/nova/instance/transformer.py @@ -25,7 +25,6 @@ from vitrage.datasources.resource_transformer_base import \ ResourceTransformerBase from vitrage.datasources import transformer_base as tbase from vitrage.datasources.transformer_base import extract_field_value -from vitrage.datasources.transformer_base import Neighbor import vitrage.graph.utils as graph_utils @@ -84,29 +83,22 @@ class InstanceTransformer(ResourceTransformerBase): metadata=metadata) def _create_snapshot_neighbors(self, entity_event): - return self._create_nova_instance_neighbors(entity_event) + return self._create_instance_neighbors(entity_event, + 'OS-EXT-SRV-ATTR:host') def _create_update_neighbors(self, entity_event): - return self._create_nova_instance_neighbors(entity_event) + return self._create_instance_neighbors(entity_event, + 'host') - def _create_nova_instance_neighbors(self, entity_event): - neighbors = [] - host_transformer = self.transformers[NOVA_HOST_DATASOURCE] + def _create_instance_neighbors(self, entity_event, host_property_name): + host_name = entity_event.get(host_property_name) + host_neighbor = self._create_neighbor(entity_event, + host_name, + NOVA_HOST_DATASOURCE, + EdgeLabel.CONTAINS, + is_entity_source=False) - host_name = 'host' if tbase.is_update_event(entity_event) \ - else 'OS-EXT-SRV-ATTR:host' - - if host_transformer: - host_neighbor = self._create_host_neighbor( - self._create_entity_key(entity_event), - extract_field_value(entity_event, host_name), - entity_event[DSProps.SAMPLE_DATE], - host_transformer) - neighbors.append(host_neighbor) - else: - LOG.warning('Cannot find host transformer') - - return neighbors + return [host_neighbor] def _create_entity_key(self, event): @@ -116,24 +108,5 @@ class InstanceTransformer(ResourceTransformerBase): instance_id)) return tbase.build_key(key_fields) - @staticmethod - def _create_host_neighbor(vertex_id, - host_name, - sample_timestamp, - host_transformer): - properties = { - VProps.ID: host_name, - VProps.TYPE: NOVA_HOST_DATASOURCE, - VProps.SAMPLE_TIMESTAMP: sample_timestamp - } - host_vertex = host_transformer.create_placeholder_vertex(**properties) - - relationship_edge = graph_utils.create_edge( - source_id=host_vertex.vertex_id, - target_id=vertex_id, - relationship_type=EdgeLabel.CONTAINS) - - return Neighbor(host_vertex, relationship_edge) - def get_type(self): return NOVA_INSTANCE_DATASOURCE diff --git a/vitrage/datasources/nova/zone/transformer.py b/vitrage/datasources/nova/zone/transformer.py index e84a7e6a0..7df2c0277 100644 --- a/vitrage/datasources/nova/zone/transformer.py +++ b/vitrage/datasources/nova/zone/transformer.py @@ -20,9 +20,11 @@ from vitrage.common.constants import EntityCategory from vitrage.common.constants import VertexProperties as VProps from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE from vitrage.datasources.nova.zone import NOVA_ZONE_DATASOURCE +from vitrage.datasources import OPENSTACK_CLUSTER from vitrage.datasources.resource_transformer_base import \ ResourceTransformerBase from vitrage.datasources import transformer_base as tbase +from vitrage.datasources.transformer_base import CLUSTER_ID from vitrage.datasources.transformer_base import extract_field_value import vitrage.graph.utils as graph_utils @@ -74,76 +76,55 @@ class ZoneTransformer(ResourceTransformerBase): metadata=metadata) def _create_snapshot_neighbors(self, entity_event): - return self._create_nova_zone_neighbors(entity_event) + return self._create_zone_neighbors(entity_event) def _create_update_neighbors(self, entity_event): - return self._create_nova_zone_neighbors(entity_event) + return self._create_zone_neighbors(entity_event) + + def _create_zone_neighbors(self, entity_event): + neighbors = [] + metadata = { + VProps.IS_PLACEHOLDER: False, + VProps.STATE: 'available' + } + cluster_neighbor = self._create_neighbor(entity_event, + CLUSTER_ID, + OPENSTACK_CLUSTER, + EdgeLabel.CONTAINS, + is_entity_source=False, + metadata=metadata) + neighbors.append(cluster_neighbor) - def _create_nova_zone_neighbors(self, entity_event): - zone_vertex_id = self._create_entity_key(entity_event) - neighbors = [self._create_cluster_neighbor(zone_vertex_id)] hosts = extract_field_value(entity_event, 'hosts') - host_transformer = self.transformers[NOVA_HOST_DATASOURCE] - if host_transformer: - for hostname, host_data in hosts.items(): + for hostname, host_data in hosts.items(): - host_available = extract_field_value(host_data, - 'nova-compute', - 'available') - host_active = extract_field_value(host_data, - 'nova-compute', - 'active') + host_available = extract_field_value(host_data, + 'nova-compute', + 'available') + host_active = extract_field_value(host_data, + 'nova-compute', + 'active') - host_state = self.STATE_AVAILABLE \ - if host_available and host_active \ - else self.STATE_UNAVAILABLE + host_state = self.STATE_AVAILABLE \ + if host_available and host_active \ + else self.STATE_UNAVAILABLE - host_neighbor = self._create_host_neighbor( - zone_vertex_id, - hostname, - host_state, - entity_event[DSProps.SAMPLE_DATE]) + metadata = { + VProps.STATE: host_state, + VProps.IS_PLACEHOLDER: False + } - neighbors.append(host_neighbor) - else: - LOG.warning('Cannot find host transformer') + host_neighbor = self._create_neighbor(entity_event, + hostname, + NOVA_HOST_DATASOURCE, + EdgeLabel.CONTAINS, + metadata=metadata, + is_entity_source=True) + neighbors.append(host_neighbor) return neighbors - @staticmethod - def _create_cluster_neighbor(zone_vertex_id): - - cluster_vertex = tbase.create_cluster_placeholder_vertex() - - relation_edge = graph_utils.create_edge( - source_id=cluster_vertex.vertex_id, - target_id=zone_vertex_id, - relationship_type=EdgeLabel.CONTAINS) - return tbase.Neighbor(cluster_vertex, relation_edge) - - def _create_host_neighbor(self, zone_id, host_name, - host_state, sample_timestamp): - - host_transformer = self.transformers[NOVA_HOST_DATASOURCE] - - properties = { - VProps.ID: host_name, - VProps.SAMPLE_TIMESTAMP: sample_timestamp, - VProps.TYPE: NOVA_HOST_DATASOURCE - } - host_neighbor = \ - host_transformer.create_placeholder_vertex(**properties) - host_neighbor[VProps.STATE] = host_state - host_neighbor[VProps.IS_PLACEHOLDER] = False - - relation_edge = graph_utils.create_edge( - source_id=zone_id, - target_id=host_neighbor.vertex_id, - relationship_type=EdgeLabel.CONTAINS) - - return tbase.Neighbor(host_neighbor, relation_edge) - def _create_entity_key(self, entity_event): zone_name = extract_field_value(entity_event, 'zoneName') diff --git a/vitrage/datasources/resource_transformer_base.py b/vitrage/datasources/resource_transformer_base.py index fce4083c5..8682d0c72 100644 --- a/vitrage/datasources/resource_transformer_base.py +++ b/vitrage/datasources/resource_transformer_base.py @@ -14,10 +14,7 @@ from oslo_log import log as logging -from vitrage.common.constants import EntityCategory -from vitrage.common.constants import VertexProperties as VProps from vitrage.datasources import transformer_base as tbase -import vitrage.graph.utils as graph_utils LOG = logging.getLogger(__name__) @@ -27,25 +24,3 @@ class ResourceTransformerBase(tbase.TransformerBase): def __init__(self, transformers, conf): super(ResourceTransformerBase, self).__init__(transformers, conf) - - def _key_values(self, *args): - return (EntityCategory.RESOURCE,) + args - - def create_placeholder_vertex(self, **kwargs): - if VProps.TYPE not in kwargs: - LOG.error("Can't create placeholder vertex. Missing property TYPE") - raise ValueError('Missing property TYPE') - - if VProps.ID not in kwargs: - LOG.error("Can't create placeholder vertex. Missing property ID") - raise ValueError('Missing property ID') - - key_fields = self._key_values(kwargs[VProps.TYPE], kwargs[VProps.ID]) - - return graph_utils.create_vertex( - tbase.build_key(key_fields), - entity_id=kwargs[VProps.ID], - entity_category=EntityCategory.RESOURCE, - entity_type=kwargs[VProps.TYPE], - sample_timestamp=kwargs[VProps.SAMPLE_TIMESTAMP], - is_placeholder=True) diff --git a/vitrage/datasources/static_physical/transformer.py b/vitrage/datasources/static_physical/transformer.py index 48f45ff98..a6dd7367c 100644 --- a/vitrage/datasources/static_physical/transformer.py +++ b/vitrage/datasources/static_physical/transformer.py @@ -24,7 +24,6 @@ from vitrage.datasources.resource_transformer_base import \ from vitrage.datasources.static_physical import STATIC_PHYSICAL_DATASOURCE from vitrage.datasources.static_physical import SWITCH from vitrage.datasources import transformer_base -from vitrage.datasources.transformer_base import Neighbor import vitrage.graph.utils as graph_utils LOG = logging.getLogger(__name__) @@ -81,49 +80,26 @@ class StaticPhysicalTransformer(ResourceTransformerBase): def _create_static_physical_neighbors(self, entity_event): neighbors = [] entity_type = entity_event[VProps.TYPE] - entity_key = self._create_entity_key(entity_event) - timestamp = entity_event[DSProps.SAMPLE_DATE] for neighbor_details in entity_event.get( self.RELATIONSHIPS_SECTION, {}): # TODO(alexey): need to decide what to do if one of the entities # fails - neighbor = self._create_neighbor(neighbor_details, entity_type, - entity_key, timestamp) + neighbor_id = neighbor_details[VProps.ID] + neighbor_type = neighbor_details[VProps.TYPE] + relation_type = neighbor_details[self.RELATION_TYPE] + is_entity_source = not self._find_relation_direction_source( + entity_type, neighbor_type) + neighbor = self._create_neighbor(entity_event, + neighbor_id, + neighbor_type, + relation_type, + is_entity_source=is_entity_source) if neighbor is not None: neighbors.append(neighbor) return neighbors - def _create_neighbor(self, neighbor_details, entity_type, - entity_key, sample_timestamp): - neighbor_type = neighbor_details[VProps.TYPE] - entity_transformer = self.transformers[neighbor_type] - - if entity_transformer: - neighbor_id = neighbor_details[VProps.ID] - relation_type = neighbor_details[self.RELATION_TYPE] - is_source = self._find_relation_direction_source( - entity_type, neighbor_type) - - properties = { - VProps.TYPE: neighbor_type, - VProps.ID: neighbor_id, - VProps.SAMPLE_TIMESTAMP: sample_timestamp - } - neighbor = entity_transformer.create_placeholder_vertex( - **properties) - - relation_edge = graph_utils.create_edge( - source_id=neighbor.vertex_id if is_source else entity_key, - target_id=entity_key if is_source else neighbor.vertex_id, - relationship_type=relation_type) - - return Neighbor(neighbor, relation_edge) - else: - LOG.warning('Cannot find zone transformer') - return None - def _create_entity_key(self, entity_event): entity_id = entity_event[VProps.ID] entity_type = entity_event[VProps.TYPE] diff --git a/vitrage/datasources/transformer_base.py b/vitrage/datasources/transformer_base.py index 16ac3cfa8..0fbe145ba 100644 --- a/vitrage/datasources/transformer_base.py +++ b/vitrage/datasources/transformer_base.py @@ -22,8 +22,10 @@ from oslo_log import log as logging import vitrage.common.constants as cons from vitrage.common.constants import DatasourceAction from vitrage.common.constants import DatasourceProperties as DSProps +from vitrage.common.constants import EntityCategory from vitrage.common.constants import GraphAction from vitrage.common.constants import UpdateMethod +from vitrage.common.constants import VertexProperties as VProps from vitrage.common.exception import VitrageTransformerError from vitrage.datasources import OPENSTACK_CLUSTER import vitrage.graph.utils as graph_utils @@ -42,6 +44,7 @@ TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%SZ' AVAILABLE = 'available' +CLUSTER_ID = 'OpenStack Cluster' def extract_field_value(entity_event, *args): @@ -61,7 +64,8 @@ def build_key(key_values): def create_cluster_placeholder_vertex(): key = build_key([cons.EntityCategory.RESOURCE, - OPENSTACK_CLUSTER]) + OPENSTACK_CLUSTER, + CLUSTER_ID]) metadata = { cons.VertexProperties.NAME: OPENSTACK_CLUSTER @@ -69,7 +73,7 @@ def create_cluster_placeholder_vertex(): return graph_utils.create_vertex( key, - entity_id=OPENSTACK_CLUSTER, + entity_id=CLUSTER_ID, entity_category=cons.EntityCategory.RESOURCE, entity_type=OPENSTACK_CLUSTER, entity_state=AVAILABLE, @@ -95,6 +99,7 @@ class TransformerBase(object): KEY_SEPARATOR = ':' QUERY_RESULT = 'graph_query_result' + METADATA = 'metadata' # graph actions which need to refer them differently GRAPH_ACTION_MAPPING = {} @@ -188,19 +193,78 @@ class TransformerBase(object): """ pass - @abc.abstractmethod - def create_placeholder_vertex(self, **kwargs): - """Creates placeholder vertex. + def _create_neighbor(self, + entity_event, + neighbor_id, + neighbor_datasource_type, + relationship_type, + neighbor_category=EntityCategory.RESOURCE, + is_entity_source=True, + metadata={}): + # create placeholder vertex + entity_vitrage_id = self._create_entity_key(entity_event) + sample_timestamp = entity_event[DSProps.SAMPLE_DATE] + properties = { + VProps.ID: neighbor_id, + VProps.TYPE: neighbor_datasource_type, + VProps.CATEGORY: neighbor_category, + VProps.SAMPLE_TIMESTAMP: sample_timestamp, + self.METADATA: metadata - Placeholder vertex contains only mandatory fields of this entity. - This way other datasources can create placeholder vertices of those - entities + } + neighbor_vertex = \ + self.create_neighbor_placeholder_vertex(**properties) - :param kwargs: the properties for the placeholder vertex - :return: Placeholder vertex - :rtype: Vertex - """ - pass + # connect placeholder vertex to entity vertex + edge_direction = self._get_edge_direction(entity_vitrage_id, + neighbor_vertex.vertex_id, + is_entity_source) + relationship_edge = graph_utils.create_edge( + source_id=edge_direction[0], + target_id=edge_direction[1], + relationship_type=relationship_type) + + return Neighbor(neighbor_vertex, relationship_edge) + + @staticmethod + def _get_edge_direction(entity_id, + neighbor_id, + is_entity_source): + source_id = entity_id + target_id = neighbor_id + + if not is_entity_source: + source_id = neighbor_id + target_id = entity_id + + return source_id, target_id + + def _key_values(self, *args): + return (EntityCategory.RESOURCE,) + args + + def create_neighbor_placeholder_vertex(self, **kwargs): + if VProps.TYPE not in kwargs: + LOG.error("Can't create placeholder vertex. Missing property TYPE") + raise ValueError('Missing property TYPE') + + if VProps.ID not in kwargs: + LOG.error("Can't create placeholder vertex. Missing property ID") + raise ValueError('Missing property ID') + + metadata = {} + if self.METADATA in kwargs: + metadata = kwargs[self.METADATA] + + key_fields = self._key_values(kwargs[VProps.TYPE], kwargs[VProps.ID]) + + return graph_utils.create_vertex( + build_key(key_fields), + entity_id=kwargs[VProps.ID], + entity_category=kwargs[VProps.CATEGORY], + entity_type=kwargs[VProps.TYPE], + sample_timestamp=kwargs[VProps.SAMPLE_TIMESTAMP], + is_placeholder=True, + metadata=metadata) def _extract_graph_action(self, entity_event): """Extract graph action. @@ -232,16 +296,6 @@ class TransformerBase(object): raise VitrageTransformerError( 'Invalid action type: (%s)' % datasource_action) - def _key_values(self, *args): - """A list of key fields - - The fields which consist the entity key - - :param args: a tuple of mutable key fields - :return: () - """ - pass - @staticmethod def _create_end_vertex(entity_event): entity_type = entity_event[DSProps.ENTITY_TYPE] diff --git a/vitrage/datasources/zabbix/transformer.py b/vitrage/datasources/zabbix/transformer.py index 27378ee89..aec18f4c2 100644 --- a/vitrage/datasources/zabbix/transformer.py +++ b/vitrage/datasources/zabbix/transformer.py @@ -15,6 +15,7 @@ from oslo_log import log as logging from vitrage.common.constants import DatasourceProperties as DSProps +from vitrage.common.constants import EdgeLabel from vitrage.common.constants import EntityCategory from vitrage.common.constants import VertexProperties as VProps from vitrage.datasources.alarm_properties import AlarmProperties as AlarmProps @@ -88,16 +89,14 @@ class ZabbixTransformer(AlarmTransformerBase): def _create_zabbix_neighbors(self, entity_event): self._unify_time_format(entity_event) - vitrage_id = self._create_entity_key(entity_event) - timestamp = entity_event[ZProps.TIMESTAMP] - resource_type = entity_event[ZProps.RESOURCE_TYPE] if resource_type: return [self._create_neighbor( - vitrage_id, - timestamp, + entity_event, + entity_event[ZProps.RESOURCE_NAME], resource_type, - entity_event[ZProps.RESOURCE_NAME])] + EdgeLabel.ON, + neighbor_category=EntityCategory.RESOURCE)] return [] @@ -109,9 +108,10 @@ class ZabbixTransformer(AlarmTransformerBase): entity_type = entity_event[DSProps.ENTITY_TYPE] alarm_id = entity_event[ZProps.TRIGGER_ID] resource_name = entity_event[ZProps.RESOURCE_NAME] - return tbase.build_key(self._key_values(entity_type, - resource_name, - alarm_id)) + return tbase.build_key((EntityCategory.ALARM, + entity_type, + resource_name, + alarm_id)) @staticmethod def _unify_time_format(entity_event): diff --git a/vitrage/evaluator/actions/evaluator_event_transformer.py b/vitrage/evaluator/actions/evaluator_event_transformer.py index eec9d3528..e83d62b1e 100644 --- a/vitrage/evaluator/actions/evaluator_event_transformer.py +++ b/vitrage/evaluator/actions/evaluator_event_transformer.py @@ -163,7 +163,7 @@ class EvaluatorEventTransformer(transformer_base.TransformerBase): def _key_values(self, *args): return (EntityCategory.ALARM, VITRAGE_TYPE) + args - def create_placeholder_vertex(self, **kwargs): + def create_neighbor_placeholder_vertex(self, **kwargs): LOG.info('Evaluator does not create placeholders') def get_type(self): diff --git a/vitrage/tests/functional/api_handler/test_apis.py b/vitrage/tests/functional/api_handler/test_apis.py index d783265b9..01fbe9208 100644 --- a/vitrage/tests/functional/api_handler/test_apis.py +++ b/vitrage/tests/functional/api_handler/test_apis.py @@ -137,12 +137,13 @@ class TestApis(TestEntityGraphUnitBase): ctx = {'tenant': 'project_1', 'is_admin': True} # Action - graph_topology = apis.get_topology(ctx, - graph_type='graph', - depth=10, - query=None, - root='RESOURCE:openstack.cluster', - all_tenants=0) + graph_topology = apis.get_topology( + ctx, + graph_type='graph', + depth=10, + query=None, + root='RESOURCE:openstack.cluster:OpenStack Cluster', + all_tenants=0) graph_topology = json.loads(graph_topology) # Test assertions @@ -158,12 +159,13 @@ class TestApis(TestEntityGraphUnitBase): ctx = {'tenant': 'project_2', 'is_admin': False} # Action - graph_topology = apis.get_topology(ctx, - graph_type='graph', - depth=10, - query=None, - root='RESOURCE:openstack.cluster', - all_tenants=0) + graph_topology = apis.get_topology( + ctx, + graph_type='graph', + depth=10, + query=None, + root='RESOURCE:openstack.cluster:OpenStack Cluster', + all_tenants=0) graph_topology = json.loads(graph_topology) # Test assertions @@ -179,12 +181,13 @@ class TestApis(TestEntityGraphUnitBase): ctx = {'tenant': 'project_1', 'is_admin': False} # Action - graph_topology = apis.get_topology(ctx, - graph_type='graph', - depth=10, - query=None, - root='RESOURCE:openstack.cluster', - all_tenants=1) + graph_topology = apis.get_topology( + ctx, + graph_type='graph', + depth=10, + query=None, + root='RESOURCE:openstack.cluster:OpenStack Cluster', + all_tenants=1) graph_topology = json.loads(graph_topology) # Test assertions @@ -209,8 +212,9 @@ class TestApis(TestEntityGraphUnitBase): graph = NXGraph('Multi tenancy graph') # create vertices - cluster_vertex = self._create_resource('RESOURCE:openstack.cluster', - OPENSTACK_CLUSTER) + cluster_vertex = self._create_resource( + 'RESOURCE:openstack.cluster:OpenStack Cluster', + OPENSTACK_CLUSTER) zone_vertex = self._create_resource('zone_1', NOVA_ZONE_DATASOURCE) host_vertex = self._create_resource('host_1', diff --git a/vitrage/tests/unit/datasources/cinder/test_cinder_volume_transformer.py b/vitrage/tests/unit/datasources/cinder/test_cinder_volume_transformer.py index fcd2b91b3..aa6f163c8 100644 --- a/vitrage/tests/unit/datasources/cinder/test_cinder_volume_transformer.py +++ b/vitrage/tests/unit/datasources/cinder/test_cinder_volume_transformer.py @@ -65,12 +65,14 @@ class TestCinderVolumeTransformer(base.BaseTest): properties = { VProps.ID: volume_id, VProps.TYPE: CINDER_VOLUME_DATASOURCE, + VProps.CATEGORY: EntityCategory.RESOURCE, VProps.SAMPLE_TIMESTAMP: timestamp } transformer = self.transformers[CINDER_VOLUME_DATASOURCE] # Test action - placeholder = transformer.create_placeholder_vertex(**properties) + placeholder = \ + transformer.create_neighbor_placeholder_vertex(**properties) # Test assertions observed_id_values = placeholder.vertex_id.split( diff --git a/vitrage/tests/unit/datasources/heat/test_heat_stack_transformer.py b/vitrage/tests/unit/datasources/heat/test_heat_stack_transformer.py index f94e909f4..4d6987ec0 100644 --- a/vitrage/tests/unit/datasources/heat/test_heat_stack_transformer.py +++ b/vitrage/tests/unit/datasources/heat/test_heat_stack_transformer.py @@ -66,12 +66,14 @@ class TestHeatStackTransformer(base.BaseTest): properties = { VProps.ID: stack_id, VProps.TYPE: HEAT_STACK_DATASOURCE, + VProps.CATEGORY: EntityCategory.RESOURCE, VProps.SAMPLE_TIMESTAMP: timestamp } transformer = self.transformers[HEAT_STACK_DATASOURCE] # Test action - placeholder = transformer.create_placeholder_vertex(**properties) + placeholder = \ + transformer.create_neighbor_placeholder_vertex(**properties) # Test assertions observed_id_values = placeholder.vertex_id.split( diff --git a/vitrage/tests/unit/datasources/nova/test_nova_host_transformer.py b/vitrage/tests/unit/datasources/nova/test_nova_host_transformer.py index 4d4cc7e17..07aaa9259 100644 --- a/vitrage/tests/unit/datasources/nova/test_nova_host_transformer.py +++ b/vitrage/tests/unit/datasources/nova/test_nova_host_transformer.py @@ -23,7 +23,7 @@ from vitrage.common.constants import EdgeLabel from vitrage.common.constants import EntityCategory from vitrage.common.constants import GraphAction from vitrage.common.constants import UpdateMethod -from vitrage.common.constants import VertexProperties +from vitrage.common.constants import VertexProperties as VProps from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE from vitrage.datasources.nova.host.transformer import HostTransformer from vitrage.datasources.nova.zone import NOVA_ZONE_DATASOURCE @@ -65,11 +65,13 @@ class NovaHostTransformerTest(base.BaseTest): # Test action properties = { - VertexProperties.ID: host_name, - VertexProperties.TYPE: NOVA_HOST_DATASOURCE, - VertexProperties.SAMPLE_TIMESTAMP: timestamp + VProps.ID: host_name, + VProps.TYPE: NOVA_HOST_DATASOURCE, + VProps.CATEGORY: EntityCategory.RESOURCE, + VProps.SAMPLE_TIMESTAMP: timestamp } - placeholder = host_transformer.create_placeholder_vertex(**properties) + placeholder = \ + host_transformer.create_neighbor_placeholder_vertex(**properties) # Test assertions observed_id_values = placeholder.vertex_id.split( @@ -79,19 +81,19 @@ class NovaHostTransformerTest(base.BaseTest): host_name) self.assertEqual(tuple(observed_id_values), expected_id_values) - observed_time = placeholder.get(VertexProperties.SAMPLE_TIMESTAMP) + observed_time = placeholder.get(VProps.SAMPLE_TIMESTAMP) self.assertEqual(observed_time, timestamp) - observed_subtype = placeholder.get(VertexProperties.TYPE) + observed_subtype = placeholder.get(VProps.TYPE) self.assertEqual(observed_subtype, NOVA_HOST_DATASOURCE) - observed_entity_id = placeholder.get(VertexProperties.ID) + observed_entity_id = placeholder.get(VProps.ID) self.assertEqual(observed_entity_id, host_name) - observed_category = placeholder.get(VertexProperties.CATEGORY) + observed_category = placeholder.get(VProps.CATEGORY) self.assertEqual(observed_category, EntityCategory.RESOURCE) - is_placeholder = placeholder.get(VertexProperties.IS_PLACEHOLDER) + is_placeholder = placeholder.get(VProps.IS_PLACEHOLDER) self.assertEqual(is_placeholder, True) def test_key_values(self): @@ -145,11 +147,13 @@ class NovaHostTransformerTest(base.BaseTest): zt = self.transformers[NOVA_ZONE_DATASOURCE] properties = { - VertexProperties.ID: zone_name, - VertexProperties.TYPE: NOVA_ZONE_DATASOURCE, - VertexProperties.SAMPLE_TIMESTAMP: time + VProps.ID: zone_name, + VProps.TYPE: NOVA_ZONE_DATASOURCE, + VProps.CATEGORY: EntityCategory.RESOURCE, + VProps.SAMPLE_TIMESTAMP: time } - expected_neighbor = zt.create_placeholder_vertex(**properties) + expected_neighbor = \ + zt.create_neighbor_placeholder_vertex(**properties) self.assertEqual(expected_neighbor, zone.vertex) # Validate neighbor edge @@ -166,30 +170,30 @@ class NovaHostTransformerTest(base.BaseTest): extract_value = tbase.extract_field_value expected_id = extract_value(event, '_info', 'host_name') - observed_id = vertex[VertexProperties.ID] + observed_id = vertex[VProps.ID] self.assertEqual(expected_id, observed_id) self.assertEqual( EntityCategory.RESOURCE, - vertex[VertexProperties.CATEGORY] + vertex[VProps.CATEGORY] ) self.assertEqual( NOVA_HOST_DATASOURCE, - vertex[VertexProperties.TYPE] + vertex[VProps.TYPE] ) expected_timestamp = event[DSProps.SAMPLE_DATE] - observed_timestamp = vertex[VertexProperties.SAMPLE_TIMESTAMP] + observed_timestamp = vertex[VProps.SAMPLE_TIMESTAMP] self.assertEqual(expected_timestamp, observed_timestamp) expected_name = extract_value(event, '_info', 'host_name') - observed_name = vertex[VertexProperties.NAME] + observed_name = vertex[VProps.NAME] self.assertEqual(expected_name, observed_name) - is_placeholder = vertex[VertexProperties.IS_PLACEHOLDER] + is_placeholder = vertex[VProps.IS_PLACEHOLDER] self.assertFalse(is_placeholder) - is_deleted = vertex[VertexProperties.IS_DELETED] + is_deleted = vertex[VProps.IS_DELETED] self.assertFalse(is_deleted) def test_extract_event_action(self): diff --git a/vitrage/tests/unit/datasources/nova/test_nova_instance_transformer.py b/vitrage/tests/unit/datasources/nova/test_nova_instance_transformer.py index d01cbcb05..e7276eba5 100644 --- a/vitrage/tests/unit/datasources/nova/test_nova_instance_transformer.py +++ b/vitrage/tests/unit/datasources/nova/test_nova_instance_transformer.py @@ -23,7 +23,7 @@ from vitrage.common.constants import EdgeLabel from vitrage.common.constants import EntityCategory from vitrage.common.constants import GraphAction from vitrage.common.constants import UpdateMethod -from vitrage.common.constants import VertexProperties +from vitrage.common.constants import VertexProperties as VProps from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE from vitrage.datasources.nova.host.transformer import HostTransformer from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE @@ -62,14 +62,16 @@ class NovaInstanceTransformerTest(base.BaseTest): instance_id = 'Instance123' timestamp = datetime.datetime.utcnow() properties = { - VertexProperties.ID: instance_id, - VertexProperties.TYPE: NOVA_INSTANCE_DATASOURCE, - VertexProperties.SAMPLE_TIMESTAMP: timestamp + VProps.ID: instance_id, + VProps.TYPE: NOVA_INSTANCE_DATASOURCE, + VProps.CATEGORY: EntityCategory.RESOURCE, + VProps.SAMPLE_TIMESTAMP: timestamp } transformer = self.transformers[NOVA_INSTANCE_DATASOURCE] # Test action - placeholder = transformer.create_placeholder_vertex(**properties) + placeholder = \ + transformer.create_neighbor_placeholder_vertex(**properties) # Test assertions observed_id_values = placeholder.vertex_id.split( @@ -78,19 +80,19 @@ class NovaInstanceTransformerTest(base.BaseTest): instance_id) self.assertEqual(tuple(observed_id_values), expected_id_values) - observed_time = placeholder.get(VertexProperties.SAMPLE_TIMESTAMP) + observed_time = placeholder.get(VProps.SAMPLE_TIMESTAMP) self.assertEqual(observed_time, timestamp) - observed_type = placeholder.get(VertexProperties.TYPE) + observed_type = placeholder.get(VProps.TYPE) self.assertEqual(observed_type, NOVA_INSTANCE_DATASOURCE) - observed_entity_id = placeholder.get(VertexProperties.ID) + observed_entity_id = placeholder.get(VProps.ID) self.assertEqual(observed_entity_id, instance_id) - observed_category = placeholder.get(VertexProperties.CATEGORY) + observed_category = placeholder.get(VProps.CATEGORY) self.assertEqual(observed_category, EntityCategory.RESOURCE) - is_placeholder = placeholder.get(VertexProperties.IS_PLACEHOLDER) + is_placeholder = placeholder.get(VProps.IS_PLACEHOLDER) self.assertEqual(is_placeholder, True) def test_snapshot_event_transform(self): @@ -165,38 +167,38 @@ class NovaInstanceTransformerTest(base.BaseTest): instance_id = 'instance_id' if is_update_event else 'id' expected_id = extract_value(event, instance_id) - observed_id = vertex[VertexProperties.ID] + observed_id = vertex[VProps.ID] self.assertEqual(expected_id, observed_id) self.assertEqual( EntityCategory.RESOURCE, - vertex[VertexProperties.CATEGORY] + vertex[VProps.CATEGORY] ) self.assertEqual(NOVA_INSTANCE_DATASOURCE, - vertex[VertexProperties.TYPE]) + vertex[VProps.TYPE]) expected_project = extract_value(event, 'tenant_id') - observed_project = vertex[VertexProperties.PROJECT_ID] + observed_project = vertex[VProps.PROJECT_ID] self.assertEqual(expected_project, observed_project) state = 'state' if is_update_event else 'status' expected_state = extract_value(event, state) - observed_state = vertex[VertexProperties.STATE] + observed_state = vertex[VProps.STATE] self.assertEqual(expected_state, observed_state) expected_timestamp = event[DSProps.SAMPLE_DATE] - observed_timestamp = vertex[VertexProperties.SAMPLE_TIMESTAMP] + observed_timestamp = vertex[VProps.SAMPLE_TIMESTAMP] self.assertEqual(expected_timestamp, observed_timestamp) name = 'hostname' if is_update_event else 'name' expected_name = extract_value(event, name) - observed_name = vertex[VertexProperties.NAME] + observed_name = vertex[VProps.NAME] self.assertEqual(expected_name, observed_name) - is_placeholder = vertex[VertexProperties.IS_PLACEHOLDER] + is_placeholder = vertex[VProps.IS_PLACEHOLDER] self.assertFalse(is_placeholder) - is_deleted = vertex[VertexProperties.IS_DELETED] + is_deleted = vertex[VProps.IS_DELETED] self.assertFalse(is_deleted) def _validate_host_neighbor(self, h_neighbor, event): @@ -210,11 +212,13 @@ class NovaInstanceTransformerTest(base.BaseTest): ht = self.transformers[NOVA_HOST_DATASOURCE] properties = { - VertexProperties.ID: host_name, - VertexProperties.TYPE: NOVA_HOST_DATASOURCE, - VertexProperties.SAMPLE_TIMESTAMP: time + VProps.ID: host_name, + VProps.TYPE: NOVA_HOST_DATASOURCE, + VProps.CATEGORY: EntityCategory.RESOURCE, + VProps.SAMPLE_TIMESTAMP: time } - expected_neighbor = ht.create_placeholder_vertex(**properties) + expected_neighbor = \ + ht.create_neighbor_placeholder_vertex(**properties) self.assertEqual(expected_neighbor, h_neighbor.vertex) # Validate neighbor edge @@ -282,25 +286,33 @@ class NovaInstanceTransformerTest(base.BaseTest): LOG.debug('Test create host neighbor') # Test setup - vertex_id = 'RESOURCE:nova.instance:456' host_name = 'host123' + vertex_id = 'RESOURCE:nova.instance:instance321' time = datetime.datetime.utcnow() + entity_event = { + '_info': { + 'host_name': host_name + }, + DSProps.DATASOURCE_ACTION: 'SNAPSHOT', + 'id': 'instance321', + 'vitrage_sample_date': time + } # Test action instance_transformer = self.transformers[NOVA_INSTANCE_DATASOURCE] - neighbor = instance_transformer._create_host_neighbor( - vertex_id, - host_name, - time, - self.transformers[NOVA_HOST_DATASOURCE] - ) + neighbor = \ + instance_transformer._create_neighbor(entity_event, + host_name, + NOVA_HOST_DATASOURCE, + EdgeLabel.CONTAINS, + is_entity_source=False) # Test assertions host_vertex_id = 'RESOURCE:nova.host:host123' self.assertEqual(host_vertex_id, neighbor.vertex.vertex_id) self.assertEqual( time, - neighbor.vertex.get(VertexProperties.SAMPLE_TIMESTAMP) + neighbor.vertex.get(VProps.SAMPLE_TIMESTAMP) ) # test relation edge diff --git a/vitrage/tests/unit/datasources/nova/test_nova_zone_transformer.py b/vitrage/tests/unit/datasources/nova/test_nova_zone_transformer.py index fdbcab6e1..0c2538b9e 100644 --- a/vitrage/tests/unit/datasources/nova/test_nova_zone_transformer.py +++ b/vitrage/tests/unit/datasources/nova/test_nova_zone_transformer.py @@ -21,13 +21,14 @@ from vitrage.common.constants import DatasourceProperties as DSProps from vitrage.common.constants import EdgeLabel from vitrage.common.constants import EntityCategory from vitrage.common.constants import UpdateMethod -from vitrage.common.constants import VertexProperties +from vitrage.common.constants import VertexProperties as VProps from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE from vitrage.datasources.nova.host.transformer import HostTransformer from vitrage.datasources.nova.zone import NOVA_ZONE_DATASOURCE from vitrage.datasources.nova.zone.transformer import ZoneTransformer from vitrage.datasources import OPENSTACK_CLUSTER from vitrage.datasources import transformer_base as tbase +from vitrage.datasources.transformer_base import CLUSTER_ID from vitrage.datasources.transformer_base import TransformerBase from vitrage.tests import base from vitrage.tests.mocks import mock_driver as mock_sync @@ -65,11 +66,13 @@ class NovaZoneTransformerTest(base.BaseTest): # Test action properties = { - VertexProperties.ID: zone_name, - VertexProperties.TYPE: NOVA_ZONE_DATASOURCE, - VertexProperties.SAMPLE_TIMESTAMP: timestamp + VProps.ID: zone_name, + VProps.TYPE: NOVA_ZONE_DATASOURCE, + VProps.CATEGORY: EntityCategory.RESOURCE, + VProps.SAMPLE_TIMESTAMP: timestamp } - placeholder = zone_transformer.create_placeholder_vertex(**properties) + placeholder = \ + zone_transformer.create_neighbor_placeholder_vertex(**properties) # Test assertions observed_id_values = placeholder.vertex_id.split( @@ -78,19 +81,19 @@ class NovaZoneTransformerTest(base.BaseTest): _key_values(NOVA_ZONE_DATASOURCE, zone_name) self.assertEqual(tuple(observed_id_values), expected_id_values) - observed_time = placeholder.get(VertexProperties.SAMPLE_TIMESTAMP) + observed_time = placeholder.get(VProps.SAMPLE_TIMESTAMP) self.assertEqual(observed_time, timestamp) - observed_subtype = placeholder.get(VertexProperties.TYPE) + observed_subtype = placeholder.get(VProps.TYPE) self.assertEqual(observed_subtype, NOVA_ZONE_DATASOURCE) - observed_entity_id = placeholder.get(VertexProperties.ID) + observed_entity_id = placeholder.get(VProps.ID) self.assertEqual(observed_entity_id, zone_name) - observed_category = placeholder.get(VertexProperties.CATEGORY) + observed_category = placeholder.get(VProps.CATEGORY) self.assertEqual(observed_category, EntityCategory.RESOURCE) - is_placeholder = placeholder.get(VertexProperties.IS_PLACEHOLDER) + is_placeholder = placeholder.get(VProps.IS_PLACEHOLDER) self.assertEqual(is_placeholder, True) def test_key_values(self): @@ -142,7 +145,7 @@ class NovaZoneTransformerTest(base.BaseTest): cluster_neighbors_counter = 0 for neighbor in neighbors: - vertex_type = neighbor.vertex.get(VertexProperties.TYPE) + vertex_type = neighbor.vertex.get(VProps.TYPE) if OPENSTACK_CLUSTER == vertex_type: cluster_neighbors_counter += 1 @@ -165,7 +168,7 @@ class NovaZoneTransformerTest(base.BaseTest): datasource_action): host_vertex = host_neighbor.vertex - host_vertex_id = host_vertex.get(VertexProperties.ID) + host_vertex_id = host_vertex.get(VProps.ID) host_dic = hosts[host_vertex_id] self.assertIsNotNone(hosts[host_vertex_id]) @@ -185,13 +188,13 @@ class NovaZoneTransformerTest(base.BaseTest): expected_host_state = ZoneTransformer.STATE_UNAVAILABLE self.assertEqual( expected_host_state, - host_vertex.get(VertexProperties.STATE) + host_vertex.get(VProps.STATE) ) - is_placeholder = host_vertex[VertexProperties.IS_PLACEHOLDER] + is_placeholder = host_vertex[VProps.IS_PLACEHOLDER] self.assertFalse(is_placeholder) - is_deleted = host_vertex[VertexProperties.IS_DELETED] + is_deleted = host_vertex[VProps.IS_DELETED] self.assertFalse(is_deleted) # Validate neighbor edge @@ -202,8 +205,20 @@ class NovaZoneTransformerTest(base.BaseTest): def _validate_cluster_neighbor(self, cluster_neighbor, zone_vertex_id): - expected_cluster_neighbor = tbase.create_cluster_placeholder_vertex() - self.assertEqual(expected_cluster_neighbor, cluster_neighbor.vertex) + self.assertEqual(cluster_neighbor.vertex[VProps.VITRAGE_ID], + cluster_neighbor.vertex.vertex_id) + self.assertEqual('RESOURCE:openstack.cluster:OpenStack Cluster', + cluster_neighbor.vertex[VProps.VITRAGE_ID]) + self.assertEqual(False, + cluster_neighbor.vertex[VProps.IS_DELETED]) + self.assertEqual(EntityCategory.RESOURCE, + cluster_neighbor.vertex[VProps.CATEGORY]) + self.assertEqual(CLUSTER_ID, + cluster_neighbor.vertex[VProps.ID]) + self.assertEqual(False, + cluster_neighbor.vertex[VProps.IS_PLACEHOLDER]) + self.assertEqual(OPENSTACK_CLUSTER, + cluster_neighbor.vertex[VProps.TYPE]) # Validate neighbor edge edge = cluster_neighbor.edge @@ -218,21 +233,21 @@ class NovaZoneTransformerTest(base.BaseTest): extract_value = tbase.extract_field_value expected_id = extract_value(event, 'zoneName') - observed_id = vertex[VertexProperties.ID] + observed_id = vertex[VProps.ID] self.assertEqual(expected_id, observed_id) self.assertEqual(EntityCategory.RESOURCE, - vertex[VertexProperties.CATEGORY]) + vertex[VProps.CATEGORY]) self.assertEqual(NOVA_ZONE_DATASOURCE, - vertex[VertexProperties.TYPE]) + vertex[VProps.TYPE]) expected_timestamp = event[DSProps.SAMPLE_DATE] - observed_timestamp = vertex[VertexProperties.SAMPLE_TIMESTAMP] + observed_timestamp = vertex[VProps.SAMPLE_TIMESTAMP] self.assertEqual(expected_timestamp, observed_timestamp) expected_name = extract_value(event, 'zoneName') - observed_name = vertex[VertexProperties.NAME] + observed_name = vertex[VProps.NAME] self.assertEqual(expected_name, observed_name) is_zone_available = extract_value(event, 'zoneState', 'available') @@ -242,11 +257,11 @@ class NovaZoneTransformerTest(base.BaseTest): else: expected_state = zone_transform.STATE_UNAVAILABLE - observed_state = vertex[VertexProperties.STATE] + observed_state = vertex[VProps.STATE] self.assertEqual(expected_state, observed_state) - is_placeholder = vertex[VertexProperties.IS_PLACEHOLDER] + is_placeholder = vertex[VProps.IS_PLACEHOLDER] self.assertFalse(is_placeholder) - is_deleted = vertex[VertexProperties.IS_DELETED] + is_deleted = vertex[VProps.IS_DELETED] self.assertFalse(is_deleted) diff --git a/vitrage/tests/unit/datasources/static_physical/test_static_physical_transformer.py b/vitrage/tests/unit/datasources/static_physical/test_static_physical_transformer.py index 6265e521b..734d6e29d 100644 --- a/vitrage/tests/unit/datasources/static_physical/test_static_physical_transformer.py +++ b/vitrage/tests/unit/datasources/static_physical/test_static_physical_transformer.py @@ -67,10 +67,11 @@ class TestStaticPhysicalTransformer(base.BaseTest): properties = { VProps.TYPE: switch_type, VProps.ID: switch_name, + VProps.CATEGORY: EntityCategory.RESOURCE, VProps.SAMPLE_TIMESTAMP: timestamp } - placeholder = static_transformer.create_placeholder_vertex( - **properties) + placeholder = \ + static_transformer.create_neighbor_placeholder_vertex(**properties) # Test assertions observed_id_values = placeholder.vertex_id.split( diff --git a/vitrage/tests/unit/graph/base.py b/vitrage/tests/unit/graph/base.py index 0fcf381c9..84efd23b8 100644 --- a/vitrage/tests/unit/graph/base.py +++ b/vitrage/tests/unit/graph/base.py @@ -30,6 +30,7 @@ from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE from vitrage.datasources import OPENSTACK_CLUSTER from vitrage.datasources.static_physical import SWITCH +from vitrage.datasources.transformer_base import CLUSTER_ID from vitrage.graph import create_graph from vitrage.graph import utils as graph_utils from vitrage.tests import base @@ -50,8 +51,11 @@ ALARM_ON_VM = 'ALARM_ON_VM' ALARM_ON_HOST = 'ALARM_ON_HOST' TEST_ON_HOST = 'TEST_ON_HOST' +cluster_vitrage_id = EntityCategory.RESOURCE + ':' + \ + OPENSTACK_CLUSTER + ':' + \ + CLUSTER_ID v_node = graph_utils.create_vertex( - vitrage_id=EntityCategory.RESOURCE + ':' + OPENSTACK_CLUSTER, + vitrage_id=cluster_vitrage_id, entity_id='111111111111', entity_type=OPENSTACK_CLUSTER, entity_category=RESOURCE) @@ -141,7 +145,8 @@ class GraphTestBase(base.BaseTest): start = time.time() g = create_graph(name, EntityCategory.RESOURCE + ':' + - OPENSTACK_CLUSTER) + OPENSTACK_CLUSTER + ':' + + CLUSTER_ID) g.add_vertex(v_node) g.add_vertex(v_switch) g.add_edge(e_node_to_switch) diff --git a/vitrage_tempest_tests/tests/api/topology/base.py b/vitrage_tempest_tests/tests/api/topology/base.py index 0a3be7623..43e36e506 100644 --- a/vitrage_tempest_tests/tests/api/topology/base.py +++ b/vitrage_tempest_tests/tests/api/topology/base.py @@ -34,7 +34,9 @@ class BaseTopologyTest(BaseApiTest): def _rollback_to_default(self): self._delete_entities() api_graph = self.vitrage_client.topology.get( - limit=4, root='RESOURCE:openstack.cluster', all_tenants=1) + limit=4, + root='RESOURCE:openstack.cluster:OpenStack Cluster', + all_tenants=1) graph = self._create_graph_from_graph_dictionary(api_graph) entities = self._entities_validation_data() num_default_entities = self.num_default_entities + \ diff --git a/vitrage_tempest_tests/tests/api/topology/test_topology.py b/vitrage_tempest_tests/tests/api/topology/test_topology.py index 5af156621..05af137b4 100644 --- a/vitrage_tempest_tests/tests/api/topology/test_topology.py +++ b/vitrage_tempest_tests/tests/api/topology/test_topology.py @@ -259,7 +259,9 @@ class TestTopology(BaseTopologyTest): # Calculate expected results api_graph = self.vitrage_client.topology.get( - limit=2, root='RESOURCE:openstack.cluster', all_tenants=1) + limit=2, + root='RESOURCE:openstack.cluster:OpenStack Cluster', + all_tenants=1) graph = self._create_graph_from_graph_dictionary(api_graph) entities = self._entities_validation_data( host_entities=1, host_edges=1) @@ -288,7 +290,9 @@ class TestTopology(BaseTopologyTest): # Calculate expected results api_graph = self.vitrage_client.topology.get( - limit=3, root='RESOURCE:openstack.cluster', all_tenants=1) + limit=3, + root='RESOURCE:openstack.cluster:OpenStack Cluster', + all_tenants=1) graph = self._create_graph_from_graph_dictionary(api_graph) entities = self._entities_validation_data( host_entities=1, @@ -321,9 +325,10 @@ class TestTopology(BaseTopologyTest): num_volumes=self.NUM_VOLUME) # Calculate expected results - self.vitrage_client.topology.get(limit=2, - root='RESOURCE:openstack.cluster', - all_tenants=1) + self.vitrage_client.topology.get( + limit=2, + root='RESOURCE:openstack.cluster:OpenStack Cluster', + all_tenants=1) except ClientException as e: self.assertEqual(403, e.code) self.assertEqual(