vitrage/vitrage/tests/unit/graph/test_graph_algo.py

1432 lines
62 KiB
Python

# Copyright 2016 - Alcatel-Lucent
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
test_vitrage graph algorithms
----------------------------------
Tests for `vitrage` graph driver algorithms
"""
from testtools import matchers
from vitrage.common.constants import EdgeLabel
from vitrage.common.constants import EdgeProperties as EProps
from vitrage.common.constants import EntityCategory
from vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources.heat.stack import HEAT_STACK_DATASOURCE
from vitrage.datasources.neutron.network import NEUTRON_NETWORK_DATASOURCE
from vitrage.datasources import NOVA_HOST_DATASOURCE
from vitrage.datasources import NOVA_INSTANCE_DATASOURCE
from vitrage.datasources import OPENSTACK_CLUSTER
from vitrage.datasources.transformer_base import CLUSTER_ID
from vitrage.graph.algo_driver.algorithm import Mapping
from vitrage.graph.algo_driver.sub_graph_matching import \
NEG_CONDITION
from vitrage.graph.algo_driver.sub_graph_matching import subgraph_matching
from vitrage.graph.driver.elements import Edge
from vitrage.graph.driver.graph import Direction
from vitrage.graph.driver.networkx_graph import NXGraph
from vitrage.graph import utils as graph_utils
from vitrage.tests.base import IsEmpty
from vitrage.tests.unit.graph.base import ALARM
from vitrage.tests.unit.graph.base import ALARM_ON_HOST
from vitrage.tests.unit.graph.base import ALARM_ON_VM
from vitrage.tests.unit.graph.base import e_node_to_switch
from vitrage.tests.unit.graph.base import ELabel
from vitrage.tests.unit.graph.base import ENTITY_GRAPH_ALARMS_PER_HOST
from vitrage.tests.unit.graph.base import ENTITY_GRAPH_ALARMS_PER_VM
from vitrage.tests.unit.graph.base import ENTITY_GRAPH_HOSTS_PER_CLUSTER
from vitrage.tests.unit.graph.base import ENTITY_GRAPH_TESTS_PER_HOST
from vitrage.tests.unit.graph.base import ENTITY_GRAPH_VMS_PER_HOST
from vitrage.tests.unit.graph.base import GraphTestBase
from vitrage.tests.unit.graph.base import RESOURCE
from vitrage.tests.unit.graph.base import v_node
from vitrage.tests.unit.graph.base import v_switch
ROOT_ID = EntityCategory.RESOURCE + ':' + OPENSTACK_CLUSTER + ':' + CLUSTER_ID
class GraphAlgorithmTest(GraphTestBase):
# noinspection PyPep8Naming
@classmethod
def setUpClass(cls):
super(GraphAlgorithmTest, cls).setUpClass()
cls.vm_id = 10000000
cls.vm_alarm_id = 30000000
cls.vms = []
cls.host_alarm_id = 20000000
cls.host_test_id = 40000000
cls.entity_graph = cls._create_entity_graph(
'entity_graph',
num_of_hosts_per_node=ENTITY_GRAPH_HOSTS_PER_CLUSTER,
num_of_vms_per_host=ENTITY_GRAPH_VMS_PER_HOST,
num_of_alarms_per_host=ENTITY_GRAPH_ALARMS_PER_HOST,
num_of_alarms_per_vm=ENTITY_GRAPH_ALARMS_PER_VM,
num_of_tests_per_host=ENTITY_GRAPH_TESTS_PER_HOST)
def test_graph_query_vertices(self):
ga = self.entity_graph.algo
query = {'==': {VProps.VITRAGE_TYPE: OPENSTACK_CLUSTER}}
subgraph = ga.graph_query_vertices(root_id=ROOT_ID, query_dict=query)
self.assertEqual(
1, # For Cluster
subgraph.num_vertices(), 'num of vertex node')
query = {
'or': [
{'==': {VProps.VITRAGE_TYPE: NOVA_HOST_DATASOURCE}},
{'==': {VProps.VITRAGE_TYPE: OPENSTACK_CLUSTER}}
]
}
subgraph = ga.graph_query_vertices(root_id=ROOT_ID, query_dict=query)
self.assertEqual(
ENTITY_GRAPH_HOSTS_PER_CLUSTER,
subgraph.num_edges(), 'num of edges Host <-- NODE')
query = {
'or': [
{'==': {VProps.VITRAGE_TYPE: NOVA_INSTANCE_DATASOURCE}},
{'==': {VProps.VITRAGE_CATEGORY: ALARM}},
{'==': {VProps.VITRAGE_TYPE: NOVA_HOST_DATASOURCE}},
{'==': {VProps.VITRAGE_TYPE: OPENSTACK_CLUSTER}}
]
}
subgraph = ga.graph_query_vertices(root_id=ROOT_ID, query_dict=query)
self.assertEqual(
ENTITY_GRAPH_HOSTS_PER_CLUSTER +
ENTITY_GRAPH_HOSTS_PER_CLUSTER * ENTITY_GRAPH_ALARMS_PER_HOST +
ENTITY_GRAPH_HOSTS_PER_CLUSTER * ENTITY_GRAPH_VMS_PER_HOST +
ENTITY_GRAPH_HOSTS_PER_CLUSTER * ENTITY_GRAPH_VMS_PER_HOST *
ENTITY_GRAPH_ALARMS_PER_VM,
subgraph.num_edges(), 'num of BOTH edges Host (depth 1)')
# Get first host ID
neighboring_hosts = self.entity_graph.neighbors(
v_node.vertex_id, {VProps.VITRAGE_TYPE: NOVA_HOST_DATASOURCE})
first_host_id = neighboring_hosts.pop().vertex_id
query = {'!=': {'NOTHING': 'IS EVERYTHING'}}
subgraph = ga.graph_query_vertices(
root_id=first_host_id, query_dict=query, depth=1)
self.assertEqual(
1 + # For host
1 + # For Cluster
ENTITY_GRAPH_ALARMS_PER_HOST +
ENTITY_GRAPH_TESTS_PER_HOST +
ENTITY_GRAPH_VMS_PER_HOST,
subgraph.num_edges(), 'num of BOTH edges Host (depth 1)')
query = {
'or': [
{'==': {VProps.VITRAGE_TYPE: 'switch'}},
{'==': {VProps.VITRAGE_TYPE: NOVA_HOST_DATASOURCE}},
]
}
subgraph = ga.graph_query_vertices(
root_id=first_host_id, query_dict=query, depth=1)
self.assertEqual(
1, # For 'switch'
subgraph.num_edges(), 'num of BOTH edges Host (depth 1)')
subgraph = ga.graph_query_vertices(root_id=first_host_id, depth=2)
self.assertEqual(
1 + # Cluster to switch
ENTITY_GRAPH_HOSTS_PER_CLUSTER * 2 +
ENTITY_GRAPH_ALARMS_PER_HOST +
ENTITY_GRAPH_TESTS_PER_HOST +
ENTITY_GRAPH_VMS_PER_HOST +
ENTITY_GRAPH_VMS_PER_HOST * ENTITY_GRAPH_ALARMS_PER_VM,
subgraph.num_edges(), 'num of BOTH edges Host (depth 2)')
subgraph = ga.graph_query_vertices(root_id=first_host_id, depth=3,
direction=Direction.OUT)
self.assertEqual(
1 +
ENTITY_GRAPH_VMS_PER_HOST,
subgraph.num_edges(), 'num of BOTH edges Host (depth 3)')
query = {
'and': [
{'!=': {VProps.VITRAGE_TYPE: ALARM_ON_VM}},
{'!=': {VProps.VITRAGE_TYPE: ALARM_ON_HOST}},
{'!=': {VProps.VITRAGE_CATEGORY: ALARM}}
]
}
subgraph = ga.graph_query_vertices(root_id=ROOT_ID,
query_dict=query,
depth=3)
self.assertEqual(
1 + # Cluster to switch
ENTITY_GRAPH_HOSTS_PER_CLUSTER * 2 +
ENTITY_GRAPH_HOSTS_PER_CLUSTER * ENTITY_GRAPH_TESTS_PER_HOST +
ENTITY_GRAPH_HOSTS_PER_CLUSTER * ENTITY_GRAPH_VMS_PER_HOST,
subgraph.num_edges(), 'num of edges Node (depth 3)')
query = {
'or': [
{'==': {VProps.VITRAGE_TYPE: OPENSTACK_CLUSTER}},
{'==': {VProps.VITRAGE_CATEGORY: ALARM}},
]
}
subgraph = ga.graph_query_vertices(root_id=ROOT_ID,
query_dict=query,
depth=3)
self.assertEqual(0, subgraph.num_edges(),
'num of BOTH edges Node (depth 3)')
self.assertEqual(1, subgraph.num_vertices(),
'num of BOTH vertices Node (depth 3)')
# check the edge_query_dict parameter
query = {'!=': {'NOTHING': 'IS EVERYTHING'}}
edge_query = {'==': {EProps.RELATIONSHIP_TYPE: EdgeLabel.CONTAINS}}
subgraph = ga.graph_query_vertices(root_id=ROOT_ID,
query_dict=query,
depth=5,
edge_query_dict=edge_query)
alarms = subgraph.get_vertices(
vertex_attr_filter={VProps.VITRAGE_CATEGORY: ALARM})
self.assertThat(alarms, IsEmpty(), 'We filtered the ON relationship,'
' so no alarms should exist')
# check that the vitrage_is_deleted=True edges are deleted from the
# graph
hosts_query = {VProps.VITRAGE_CATEGORY: RESOURCE,
VProps.VITRAGE_TYPE: NOVA_HOST_DATASOURCE}
hosts = self.entity_graph.get_vertices(
vertex_attr_filter=hosts_query)
instances_query = {VProps.VITRAGE_CATEGORY: RESOURCE,
VProps.VITRAGE_TYPE: NOVA_INSTANCE_DATASOURCE}
instances = self.entity_graph.get_vertices(
vertex_attr_filter=instances_query)
instance_edges = self.entity_graph.get_edges(instances[0].vertex_id)
for edge in instance_edges:
if NOVA_HOST_DATASOURCE in edge.source_id:
host_instance_edge = edge
host_instance_edge[VProps.VITRAGE_IS_DELETED] = True
self.entity_graph.update_edge(host_instance_edge)
edges_query = {EProps.RELATIONSHIP_TYPE: EdgeLabel.CONTAINS,
VProps.VITRAGE_IS_DELETED: False}
if host_instance_edge.source_id != hosts[0].vertex_id:
new_edge = Edge(hosts[0].vertex_id, instances[0].vertex_id,
EdgeLabel.CONTAINS, properties=edges_query)
self.entity_graph.update_edge(new_edge)
else:
new_edge = Edge(hosts[1].vertex_id, instances[0].vertex_id,
EdgeLabel.CONTAINS, properties=edges_query)
self.entity_graph.update_edge(new_edge)
query = {'!=': {'NOTHING': 'IS EVERYTHING'}}
edge_query = {'==': {EProps.VITRAGE_IS_DELETED: False}}
subgraph = ga.graph_query_vertices(root_id=ROOT_ID,
query_dict=query,
depth=5,
edge_query_dict=edge_query)
self.assertEqual(self.entity_graph.num_edges() - 1,
subgraph.num_edges(),
'We filtered the ON relationship, so no alarms '
'should exist')
# Undo changes made by this test
host_instance_edge[VProps.VITRAGE_IS_DELETED] = False
self.entity_graph.update_edge(host_instance_edge)
self.entity_graph.remove_edge(new_edge)
def test_no_match_graph_query_vertices(self):
query = {'==': {VProps.VITRAGE_TYPE: 'test'}}
subgraph = self.entity_graph.algo.graph_query_vertices(
root_id=ROOT_ID,
query_dict=query)
self.assertEqual(
0,
subgraph.num_vertices(), 'num of vertex node')
def test_template_matching(self):
"""Test the template matching algorithm
Using the entity graph (created above) as a big graph we search
for a sub graph match
"""
ga = self.entity_graph.algo
# Get ids of some of the elements in the entity graph:
vm_alarm = self.entity_graph.get_vertex(
ALARM_ON_VM + str(self.vm_alarm_id - 1))
host_alarm = self.entity_graph.get_vertex(
ALARM_ON_HOST + str(self.host_alarm_id - 1))
# Create a template for template matching
template_graph = NXGraph('template_graph')
t_v_host_alarm = graph_utils.create_vertex(
vitrage_id='1', vitrage_category=ALARM, vitrage_type=ALARM_ON_HOST)
t_v_alarm_fail = graph_utils.create_vertex(
vitrage_id='1', vitrage_category=ALARM, vitrage_type='fail')
t_v_host = graph_utils.create_vertex(
vitrage_id='2',
vitrage_category=RESOURCE,
vitrage_type=NOVA_HOST_DATASOURCE)
t_v_vm = graph_utils.create_vertex(
vitrage_id='3',
vitrage_category=RESOURCE,
vitrage_type=NOVA_INSTANCE_DATASOURCE)
t_v_vm_alarm = graph_utils.create_vertex(
vitrage_id='4', vitrage_category=ALARM, vitrage_type=ALARM_ON_VM)
t_v_switch = graph_utils.create_vertex(
vitrage_id='5', vitrage_category=RESOURCE, vitrage_type='switch')
t_v_node = graph_utils.create_vertex(
vitrage_id='6',
vitrage_category=RESOURCE,
vitrage_type=OPENSTACK_CLUSTER)
t_v_node_not_in_graph = graph_utils.create_vertex(
vitrage_id='7',
vitrage_category=RESOURCE,
vitrage_type=OPENSTACK_CLUSTER + ' not in graph')
e_alarm_on_host = graph_utils.create_edge(
t_v_host_alarm.vertex_id, t_v_host.vertex_id, ELabel.ON)
e_host_contains_vm = graph_utils.create_edge(
t_v_host.vertex_id, t_v_vm.vertex_id, ELabel.CONTAINS)
e_alarm_on_vm = graph_utils.create_edge(
t_v_vm_alarm.vertex_id, t_v_vm.vertex_id, ELabel.ON)
e_host_uses_switch = graph_utils.create_edge(
t_v_host.vertex_id, t_v_switch.vertex_id, 'USES')
e_node_contains_host = graph_utils.create_edge(
t_v_node.vertex_id, t_v_host.vertex_id, ELabel.CONTAINS)
e_node_contains_switch = graph_utils.create_edge(
t_v_node.vertex_id, t_v_switch.vertex_id, ELabel.CONTAINS)
e_node_contains_switch_fail = graph_utils.create_edge(
t_v_node.vertex_id, t_v_switch.vertex_id, ELabel.CONTAINS + 'fail')
e_host_to_node_not_in_graph = graph_utils.create_edge(
t_v_node_not_in_graph.vertex_id, t_v_host.vertex_id, ELabel.ON)
for v in [t_v_host_alarm, t_v_host, t_v_vm, t_v_vm_alarm,
t_v_switch, t_v_switch, t_v_node]:
del(v[VProps.VITRAGE_ID])
template_graph.add_vertex(t_v_alarm_fail)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host_alarm,
host_alarm,
is_vertex=True),
validate=True)
self.assertThat(
mappings,
IsEmpty(),
'Template - Single vertex alarm not in graph '
'Template_root is a specific host alarm ')
template_graph.remove_vertex(t_v_alarm_fail)
template_graph.add_vertex(t_v_host_alarm)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host_alarm,
host_alarm,
is_vertex=True))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Single vertex (host alarm) '
'Template_root is a specific host alarm ')
template_graph.add_vertex(t_v_host)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host_alarm,
host_alarm,
is_vertex=True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two disconnected vertices (host alarm , host)'
'Template_root is a specific host alarm ')
template_graph.add_edge(e_alarm_on_host)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host_alarm,
host_alarm,
is_vertex=True))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Two connected vertices (host alarm -ON-> host)'
' template_root is a specific host alarm ')
host = mappings[0][t_v_host.vertex_id]
host_vertex = self.entity_graph.get_vertex(host.vertex_id)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host,
host_vertex,
is_vertex=True))
self.assertThat(
mappings,
matchers.HasLength(ENTITY_GRAPH_ALARMS_PER_HOST),
'Template - Two connected vertices (host alarm -ON-> host)'
' template_root is a specific host ')
template_graph.add_vertex(t_v_vm)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host_alarm,
host_alarm,
is_vertex=True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two connected vertices and a disconnected vertex'
'(host alarm -ON-> host, instance)'
' template_root is a specific host alarm ')
template_graph.add_vertex(t_v_vm_alarm)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_vm_alarm,
vm_alarm,
is_vertex=True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two connected vertices and two disconnected vertices'
'(host alarm -ON-> host, instance, instance alarm)'
' template_root is a specific instance alarm ')
template_graph.add_edge(e_alarm_on_vm)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_vm_alarm,
vm_alarm,
is_vertex=True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two connected vertices and two more connected vertices'
'(host alarm -ON-> host, instance alarm -ON-> instance)'
' template_root is a specific instance alarm ')
template_graph.add_edge(e_host_contains_vm)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_vm_alarm,
vm_alarm,
is_vertex=True))
self.assertThat(
mappings,
matchers.HasLength(ENTITY_GRAPH_ALARMS_PER_HOST),
'Template - Four connected vertices'
'(host alarm -ON-> host -CONTAINS-> instance <-ON- instance alarm)'
' template_root is a specific instance alarm ')
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host_alarm,
host_alarm,
is_vertex=True))
self.assertThat(
mappings,
matchers.HasLength(ENTITY_GRAPH_VMS_PER_HOST *
ENTITY_GRAPH_ALARMS_PER_VM),
'Template - Four connected vertices'
'(host alarm -ON-> host -CONTAINS-> instance <-ON- instance alarm)'
' template_root is a specific host alarm ')
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host,
host_vertex,
is_vertex=True))
self.assertThat(
mappings,
matchers.HasLength(ENTITY_GRAPH_VMS_PER_HOST *
ENTITY_GRAPH_ALARMS_PER_VM *
ENTITY_GRAPH_ALARMS_PER_HOST),
'Template - Four connected vertices'
'(host alarm -ON-> host -CONTAINS-> instance <-ON- instance alarm)'
' template_root is a specific host ')
template_graph.add_vertex(t_v_switch)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_vm_alarm,
vm_alarm,
is_vertex=True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Four connected vertices and a disconnected vertex'
'(host alarm -ON-> host -CONTAINS-> instance <-ON- instance alarm'
',switch) template_root is an instance alarm ')
template_graph.add_edge(e_host_uses_switch)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_vm_alarm,
vm_alarm,
is_vertex=True))
self.assertThat(
mappings,
matchers.HasLength(ENTITY_GRAPH_ALARMS_PER_HOST),
'Template - Five connected vertices'
'(host alarm -ON-> host -CONTAINS-> instance <-ON- instance alarm'
',host -USES-> switch) template_root '
'is a specific instance alarm ')
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host,
host_vertex,
is_vertex=True))
self.assertThat(
mappings,
matchers.HasLength(ENTITY_GRAPH_VMS_PER_HOST *
ENTITY_GRAPH_ALARMS_PER_VM *
ENTITY_GRAPH_ALARMS_PER_HOST),
'Template - Five connected vertices'
'(host alarm -ON-> host -CONTAINS-> instance <-ON- instance alarm'
',host -USES-> switch) template_root is a specific host ')
mappings = subgraph_matching(self.entity_graph, template_graph, [
Mapping(t_v_switch, v_switch, is_vertex=True),
Mapping(t_v_vm_alarm, vm_alarm, is_vertex=True)],
validate=False)
self.assertThat(
mappings,
matchers.HasLength(ENTITY_GRAPH_ALARMS_PER_HOST),
'Template - Five connected vertices, two mappings given'
'(host alarm -ON-> host -CONTAINS-> instance <-ON- instance alarm'
',host -USES-> switch) 7template_root is a specific host ')
template_graph.add_vertex(t_v_node_not_in_graph)
template_graph.add_edge(e_host_to_node_not_in_graph)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_vm_alarm,
vm_alarm,
is_vertex=True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Five connected vertices and an invalid edge'
'(host alarm -ON-> host -CONTAINS-> instance <-ON- instance alarm'
',host -USES-> switch) template_root is an instance alarm ')
template_graph.remove_vertex(t_v_node_not_in_graph)
template_graph.remove_vertex(t_v_host_alarm)
template_graph.add_vertex(t_v_node)
template_graph.add_edge(e_node_contains_host)
template_graph.add_edge(e_node_contains_switch)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_vm_alarm,
vm_alarm,
is_vertex=True))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - FIVE connected vertices'
'(host -CONTAINS-> instance <-ON- instance alarm'
',node -CONTAINS-> host -USES-> switch, node-CONTAINS->switch)'
' template_root is an instance alarm ')
mappings = subgraph_matching(self.entity_graph, template_graph, [
Mapping(e_node_contains_switch, e_node_to_switch, is_vertex=False),
Mapping(t_v_vm_alarm, vm_alarm, is_vertex=True)])
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - FIVE connected vertices'
'(host -CONTAINS-> instance <-ON- instance alarm'
',node -CONTAINS-> host -USES-> switch, node-CONTAINS->switch)'
' 3 Known Mappings[switch, node, vm alarm] ')
template_graph.add_edge(e_node_contains_switch_fail)
mappings = subgraph_matching(self.entity_graph, template_graph, [
Mapping(t_v_node, v_node, is_vertex=True),
Mapping(t_v_switch, v_switch, is_vertex=True)], validate=True)
self.assertThat(
mappings,
IsEmpty(),
'Template - FIVE connected vertices - 2 Known Mapping[node,switch]'
' Check that ALL edges between the 2 known mappings are checked'
' we now have node-CONTAINS fail->switch AND node-CONTAINS->switch'
' ')
mappings = ga.sub_graph_matching(template_graph,
Mapping(e_node_contains_switch,
e_node_to_switch,
is_vertex=False),
validate=True)
self.assertThat(
mappings,
IsEmpty(),
'Template - FIVE connected vertices - 2 Known Mapping[node,switch]'
' Check that ALL edges between the 2 known mappings are checked'
' we now have node-CONTAINS fail->switch AND node-CONTAINS->switch'
' ')
template_graph.remove_edge(e_node_contains_switch)
mappings = subgraph_matching(self.entity_graph, template_graph, [
Mapping(t_v_node, v_node, is_vertex=True),
Mapping(t_v_switch, v_switch, is_vertex=True)])
self.assertThat(
mappings,
IsEmpty(),
'Template - FIVE connected vertices - 2 Known Mapping[node,switch]'
' But the edge between these 2 is not same as the graph '
'(host -CONTAINS-> instance <-ON- instance alarm'
',node -CONTAINS-> host -USES-> switch, node-CONTAINS '
'fail->switch)'
' ')
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_vm_alarm,
vm_alarm,
is_vertex=True))
self.assertThat(
mappings,
IsEmpty(),
'Template - FIVE connected vertices'
'(host -CONTAINS-> instance <-ON- instance alarm'
',node -CONTAINS-> host -USES-> switch, node-CONTAINS '
'fail->switch)'
' template_root is an instance alarm')
def test_template_matching_with_not_operator_of_complicated_subgraph(self):
"""Test the template matching algorithm with 'not' operator
Using the entity graph (created above) as a big graph we search
for a sub graph matches that has simple 'not' operator in the template
"""
ga = self.entity_graph.algo
# Get ids of some of the elements in the entity graph:
host = self.entity_graph.get_vertex(
NOVA_HOST_DATASOURCE + str(ENTITY_GRAPH_HOSTS_PER_CLUSTER - 1))
# Create a template for template matching
template_graph = NXGraph('template_graph')
t_v_alarm_fail = graph_utils.create_vertex(
vitrage_id='1', vitrage_category=ALARM, vitrage_type='fail')
t_v_host = graph_utils.create_vertex(
vitrage_id='2',
vitrage_category=RESOURCE,
vitrage_type=NOVA_HOST_DATASOURCE)
t_v_vm = graph_utils.create_vertex(
vitrage_id='3',
vitrage_category=RESOURCE,
vitrage_type=NOVA_INSTANCE_DATASOURCE)
t_v_vm_alarm = graph_utils.create_vertex(
vitrage_id='4', vitrage_category=ALARM, vitrage_type=ALARM_ON_VM)
e_host_contains_vm = graph_utils.create_edge(
t_v_host.vertex_id, t_v_vm.vertex_id, ELabel.CONTAINS)
e_alarm_not_on_vm = graph_utils.create_edge(
t_v_vm_alarm.vertex_id, t_v_vm.vertex_id, ELabel.ON)
e_alarm_not_on_vm[NEG_CONDITION] = True
e_alarm_not_on_vm[EProps.VITRAGE_IS_DELETED] = True
e_alarm_not_on_host = graph_utils.create_edge(
t_v_alarm_fail.vertex_id, t_v_host.vertex_id, ELabel.ON)
e_alarm_not_on_host[NEG_CONDITION] = True
e_alarm_not_on_host[EProps.VITRAGE_IS_DELETED] = True
for v in [t_v_alarm_fail, t_v_host, t_v_vm, t_v_vm_alarm]:
del(v[VProps.VITRAGE_ID])
# add host vertex to subgraph
template_graph.add_vertex(t_v_host)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host, host, True),
validate=True)
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Single vertex alarm not in graph '
'Template_root is a specific host ' + str(mappings))
# add vm vertex to subgraph
template_graph.add_vertex(t_v_vm)
template_graph.add_edge(e_host_contains_vm)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host, host, True))
self.assertThat(
mappings, matchers.HasLength(ENTITY_GRAPH_VMS_PER_HOST),
'Template - Two connected vertices (host -> vm)'
' template_root is a specific host ' + str(mappings))
# add not alarm to subgraph
template_graph.add_vertex(t_v_vm_alarm)
template_graph.add_edge(e_alarm_not_on_vm)
mappings = ga.sub_graph_matching(template_graph,
Mapping(t_v_host, host, True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Three connected vertices (host -> vm <- NOT alarm)'
' template_root is a specific host ' + str(mappings))
# create temporary entity graph
temp_entity_graph = self.entity_graph.copy()
temp_ga = temp_entity_graph.algo
vms = temp_entity_graph.neighbors(
host.vertex_id,
vertex_attr_filter={
VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_TYPE: NOVA_INSTANCE_DATASOURCE})
###################################################################
# Use case 1: remove alarms of specific vm
###################################################################
alarms = temp_entity_graph.neighbors(
vms[0].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
for alarm in alarms:
temp_entity_graph.remove_vertex(alarm)
mappings = temp_ga.sub_graph_matching(template_graph,
Mapping(t_v_host, host, True))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Three connected vertices (host -> vm <- NOT alarm)'
'Template_root is a specific host ' + str(mappings))
# add another not alarm to subgraph
template_graph.add_vertex(t_v_alarm_fail)
template_graph.add_edge(e_alarm_not_on_host)
mappings = temp_ga.sub_graph_matching(template_graph,
Mapping(t_v_host, host, True))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Four connected vertices '
'(NOT alarm -> host -> vm <- NOT alarm)'
' template_root is a specific host alarm ' + str(mappings))
###################################################################
# Use case 2: mark alarms and their edges as deleted
###################################################################
vms = temp_entity_graph.neighbors(
host.vertex_id,
vertex_attr_filter={
VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_TYPE: NOVA_INSTANCE_DATASOURCE})
alarms = temp_entity_graph.neighbors(
vms[1].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
for alarm in alarms:
alarm[VProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_vertex(alarm)
edges = temp_entity_graph.get_edges(alarm.vertex_id)
for edge in edges:
edge[EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(edge)
mappings = temp_ga.sub_graph_matching(template_graph,
Mapping(t_v_host, host, True))
self.assertThat(
mappings,
matchers.HasLength(2),
'Template - Three connected vertices (host -> vm <- NOT alarm)'
'Template_root is a specific host ' + str(mappings))
###################################################################
# Use case 3: mark alarm edges as deleted with event on the host
###################################################################
alarms = temp_entity_graph.neighbors(
vms[2].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
for alarm in alarms:
edges = temp_entity_graph.get_edges(alarm.vertex_id)
for edge in edges:
edge[EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(edge)
mappings = temp_ga.sub_graph_matching(template_graph,
Mapping(t_v_host, host, True))
self.assertThat(
mappings,
matchers.HasLength(3),
'Template - Three connected vertices (host -> vm <- NOT alarm)'
'Template_root is a specific host ' + str(mappings))
###################################################################
# Use case 4: event arrived on deleted alarm vertex on vm, that
# has other alarms on it
###################################################################
alarms = temp_entity_graph.neighbors(
vms[3].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
deleted_vertex = alarms[0]
deleted_vertex[VProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_vertex(deleted_vertex)
mappings = temp_ga.sub_graph_matching(template_graph,
Mapping(t_v_vm_alarm,
deleted_vertex,
True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Four connected vertices '
'(NOT alarm -> host -> vm <- NOT alarm)'
' template_root is a specific host ' + str(mappings))
###################################################################
# Use case 5: event arrived on deleted alarm edge on vm, that has
# other alarms on it
###################################################################
alarms = temp_entity_graph.neighbors(
vms[4].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
edges = list(temp_entity_graph.get_edges(alarms[0].vertex_id))
deleted_edge = edges[0]
deleted_edge[EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(deleted_edge)
mappings = temp_ga.sub_graph_matching(template_graph,
Mapping(e_alarm_not_on_vm,
deleted_edge,
False))
self.assertThat(
mappings,
IsEmpty(),
'Template - Four connected vertices '
'(NOT alarm -> host -> vm <- NOT alarm)'
' template_root is a specific host ' + str(mappings))
###################################################################
# Use case 6: event arrived on deleted alarm edge on vm, that has
# other vitrage_is_deleted alarms on it
###################################################################
alarms = temp_entity_graph.neighbors(
vms[5].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
for alarm in alarms:
edges = temp_entity_graph.get_edges(alarm.vertex_id)
for edge in edges:
edge[EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(edge)
deleted_edge = \
list(temp_entity_graph.get_edges(alarms[0].vertex_id))[0]
mappings = temp_ga.sub_graph_matching(template_graph,
Mapping(e_alarm_not_on_vm,
deleted_edge,
False))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Four connected vertices '
'(NOT alarm -> host -> vm <- NOT alarm)'
' template_root is a specific host ' + str(mappings))
def test_template_matching_with_not_operator_of_simple_subgraph(self):
"""Test the template matching algorithm with 'not' operator
Using the entity graph (created above) as a big graph we search
for a sub graph matches that has simple 'not' operator in the template
"""
# Get ids of some of the elements in the entity graph:
graph_host = self.entity_graph.get_vertex(
NOVA_HOST_DATASOURCE + str(ENTITY_GRAPH_HOSTS_PER_CLUSTER - 1))
# Create a template for template matching
template_graph = NXGraph('template_graph')
t_v_vm = graph_utils.create_vertex(
vitrage_id='1',
vitrage_category=RESOURCE,
vitrage_type=NOVA_INSTANCE_DATASOURCE)
t_v_vm_alarm = graph_utils.create_vertex(
vitrage_id='2', vitrage_category=ALARM, vitrage_type=ALARM_ON_VM)
e_alarm_not_on_vm = graph_utils.create_edge(
t_v_vm_alarm.vertex_id, t_v_vm.vertex_id, ELabel.ON)
e_alarm_not_on_vm[NEG_CONDITION] = True
e_alarm_not_on_vm[EProps.VITRAGE_IS_DELETED] = True
for v in [t_v_vm, t_v_vm_alarm]:
del(v[VProps.VITRAGE_ID])
# add instance vertex to subgraph
template_graph.add_vertex(t_v_vm)
# add not alarm on vm vertex to subgraph
template_graph.add_vertex(t_v_vm_alarm)
template_graph.add_edge(e_alarm_not_on_vm)
# create copy of the entity graph
temp_entity_graph = self.entity_graph.copy()
temp_ga = temp_entity_graph.algo
vms = temp_entity_graph.neighbors(
graph_host.vertex_id,
vertex_attr_filter={
VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_TYPE: NOVA_INSTANCE_DATASOURCE})
###################################################################
# Use case 1: find subgraphs (when edges are deleted) with event on
# the edge
###################################################################
alarms = temp_entity_graph.neighbors(
vms[0].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
for alarm in alarms:
edges = temp_entity_graph.get_edges(alarm.vertex_id)
for edge in edges:
edge[EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(edge)
graph_alarm_edge = \
list(temp_entity_graph.get_edges(alarms[0].vertex_id))[0]
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Two not connected vertices (vm <- alarm)')
# find subgraphs (when edges are deleted) with event on the alarm
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_vm_alarm, alarms[0], True))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Two not connected vertices (vm <- alarm)')
###################################################################
# Use case 2: find subgraphs (when vertices are deleted) with event
# on the edge
###################################################################
alarms = temp_entity_graph.neighbors(
vms[1].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
for alarm in alarms:
alarm[VProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_vertex(alarm)
graph_alarm_edge = \
list(temp_entity_graph.get_edges(alarms[0].vertex_id))[0]
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Two not connected vertices (vm <- alarm)')
# find subgraphs (when vertices are deleted) with event on the alarm
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_vm_alarm, alarms[0], True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
###################################################################
# Use case 3: find subgraphs (when vertices and edges are deleted)
# with event on the edge
###################################################################
alarms = temp_entity_graph.neighbors(
vms[2].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
for alarm in alarms:
alarm[VProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_vertex(alarm)
edges = temp_entity_graph.get_edges(alarm.vertex_id)
for edge in edges:
edge[EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(edge)
graph_alarm_edge = \
list(temp_entity_graph.get_edges(alarms[0].vertex_id))[0]
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Two not connected vertices (vm <- alarm)')
# find subgraphs (when vertices and edges are deleted) with event
# on the alarm
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_vm_alarm, alarms[0], True))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Two not connected vertices (vm <- alarm)')
###################################################################
# Use case 4: find subgraphs (when one alarm of many is deleted)
# with event on the edge
###################################################################
alarms = temp_entity_graph.neighbors(
vms[3].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
graph_alarm = alarms[0]
graph_alarm[VProps.VITRAGE_IS_DELETED] = True
graph_alarm_edge = \
list(temp_entity_graph.get_edges(alarms[0].vertex_id))[0]
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
# find subgraphs (when one alarm of many is deleted) with event
# on the alarm
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_vm_alarm, alarms[0], True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
###################################################################
# Use case 5: find subgraphs (when one edge of alarm of many is
# deleted) with event on the edge
###################################################################
alarms = temp_entity_graph.neighbors(
vms[4].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
graph_alarm_edge = \
list(temp_entity_graph.get_edges(alarms[0].vertex_id))[0]
graph_alarm_edge[EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(graph_alarm_edge)
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
###################################################################
# Use case 6: find subgraphs (when one alarm its edge are deleted
# from many alarms) with event on the edge
###################################################################
alarms = temp_entity_graph.neighbors(
vms[5].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
alarms[0][VProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_vertex(alarms[0])
graph_alarm_edge = \
list(temp_entity_graph.get_edges(alarms[0].vertex_id))[0]
graph_alarm_edge[EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(graph_alarm_edge)
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
def test_template_matching_with_not_operator_of_problematic_subgraph(self):
"""Test the template matching algorithm with 'not' operator
Checking the following use case:
network -> vm <--- alarm -> stack -> network
"""
# Get ids of some of the elements in the entity graph:
graph_host = self.entity_graph.get_vertex(
NOVA_HOST_DATASOURCE + str(ENTITY_GRAPH_HOSTS_PER_CLUSTER - 1))
# Create a template for template matching
template_graph = NXGraph('template_graph')
t_v_network = graph_utils.create_vertex(
vitrage_id='1',
vitrage_category=RESOURCE,
vitrage_type=NEUTRON_NETWORK_DATASOURCE)
t_v_vm = graph_utils.create_vertex(
vitrage_id='2',
vitrage_category=RESOURCE,
vitrage_type=NOVA_INSTANCE_DATASOURCE)
t_v_alarm = graph_utils.create_vertex(
vitrage_id='3', vitrage_category=ALARM, vitrage_type=ALARM_ON_VM)
t_v_stack = graph_utils.create_vertex(
vitrage_id='4',
vitrage_category=RESOURCE,
vitrage_type=HEAT_STACK_DATASOURCE)
e_network_connect_vm = graph_utils.create_edge(
t_v_network.vertex_id, t_v_vm.vertex_id, ELabel.CONNECT)
e_alarm_not_on_vm = graph_utils.create_edge(
t_v_alarm.vertex_id, t_v_vm.vertex_id, ELabel.ON)
e_alarm_not_on_vm[NEG_CONDITION] = True
e_alarm_not_on_vm[EProps.VITRAGE_IS_DELETED] = True
e_alarm_on_stack = graph_utils.create_edge(
t_v_alarm.vertex_id, t_v_stack.vertex_id, ELabel.ON)
e_stack_connect_network = graph_utils.create_edge(
t_v_network.vertex_id, t_v_stack.vertex_id, ELabel.CONNECT)
for v in [t_v_vm, t_v_alarm, t_v_network, t_v_stack]:
del(v[VProps.VITRAGE_ID])
# add network vertex to subgraph
template_graph.add_vertex(t_v_network)
# add vm vertex and connect it to host
template_graph.add_vertex(t_v_vm)
template_graph.add_edge(e_network_connect_vm)
# add not alarm and connect it to vm
template_graph.add_vertex(t_v_alarm)
template_graph.add_edge(e_alarm_not_on_vm)
# add stack vertex and connect it to alarm
template_graph.add_vertex(t_v_stack)
template_graph.add_edge(e_alarm_on_stack)
# connect stack to network
template_graph.add_edge(e_stack_connect_network)
# create copy of the entity graph
temp_entity_graph = self.entity_graph.copy()
temp_ga = temp_entity_graph.algo
vms = temp_entity_graph.neighbors(
graph_host.vertex_id,
vertex_attr_filter={
VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_TYPE: NOVA_INSTANCE_DATASOURCE})
###################################################################
# Use case 1: alarm connected to vm
###################################################################
alarms = temp_entity_graph.neighbors(
vms[0].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
# Action
for alarm in alarms[1:len(alarms)]:
alarm[VProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_vertex(alarm)
edges = temp_entity_graph.get_edges(alarm.vertex_id)
for edge in edges:
edge[EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(edge)
# build problematic subgraph in entity graph
specific_alarm = alarms[0]
self._build_problematic_subgraph_in_entity_graph(specific_alarm,
vms[0],
temp_entity_graph,
0)
# trigger on edge between vm and alarm
graph_alarm_edges = \
temp_entity_graph.get_edges(specific_alarm.vertex_id)
for edge in graph_alarm_edges:
if 'instance' in edge.target_id:
graph_alarm_edge = edge
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
# trigger on alarm
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_alarm, specific_alarm, True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
###################################################################
# Use case 2: alarm not connected to vm (with edge
# vitrage_is_deleted=True)
###################################################################
alarms = temp_entity_graph.neighbors(
vms[1].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
# Action
for alarm in alarms:
edges = temp_entity_graph.get_edges(alarm.vertex_id)
for edge in edges:
edge[EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(edge)
# build problematic subgraph in entity graph
specific_alarm = alarms[0]
self._build_problematic_subgraph_in_entity_graph(specific_alarm,
vms[1],
temp_entity_graph,
1)
# trigger on edge between vm and alarm
graph_alarm_edges = \
temp_entity_graph.get_edges(specific_alarm.vertex_id)
for edge in graph_alarm_edges:
if 'instance' in edge.target_id:
graph_alarm_edge = edge
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Two not connected vertices (vm <- alarm)')
# trigger on alarm
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_alarm, specific_alarm, True))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Two not connected vertices (vm <- alarm)')
###################################################################
# Use case 3: alarm not connected to vm (without any edge)
###################################################################
alarms = temp_entity_graph.neighbors(
vms[2].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
# Action
for alarm in alarms:
edges = temp_entity_graph.get_edges(alarm.vertex_id)
for edge in edges:
temp_entity_graph.remove_edge(edge)
# build problematic subgraph in entity graph
specific_alarm = alarms[0]
self._build_problematic_subgraph_in_entity_graph(specific_alarm,
vms[2],
temp_entity_graph,
2)
# trigger on edge between vm and alarm
graph_alarm_edges = \
temp_entity_graph.get_edges(specific_alarm.vertex_id)
for edge in graph_alarm_edges:
if 'instance' in edge.target_id:
graph_alarm_edge = edge
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Two not connected vertices (vm <- alarm)')
# trigger on alarm
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_alarm, specific_alarm, True))
self.assertThat(
mappings,
matchers.HasLength(1),
'Template - Two not connected vertices (vm <- alarm)')
###################################################################
# Use case 4: alarm not connected to vm (with edge
# vitrage_is_deleted=True) and other connected alarms exist
###################################################################
alarms = temp_entity_graph.neighbors(
vms[3].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
# Action
edges = [e for e in temp_entity_graph.get_edges(alarms[0].vertex_id)]
edges[0][EProps.VITRAGE_IS_DELETED] = True
temp_entity_graph.update_edge(edge)
# build problematic subgraph in entity graph
for alarm in alarms:
self._build_problematic_subgraph_in_entity_graph(alarm,
vms[3],
temp_entity_graph,
3)
# trigger on edge (that was deleted) between vm and alarm
specific_alarm = alarms[0]
graph_alarm_edges = \
temp_entity_graph.get_edges(specific_alarm.vertex_id)
for edge in graph_alarm_edges:
if 'instance' in edge.target_id:
graph_alarm_edge = edge
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
# trigger on edge (that wasn't deleted) between vm and alarm
specific_alarm = alarms[1]
graph_alarm_edges = \
temp_entity_graph.get_edges(specific_alarm.vertex_id)
for edge in graph_alarm_edges:
if 'instance' in edge.target_id:
graph_alarm_edge = edge
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
# trigger on alarm
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_alarm, specific_alarm, True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
# trigger on instance
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_vm, vms[3], True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
###################################################################
# Use case 5: alarm not connected to vm (without any edge) and
# other connected alarms exist
###################################################################
alarms = temp_entity_graph.neighbors(
vms[4].vertex_id,
vertex_attr_filter={VProps.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_TYPE: ALARM_ON_VM})
# Action
edges = [e for e in temp_entity_graph.get_edges(alarms[0].vertex_id)]
temp_entity_graph.remove_edge(edges[0])
# build problematic subgraph in entity graph
for alarm in alarms:
self._build_problematic_subgraph_in_entity_graph(alarm,
vms[4],
temp_entity_graph,
4)
# trigger on edge (that was deleted) between vm and alarm
specific_alarm = alarms[0]
graph_alarm_edges = \
temp_entity_graph.get_edges(specific_alarm.vertex_id)
for edge in graph_alarm_edges:
if 'instance' in edge.target_id:
graph_alarm_edge = edge
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
# trigger on edge (that wasn't deleted) between vm and alarm
specific_alarm = alarms[1]
graph_alarm_edges = \
temp_entity_graph.get_edges(specific_alarm.vertex_id)
for edge in graph_alarm_edges:
if 'instance' in edge.target_id:
graph_alarm_edge = edge
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(e_alarm_not_on_vm, graph_alarm_edge, False))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
# trigger on alarm
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_alarm, specific_alarm, True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
# trigger on instance
mappings = temp_ga.sub_graph_matching(
template_graph,
Mapping(t_v_vm, vms[4], True))
self.assertThat(
mappings,
IsEmpty(),
'Template - Two not connected vertices (vm <- alarm)')
@staticmethod
def _build_problematic_subgraph_in_entity_graph(alarm,
vm,
temp_entity_graph,
num):
stack_vertex = graph_utils.create_vertex(
vitrage_id='stack' + str(num),
vitrage_category=RESOURCE,
vitrage_type=HEAT_STACK_DATASOURCE)
temp_entity_graph.update_vertex(stack_vertex)
alarm_stack_edge = graph_utils.create_edge(
alarm.vertex_id, stack_vertex.vertex_id, ELabel.ON)
temp_entity_graph.update_edge(alarm_stack_edge)
network_vertex = graph_utils.create_vertex(
vitrage_id='network' + str(num),
vitrage_category=RESOURCE,
vitrage_type=NEUTRON_NETWORK_DATASOURCE)
temp_entity_graph.update_vertex(network_vertex)
network_stack_edge = graph_utils.create_edge(
network_vertex.vertex_id, stack_vertex.vertex_id, ELabel.CONNECT)
temp_entity_graph.update_edge(network_stack_edge)
network_vm_edge = graph_utils.create_edge(
network_vertex.vertex_id, vm.vertex_id, ELabel.CONNECT)
temp_entity_graph.update_edge(network_vm_edge)