Allow interchangeable graph class for the entity graph.
Graph driver class is a configurable entry point using stevedore, can be changed in entry_points.txt and vitrage.conf. NetworkX graph - classes encapsulation, can now easily be replaced Change-Id: I7390d2f692886c0e2c67159b63486e2956046bfd
This commit is contained in:
parent
9d7457dddb
commit
312617d636
@ -29,6 +29,9 @@ console_scripts =
|
|||||||
vitrage-graph = vitrage.cmd.graph:main
|
vitrage-graph = vitrage.cmd.graph:main
|
||||||
vitrage-notifier = vitrage.cmd.notifier:main
|
vitrage-notifier = vitrage.cmd.notifier:main
|
||||||
|
|
||||||
|
vitrage.entity_graph =
|
||||||
|
networkx = vitrage.graph.driver.networkx_graph:NXGraph
|
||||||
|
|
||||||
oslo.config.opts =
|
oslo.config.opts =
|
||||||
vitrage = vitrage.opts:list_opts
|
vitrage = vitrage.opts:list_opts
|
||||||
datasources = vitrage.opts:datasources_opts
|
datasources = vitrage.opts:datasources_opts
|
||||||
|
@ -18,7 +18,6 @@ from vitrage.api_handler.apis.base import ALARMS_ALL_QUERY
|
|||||||
from vitrage.api_handler.apis.base import EDGE_QUERY
|
from vitrage.api_handler.apis.base import EDGE_QUERY
|
||||||
from vitrage.api_handler.apis.base import EntityGraphApisBase
|
from vitrage.api_handler.apis.base import EntityGraphApisBase
|
||||||
from vitrage.api_handler.apis.base import RCA_QUERY
|
from vitrage.api_handler.apis.base import RCA_QUERY
|
||||||
from vitrage.graph import create_algorithm
|
|
||||||
from vitrage.graph import Direction
|
from vitrage.graph import Direction
|
||||||
|
|
||||||
|
|
||||||
@ -37,7 +36,7 @@ class RcaApis(EntityGraphApisBase):
|
|||||||
|
|
||||||
project_id = ctx.get(self.TENANT_PROPERTY, None)
|
project_id = ctx.get(self.TENANT_PROPERTY, None)
|
||||||
is_admin_project = ctx.get(self.IS_ADMIN_PROJECT_PROPERTY, False)
|
is_admin_project = ctx.get(self.IS_ADMIN_PROJECT_PROPERTY, False)
|
||||||
ga = create_algorithm(self.entity_graph)
|
ga = self.entity_graph.algo
|
||||||
|
|
||||||
found_graph_out = ga.graph_query_vertices(query_dict=RCA_QUERY,
|
found_graph_out = ga.graph_query_vertices(query_dict=RCA_QUERY,
|
||||||
root_id=root,
|
root_id=root,
|
||||||
|
@ -24,7 +24,6 @@ from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE
|
|||||||
from vitrage.datasources import OPENSTACK_CLUSTER
|
from vitrage.datasources import OPENSTACK_CLUSTER
|
||||||
from vitrage.datasources.transformer_base import build_key
|
from vitrage.datasources.transformer_base import build_key
|
||||||
from vitrage.datasources.transformer_base import CLUSTER_ID
|
from vitrage.datasources.transformer_base import CLUSTER_ID
|
||||||
from vitrage.graph import create_algorithm
|
|
||||||
|
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
@ -42,7 +41,7 @@ class TopologyApis(EntityGraphApisBase):
|
|||||||
|
|
||||||
project_id = ctx.get(self.TENANT_PROPERTY, None)
|
project_id = ctx.get(self.TENANT_PROPERTY, None)
|
||||||
is_admin_project = ctx.get(self.IS_ADMIN_PROJECT_PROPERTY, False)
|
is_admin_project = ctx.get(self.IS_ADMIN_PROJECT_PROPERTY, False)
|
||||||
ga = create_algorithm(self.entity_graph)
|
ga = self.entity_graph.algo
|
||||||
|
|
||||||
if graph_type == 'tree':
|
if graph_type == 'tree':
|
||||||
if not query:
|
if not query:
|
||||||
|
@ -24,12 +24,12 @@ from vitrage.common.constants import EntityCategory
|
|||||||
from vitrage.datasources import launcher as datasource_launcher
|
from vitrage.datasources import launcher as datasource_launcher
|
||||||
from vitrage.datasources import OPENSTACK_CLUSTER
|
from vitrage.datasources import OPENSTACK_CLUSTER
|
||||||
from vitrage.datasources.transformer_base import CLUSTER_ID
|
from vitrage.datasources.transformer_base import CLUSTER_ID
|
||||||
|
from vitrage import entity_graph
|
||||||
from vitrage.entity_graph.consistency import service as consistency_svc
|
from vitrage.entity_graph.consistency import service as consistency_svc
|
||||||
from vitrage.entity_graph.initialization_status import InitializationStatus
|
from vitrage.entity_graph.initialization_status import InitializationStatus
|
||||||
from vitrage.entity_graph import service as entity_graph_svc
|
from vitrage.entity_graph import service as entity_graph_svc
|
||||||
from vitrage.evaluator.scenario_evaluator import ScenarioEvaluator
|
from vitrage.evaluator.scenario_evaluator import ScenarioEvaluator
|
||||||
from vitrage.evaluator.scenario_repository import ScenarioRepository
|
from vitrage.evaluator.scenario_repository import ScenarioRepository
|
||||||
from vitrage.graph import create_graph
|
|
||||||
from vitrage import service
|
from vitrage import service
|
||||||
|
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ def main():
|
|||||||
def init(conf):
|
def init(conf):
|
||||||
mp_queue = multiprocessing.Queue()
|
mp_queue = multiprocessing.Queue()
|
||||||
evaluator_q = queue.Queue()
|
evaluator_q = queue.Queue()
|
||||||
e_graph = create_graph(
|
e_graph = entity_graph.get_graph_driver(conf)(
|
||||||
'Entity Graph',
|
'Entity Graph',
|
||||||
'%s:%s:%s' % (EntityCategory.RESOURCE, OPENSTACK_CLUSTER, CLUSTER_ID))
|
'%s:%s:%s' % (EntityCategory.RESOURCE, OPENSTACK_CLUSTER, CLUSTER_ID))
|
||||||
scenario_repo = ScenarioRepository(conf)
|
scenario_repo = ScenarioRepository(conf)
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
import cProfile
|
||||||
|
|
||||||
|
|
||||||
def recursive_keypairs(d, separator='.'):
|
def recursive_keypairs(d, separator='.'):
|
||||||
# taken from ceilometer and gnocchi
|
# taken from ceilometer and gnocchi
|
||||||
@ -35,3 +37,16 @@ def opt_exists(conf_parent, opt):
|
|||||||
return conf_parent[opt]
|
return conf_parent[opt]
|
||||||
except cfg.NoSuchOptError:
|
except cfg.NoSuchOptError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def do_cprofile(func):
|
||||||
|
def profiled_func(*args, **kwargs):
|
||||||
|
profile = cProfile.Profile()
|
||||||
|
try:
|
||||||
|
profile.enable()
|
||||||
|
result = func(*args, **kwargs)
|
||||||
|
profile.disable()
|
||||||
|
return result
|
||||||
|
finally:
|
||||||
|
profile.print_stats('cumulative')
|
||||||
|
return profiled_func
|
||||||
|
@ -41,6 +41,7 @@ class Launcher(object):
|
|||||||
self.services = self._register_services()
|
self.services = self._register_services()
|
||||||
|
|
||||||
def launch(self):
|
def launch(self):
|
||||||
|
# launcher = os_service.ServiceLauncher(self.conf) # For Debugging
|
||||||
launcher = os_service.ProcessLauncher(self.conf)
|
launcher = os_service.ProcessLauncher(self.conf)
|
||||||
for service in self.services:
|
for service in self.services:
|
||||||
launcher.launch_service(service, 1)
|
launcher.launch_service(service, 1)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from stevedore import driver
|
||||||
|
|
||||||
OPTS = [
|
OPTS = [
|
||||||
cfg.StrOpt('datasources_values_dir',
|
cfg.StrOpt('datasources_values_dir',
|
||||||
@ -26,4 +27,17 @@ OPTS = [
|
|||||||
default='vitrage.graph',
|
default='vitrage.graph',
|
||||||
help='The topic that vitrage-graph uses for graph '
|
help='The topic that vitrage-graph uses for graph '
|
||||||
'notification messages.'),
|
'notification messages.'),
|
||||||
|
cfg.StrOpt('graph_driver',
|
||||||
|
default='networkx',
|
||||||
|
help='graph driver implementation class'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_graph_driver(conf):
|
||||||
|
try:
|
||||||
|
mgr = driver.DriverManager('vitrage.entity_graph',
|
||||||
|
conf.entity_graph.graph_driver,
|
||||||
|
invoke_on_load=True)
|
||||||
|
return mgr.driver
|
||||||
|
except ImportError:
|
||||||
|
return None
|
||||||
|
@ -24,8 +24,8 @@ from vitrage.entity_graph.processor import base as processor
|
|||||||
from vitrage.entity_graph.processor.notifier import GraphNotifier
|
from vitrage.entity_graph.processor.notifier import GraphNotifier
|
||||||
from vitrage.entity_graph.processor import processor_utils as PUtils
|
from vitrage.entity_graph.processor import processor_utils as PUtils
|
||||||
from vitrage.entity_graph.transformer_manager import TransformerManager
|
from vitrage.entity_graph.transformer_manager import TransformerManager
|
||||||
from vitrage.graph import create_graph
|
|
||||||
from vitrage.graph import Direction
|
from vitrage.graph import Direction
|
||||||
|
from vitrage.graph.driver.networkx_graph import NXGraph
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ class Processor(processor.ProcessorBase):
|
|||||||
self._initialize_events_actions()
|
self._initialize_events_actions()
|
||||||
self.initialization_status = initialization_status
|
self.initialization_status = initialization_status
|
||||||
self.entity_graph = e_graph if e_graph is not None\
|
self.entity_graph = e_graph if e_graph is not None\
|
||||||
else create_graph("Entity Graph")
|
else NXGraph("Entity Graph")
|
||||||
self._notifier = GraphNotifier(conf)
|
self._notifier = GraphNotifier(conf)
|
||||||
|
|
||||||
def process_event(self, event):
|
def process_event(self, event):
|
||||||
|
@ -28,8 +28,7 @@ from vitrage.evaluator.template_data import ActionSpecs
|
|||||||
from vitrage.evaluator.template_data import EdgeDescription
|
from vitrage.evaluator.template_data import EdgeDescription
|
||||||
from vitrage.evaluator.template_data import ENTITY
|
from vitrage.evaluator.template_data import ENTITY
|
||||||
from vitrage.graph.algo_driver.algorithm import Mapping
|
from vitrage.graph.algo_driver.algorithm import Mapping
|
||||||
from vitrage.graph import create_algorithm
|
from vitrage.graph.driver.networkx_graph import NXGraph
|
||||||
from vitrage.graph import create_graph
|
|
||||||
from vitrage.graph.driver import Vertex
|
from vitrage.graph.driver import Vertex
|
||||||
|
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
@ -55,7 +54,6 @@ class ScenarioEvaluator(object):
|
|||||||
self.conf = conf
|
self.conf = conf
|
||||||
self._scenario_repo = scenario_repo
|
self._scenario_repo = scenario_repo
|
||||||
self._entity_graph = entity_graph
|
self._entity_graph = entity_graph
|
||||||
self._graph_algs = create_algorithm(entity_graph)
|
|
||||||
self._action_executor = ActionExecutor(event_queue)
|
self._action_executor = ActionExecutor(event_queue)
|
||||||
self._entity_graph.subscribe(self.process_event)
|
self._entity_graph.subscribe(self.process_event)
|
||||||
self._action_tracker = ActionTracker(DatasourceInfoMapper(self.conf))
|
self._action_tracker = ActionTracker(DatasourceInfoMapper(self.conf))
|
||||||
@ -204,7 +202,7 @@ class ScenarioEvaluator(object):
|
|||||||
|
|
||||||
def _evaluate_and_condition(self, condition, element, scenario_element):
|
def _evaluate_and_condition(self, condition, element, scenario_element):
|
||||||
|
|
||||||
condition_g = create_graph("scenario condition")
|
condition_g = NXGraph("scenario condition")
|
||||||
for term in condition:
|
for term in condition:
|
||||||
if not term.positive:
|
if not term.positive:
|
||||||
# todo(erosensw): add support for NOT clauses
|
# todo(erosensw): add support for NOT clauses
|
||||||
@ -224,7 +222,8 @@ class ScenarioEvaluator(object):
|
|||||||
initial_map = Mapping(scenario_element, element, True)
|
initial_map = Mapping(scenario_element, element, True)
|
||||||
else:
|
else:
|
||||||
initial_map = Mapping(scenario_element.edge, element, False)
|
initial_map = Mapping(scenario_element.edge, element, False)
|
||||||
return self._graph_algs.sub_graph_matching(condition_g, [initial_map])
|
return self._entity_graph.algo.sub_graph_matching(condition_g,
|
||||||
|
[initial_map])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _set_relationship_not_deleted(edge_description):
|
def _set_relationship_not_deleted(edge_description):
|
||||||
|
@ -11,18 +11,4 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
__author__ = 'stack'
|
||||||
from vitrage.graph.algo_driver.algorithm import * # noqa
|
|
||||||
from vitrage.graph.algo_driver.networkx_algorithm import NXAlgorithm
|
|
||||||
|
|
||||||
|
|
||||||
def create_algorithm(graph):
|
|
||||||
"""Create a Graph algorithm instance
|
|
||||||
|
|
||||||
For now only return NXAlgorithm
|
|
||||||
|
|
||||||
:param graph:
|
|
||||||
:type graph: Graph
|
|
||||||
:rtype: GraphAlgorithm
|
|
||||||
"""
|
|
||||||
return NXAlgorithm(graph=graph)
|
|
||||||
|
@ -21,7 +21,6 @@ from vitrage.graph.algo_driver.algorithm import GraphAlgorithm
|
|||||||
from vitrage.graph.algo_driver.sub_graph_matching import subgraph_matching
|
from vitrage.graph.algo_driver.sub_graph_matching import subgraph_matching
|
||||||
from vitrage.graph.driver import Direction
|
from vitrage.graph.driver import Direction
|
||||||
from vitrage.graph.driver import Edge
|
from vitrage.graph.driver import Edge
|
||||||
from vitrage.graph.driver import NXGraph
|
|
||||||
from vitrage.graph.driver import Vertex
|
from vitrage.graph.driver import Vertex
|
||||||
from vitrage.graph.filter import check_filter
|
from vitrage.graph.filter import check_filter
|
||||||
from vitrage.graph.query import create_predicate
|
from vitrage.graph.query import create_predicate
|
||||||
@ -39,14 +38,18 @@ class NXAlgorithm(GraphAlgorithm):
|
|||||||
"""
|
"""
|
||||||
super(NXAlgorithm, self).__init__(graph)
|
super(NXAlgorithm, self).__init__(graph)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _create_new_graph(cls, *args, **kwargs):
|
||||||
|
from vitrage.graph.driver.networkx_graph import NXGraph
|
||||||
|
return NXGraph(args, **kwargs)
|
||||||
|
|
||||||
def graph_query_vertices(self,
|
def graph_query_vertices(self,
|
||||||
query_dict=None,
|
query_dict=None,
|
||||||
root_id=None,
|
root_id=None,
|
||||||
depth=None,
|
depth=None,
|
||||||
direction=Direction.BOTH,
|
direction=Direction.BOTH,
|
||||||
edge_query_dict=None):
|
edge_query_dict=None):
|
||||||
|
graph = self._create_new_graph('graph')
|
||||||
graph = NXGraph('graph')
|
|
||||||
|
|
||||||
if not root_id:
|
if not root_id:
|
||||||
root_id = self.graph.root_id
|
root_id = self.graph.root_id
|
||||||
@ -80,7 +83,8 @@ class NXAlgorithm(GraphAlgorithm):
|
|||||||
e_result.extend(e_list)
|
e_result.extend(e_list)
|
||||||
nodes_q.extend([(v_id, curr_depth + 1) for v_id, data in n_list])
|
nodes_q.extend([(v_id, curr_depth + 1) for v_id, data in n_list])
|
||||||
|
|
||||||
graph = NXGraph(graph.name,
|
graph = self._create_new_graph(
|
||||||
|
graph.name,
|
||||||
graph.root_id,
|
graph.root_id,
|
||||||
vertices=self._vertex_result_to_list(n_result),
|
vertices=self._vertex_result_to_list(n_result),
|
||||||
edges=self._edge_result_to_list(e_result))
|
edges=self._edge_result_to_list(e_result))
|
||||||
@ -125,7 +129,7 @@ class NXAlgorithm(GraphAlgorithm):
|
|||||||
|
|
||||||
vertices_ids = [vertex.vertex_id for vertex in vertices]
|
vertices_ids = [vertex.vertex_id for vertex in vertices]
|
||||||
|
|
||||||
graph = NXGraph('graph')
|
graph = self._create_new_graph('graph')
|
||||||
graph._g = self.graph._g.subgraph(vertices_ids)
|
graph._g = self.graph._g.subgraph(vertices_ids)
|
||||||
|
|
||||||
# delete non matching edges
|
# delete non matching edges
|
||||||
@ -143,7 +147,7 @@ class NXAlgorithm(GraphAlgorithm):
|
|||||||
return graph
|
return graph
|
||||||
|
|
||||||
def subgraph(self, entities):
|
def subgraph(self, entities):
|
||||||
subgraph = NXGraph('graph')
|
subgraph = self._create_new_graph('graph')
|
||||||
subgraph._g = self.graph._g.subgraph(entities)
|
subgraph._g = self.graph._g.subgraph(entities)
|
||||||
return subgraph
|
return subgraph
|
||||||
|
|
||||||
|
@ -14,16 +14,3 @@
|
|||||||
|
|
||||||
from vitrage.graph.driver.elements import * # noqa
|
from vitrage.graph.driver.elements import * # noqa
|
||||||
from vitrage.graph.driver.graph import * # noqa
|
from vitrage.graph.driver.graph import * # noqa
|
||||||
from vitrage.graph.driver.networkx_graph import NXGraph
|
|
||||||
|
|
||||||
|
|
||||||
def create_graph(name, root_id=None):
|
|
||||||
"""Create a Graph instance
|
|
||||||
|
|
||||||
For now only return NXGraph
|
|
||||||
|
|
||||||
:param root_id:
|
|
||||||
:type name: str
|
|
||||||
:rtype: Graph
|
|
||||||
"""
|
|
||||||
return NXGraph(name, root_id)
|
|
||||||
|
@ -20,6 +20,7 @@ vitrage.graph.driver namespace.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import abc
|
import abc
|
||||||
|
import copy
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from vitrage.graph.driver.elements import Edge
|
from vitrage.graph.driver.elements import Edge
|
||||||
@ -61,6 +62,14 @@ class Graph(object):
|
|||||||
if isinstance(item, Vertex):
|
if isinstance(item, Vertex):
|
||||||
return self.get_vertex(item.vertex_id)
|
return self.get_vertex(item.vertex_id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def algo(self):
|
||||||
|
"""Get graph algorithms
|
||||||
|
|
||||||
|
:rtype: GraphAlgorithm
|
||||||
|
"""
|
||||||
|
return None
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def copy(self):
|
def copy(self):
|
||||||
"""Create a copy of the graph
|
"""Create a copy of the graph
|
||||||
@ -105,7 +114,6 @@ class Graph(object):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def add_vertices(self, vertices):
|
def add_vertices(self, vertices):
|
||||||
"""Add a list of vertices to the graph
|
"""Add a list of vertices to the graph
|
||||||
|
|
||||||
@ -114,7 +122,11 @@ class Graph(object):
|
|||||||
:param vertices:
|
:param vertices:
|
||||||
:type vertices:list of Vertex
|
:type vertices:list of Vertex
|
||||||
"""
|
"""
|
||||||
pass
|
if not vertices:
|
||||||
|
return
|
||||||
|
|
||||||
|
for v in vertices:
|
||||||
|
self.add_vertex(v)
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def add_edge(self, e):
|
def add_edge(self, e):
|
||||||
@ -143,7 +155,6 @@ class Graph(object):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
|
||||||
def add_edges(self, edges):
|
def add_edges(self, edges):
|
||||||
"""Add a list of edges to the graph
|
"""Add a list of edges to the graph
|
||||||
|
|
||||||
@ -152,7 +163,11 @@ class Graph(object):
|
|||||||
:param edges:
|
:param edges:
|
||||||
:type edges:list of Edge
|
:type edges:list of Edge
|
||||||
"""
|
"""
|
||||||
pass
|
if not edges:
|
||||||
|
return
|
||||||
|
|
||||||
|
for e in edges:
|
||||||
|
self.add_edge(e)
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def get_vertex(self, v_id):
|
def get_vertex(self, v_id):
|
||||||
@ -213,53 +228,52 @@ class Graph(object):
|
|||||||
:type attr_filter: dict
|
:type attr_filter: dict
|
||||||
|
|
||||||
:return: All edges matching the requirements
|
:return: All edges matching the requirements
|
||||||
:rtype: list of Edge
|
:rtype: set of Edge
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def update_vertex(self, v, hard_update=False):
|
def update_vertex(self, v):
|
||||||
"""Update the vertex properties
|
"""Update the vertex properties
|
||||||
|
|
||||||
Update an existing vertex and create it if non existing.
|
Update an existing vertex and create it if non existing.
|
||||||
Hard update: can be used to remove existing fields.
|
|
||||||
|
|
||||||
:param v: the vertex with the new data
|
:param v: the vertex with the new data
|
||||||
:type v: Vertex
|
:type v: Vertex
|
||||||
:param hard_update: if True, original properties will be removed.
|
|
||||||
:type hard_update: bool
|
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
def update_vertices(self, vertices):
|
||||||
def update_vertices(self, vertices, hard_update=False):
|
|
||||||
"""For each vertex, update its properties
|
"""For each vertex, update its properties
|
||||||
|
|
||||||
For each existing vertex, update its properties and create it if
|
For each existing vertex, update its properties and create it if
|
||||||
non existing.
|
non existing.
|
||||||
Hard update: can be used to remove existing fields.
|
|
||||||
|
|
||||||
:param vertices: the vertex with the new data
|
:param vertices: the vertex with the new data
|
||||||
:type vertices: List
|
:type vertices: List
|
||||||
:param hard_update: if True, original properties will be removed.
|
|
||||||
:type hard_update: bool
|
|
||||||
"""
|
"""
|
||||||
pass
|
for v in vertices:
|
||||||
|
self.update_vertex(v)
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def update_edge(self, e, hard_update=False):
|
def update_edge(self, e):
|
||||||
"""Update the edge properties
|
"""Update the edge properties
|
||||||
|
|
||||||
Update an existing edge and create it if non existing.
|
Update an existing edge and create it if non existing.
|
||||||
Hard update: can be used to remove existing fields.
|
|
||||||
|
|
||||||
:param e: the edge with the new data
|
:param e: the edge with the new data
|
||||||
:type e: Edge
|
:type e: Edge
|
||||||
:param hard_update: if True, original properties will be removed.
|
|
||||||
:type hard_update: bool
|
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _merge_properties(base_props, new_props):
|
||||||
|
if base_props is None:
|
||||||
|
base_props = copy.copy(new_props)
|
||||||
|
else:
|
||||||
|
base_props.update(copy.copy(new_props))
|
||||||
|
return {k: v for k, v in base_props.items() if v is not None}
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def remove_vertex(self, v):
|
def remove_vertex(self, v):
|
||||||
"""Remove Vertex v and its edges from the graph
|
"""Remove Vertex v and its edges from the graph
|
||||||
|
@ -21,6 +21,7 @@ from networkx.readwrite import json_graph
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from vitrage.common.constants import VertexProperties as VProps
|
from vitrage.common.constants import VertexProperties as VProps
|
||||||
|
from vitrage.graph.algo_driver.networkx_algorithm import NXAlgorithm
|
||||||
from vitrage.graph.driver.elements import Edge
|
from vitrage.graph.driver.elements import Edge
|
||||||
from vitrage.graph.driver.elements import Vertex
|
from vitrage.graph.driver.elements import Vertex
|
||||||
from vitrage.graph.driver.graph import Direction
|
from vitrage.graph.driver.graph import Direction
|
||||||
@ -59,6 +60,10 @@ class NXGraph(Graph):
|
|||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self._g)
|
return len(self._g)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def algo(self):
|
||||||
|
return NXAlgorithm(self)
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
self_copy = NXGraph(self.name, self.root_id)
|
self_copy = NXGraph(self.name, self.root_id)
|
||||||
self_copy._g = self._g.copy()
|
self_copy._g = self._g.copy()
|
||||||
@ -77,13 +82,6 @@ class NXGraph(Graph):
|
|||||||
properties_copy = copy.copy(v.properties)
|
properties_copy = copy.copy(v.properties)
|
||||||
self._g.add_node(n=v.vertex_id, attr_dict=properties_copy)
|
self._g.add_node(n=v.vertex_id, attr_dict=properties_copy)
|
||||||
|
|
||||||
def add_vertices(self, vertices):
|
|
||||||
if not vertices:
|
|
||||||
return
|
|
||||||
|
|
||||||
for v in vertices:
|
|
||||||
self.add_vertex(v)
|
|
||||||
|
|
||||||
@Notifier.update_notify
|
@Notifier.update_notify
|
||||||
def add_edge(self, e):
|
def add_edge(self, e):
|
||||||
"""Add an edge to the graph
|
"""Add an edge to the graph
|
||||||
@ -98,13 +96,6 @@ class NXGraph(Graph):
|
|||||||
self._g.add_edge(u=e.source_id, v=e.target_id,
|
self._g.add_edge(u=e.source_id, v=e.target_id,
|
||||||
key=e.label, attr_dict=properties_copy)
|
key=e.label, attr_dict=properties_copy)
|
||||||
|
|
||||||
def add_edges(self, edges):
|
|
||||||
if not edges:
|
|
||||||
return
|
|
||||||
|
|
||||||
for e in edges:
|
|
||||||
self.add_edge(e)
|
|
||||||
|
|
||||||
def get_vertex(self, v_id):
|
def get_vertex(self, v_id):
|
||||||
"""Fetch a vertex from the graph
|
"""Fetch a vertex from the graph
|
||||||
|
|
||||||
@ -131,15 +122,15 @@ class NXGraph(Graph):
|
|||||||
attr_filter=None):
|
attr_filter=None):
|
||||||
"""Fetch multiple edges from the graph
|
"""Fetch multiple edges from the graph
|
||||||
|
|
||||||
:rtype: list of Edge
|
:rtype: set of Edge
|
||||||
"""
|
"""
|
||||||
def check_edge(edge_data):
|
def check_edge(edge_data):
|
||||||
return check_filter(edge_data, attr_filter)
|
return check_filter(edge_data, attr_filter)
|
||||||
|
|
||||||
nodes, edges = self._neighboring_nodes_edges_query(
|
nodes, edges = self._neighboring_nodes_edges_query(
|
||||||
v_id, edge_predicate=check_edge, direction=direction)
|
v_id, edge_predicate=check_edge, direction=direction)
|
||||||
edge_copies = [edge_copy(u, v, label, data)
|
edge_copies = set(edge_copy(u, v, label, data)
|
||||||
for u, v, label, data in edges]
|
for u, v, label, data in edges)
|
||||||
return edge_copies
|
return edge_copies
|
||||||
|
|
||||||
def _get_edges_by_direction(self, v_id, direction):
|
def _get_edges_by_direction(self, v_id, direction):
|
||||||
@ -165,33 +156,22 @@ class NXGraph(Graph):
|
|||||||
return self._g.number_of_edges()
|
return self._g.number_of_edges()
|
||||||
|
|
||||||
@Notifier.update_notify
|
@Notifier.update_notify
|
||||||
def update_vertex(self, v, hard_update=False):
|
def update_vertex(self, v):
|
||||||
"""Update the vertex properties
|
"""Update the vertex properties
|
||||||
|
|
||||||
:param hard_update:
|
|
||||||
:type v: Vertex
|
:type v: Vertex
|
||||||
"""
|
"""
|
||||||
orig_prop = self._g.node.get(v.vertex_id, None)
|
orig_prop = self._g.node.get(v.vertex_id, None)
|
||||||
if not orig_prop:
|
if not orig_prop:
|
||||||
self._add_vertex(v)
|
self._add_vertex(v)
|
||||||
return
|
return
|
||||||
new_prop = self._merge_properties(orig_prop, v.properties, hard_update)
|
new_prop = self._merge_properties(orig_prop, v.properties)
|
||||||
self._g.node[v.vertex_id] = new_prop
|
self._g.node[v.vertex_id] = new_prop
|
||||||
|
|
||||||
def update_vertices(self, vertices, hard_update=False):
|
|
||||||
"""For each vertex, update its properties
|
|
||||||
|
|
||||||
:param hard_update:
|
|
||||||
:type vertices: List
|
|
||||||
"""
|
|
||||||
for v in vertices:
|
|
||||||
self.update_vertex(v, hard_update)
|
|
||||||
|
|
||||||
@Notifier.update_notify
|
@Notifier.update_notify
|
||||||
def update_edge(self, e, hard_update=False):
|
def update_edge(self, e):
|
||||||
"""Update the edge properties
|
"""Update the edge properties
|
||||||
|
|
||||||
:param hard_update:
|
|
||||||
:type e: Edge
|
:type e: Edge
|
||||||
"""
|
"""
|
||||||
orig_prop = self._g.edge.get(
|
orig_prop = self._g.edge.get(
|
||||||
@ -201,17 +181,9 @@ class NXGraph(Graph):
|
|||||||
if not orig_prop:
|
if not orig_prop:
|
||||||
self._add_edge(e)
|
self._add_edge(e)
|
||||||
return
|
return
|
||||||
new_prop = self._merge_properties(orig_prop, e.properties, hard_update)
|
new_prop = self._merge_properties(orig_prop, e.properties)
|
||||||
self._g.edge[e.source_id][e.target_id][e.label] = new_prop
|
self._g.edge[e.source_id][e.target_id][e.label] = new_prop
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _merge_properties(base_props, new_props, hard_update):
|
|
||||||
if base_props is None or hard_update:
|
|
||||||
base_props = copy.copy(new_props)
|
|
||||||
else:
|
|
||||||
base_props.update(copy.copy(new_props))
|
|
||||||
return {k: v for k, v in base_props.items() if v is not None}
|
|
||||||
|
|
||||||
def remove_vertex(self, v):
|
def remove_vertex(self, v):
|
||||||
"""Remove Vertex v and its edges from the graph
|
"""Remove Vertex v and its edges from the graph
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ def _after_func(graph, item, data_before=None):
|
|||||||
if not graph.is_subscribed():
|
if not graph.is_subscribed():
|
||||||
return
|
return
|
||||||
element = graph.get_item(item)
|
element = graph.get_item(item)
|
||||||
is_vertex = isinstance(element, Vertex)
|
is_vertex = isinstance(element, Vertex) or isinstance(item, Vertex)
|
||||||
graph.notifier.notify(data_before, graph.get_item(item), is_vertex, graph)
|
graph.notifier.notify(data_before, element, is_vertex, graph)
|
||||||
|
|
||||||
|
|
||||||
class Notifier(object):
|
class Notifier(object):
|
||||||
|
@ -23,7 +23,7 @@ from vitrage.datasources import NOVA_HOST_DATASOURCE
|
|||||||
from vitrage.datasources import NOVA_INSTANCE_DATASOURCE
|
from vitrage.datasources import NOVA_INSTANCE_DATASOURCE
|
||||||
from vitrage.datasources import NOVA_ZONE_DATASOURCE
|
from vitrage.datasources import NOVA_ZONE_DATASOURCE
|
||||||
from vitrage.datasources import OPENSTACK_CLUSTER
|
from vitrage.datasources import OPENSTACK_CLUSTER
|
||||||
from vitrage.graph import NXGraph
|
from vitrage.graph.driver.networkx_graph import NXGraph
|
||||||
import vitrage.graph.utils as graph_utils
|
import vitrage.graph.utils as graph_utils
|
||||||
from vitrage.tests.unit.entity_graph.base import TestEntityGraphUnitBase
|
from vitrage.tests.unit.entity_graph.base import TestEntityGraphUnitBase
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from vitrage.entity_graph.processor import processor_utils as PUtils
|
from vitrage.entity_graph.processor import processor_utils as PUtils
|
||||||
from vitrage.graph import NXGraph
|
from vitrage.graph.driver.networkx_graph import NXGraph
|
||||||
from vitrage.tests.unit.entity_graph.processor import base
|
from vitrage.tests.unit.entity_graph.processor import base
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,12 +26,13 @@ from oslo_log import log as logging
|
|||||||
|
|
||||||
from vitrage.common.constants import EdgeLabel as ELabel
|
from vitrage.common.constants import EdgeLabel as ELabel
|
||||||
from vitrage.common.constants import EntityCategory
|
from vitrage.common.constants import EntityCategory
|
||||||
|
from vitrage.common.exception import VitrageError
|
||||||
from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE
|
from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE
|
||||||
from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE
|
from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE
|
||||||
from vitrage.datasources import OPENSTACK_CLUSTER
|
from vitrage.datasources import OPENSTACK_CLUSTER
|
||||||
from vitrage.datasources.static_physical import SWITCH
|
from vitrage.datasources.static_physical import SWITCH
|
||||||
from vitrage.datasources.transformer_base import CLUSTER_ID
|
from vitrage.datasources.transformer_base import CLUSTER_ID
|
||||||
from vitrage.graph import create_graph
|
from vitrage.graph.driver.networkx_graph import NXGraph
|
||||||
from vitrage.graph import utils as graph_utils
|
from vitrage.graph import utils as graph_utils
|
||||||
from vitrage.tests import base
|
from vitrage.tests import base
|
||||||
|
|
||||||
@ -120,31 +121,19 @@ class GraphTestBase(base.BaseTest):
|
|||||||
def __init__(self, *args, **kwds):
|
def __init__(self, *args, **kwds):
|
||||||
super(GraphTestBase, self).__init__(*args, **kwds)
|
super(GraphTestBase, self).__init__(*args, **kwds)
|
||||||
|
|
||||||
self.vm_id = 10000000
|
|
||||||
self.vm_alarm_id = 30000000
|
|
||||||
self.vms = []
|
|
||||||
self.host_alarm_id = 20000000
|
|
||||||
self.host_test_id = 40000000
|
|
||||||
self.entity_graph = self._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 _assert_set_equal(self, d1, d2, message):
|
def _assert_set_equal(self, d1, d2, message):
|
||||||
super(GraphTestBase, self).assert_dict_equal(
|
super(GraphTestBase, self).assert_dict_equal(
|
||||||
dict.fromkeys(d1, 0), dict.fromkeys(d2, 0), message)
|
dict.fromkeys(d1, 0), dict.fromkeys(d2, 0), message)
|
||||||
|
|
||||||
def _create_entity_graph(self, name, num_of_alarms_per_host,
|
@classmethod
|
||||||
|
def _create_entity_graph(cls, name, num_of_alarms_per_host,
|
||||||
num_of_alarms_per_vm,
|
num_of_alarms_per_vm,
|
||||||
num_of_hosts_per_node,
|
num_of_hosts_per_node,
|
||||||
num_of_vms_per_host,
|
num_of_vms_per_host,
|
||||||
num_of_tests_per_host):
|
num_of_tests_per_host):
|
||||||
|
|
||||||
start = time.time()
|
start = time.time()
|
||||||
g = create_graph(name, EntityCategory.RESOURCE + ':' +
|
g = NXGraph(name, EntityCategory.RESOURCE + ':' +
|
||||||
OPENSTACK_CLUSTER + ':' +
|
OPENSTACK_CLUSTER + ':' +
|
||||||
CLUSTER_ID)
|
CLUSTER_ID)
|
||||||
g.add_vertex(v_node)
|
g.add_vertex(v_node)
|
||||||
@ -167,34 +156,34 @@ class GraphTestBase(base.BaseTest):
|
|||||||
# Add Host Alarms
|
# Add Host Alarms
|
||||||
for j in range(num_of_alarms_per_host):
|
for j in range(num_of_alarms_per_host):
|
||||||
add_connected_vertex(g, ALARM, ALARM_ON_HOST,
|
add_connected_vertex(g, ALARM, ALARM_ON_HOST,
|
||||||
self.host_alarm_id, ELabel.ON,
|
cls.host_alarm_id, ELabel.ON,
|
||||||
host_to_add)
|
host_to_add)
|
||||||
self.host_alarm_id += 1
|
cls.host_alarm_id += 1
|
||||||
|
|
||||||
# Add Host Tests
|
# Add Host Tests
|
||||||
for j in range(num_of_tests_per_host):
|
for j in range(num_of_tests_per_host):
|
||||||
add_connected_vertex(g, TEST, TEST_ON_HOST, self.host_test_id,
|
add_connected_vertex(g, TEST, TEST_ON_HOST, cls.host_test_id,
|
||||||
ELabel.ON, host_to_add)
|
ELabel.ON, host_to_add)
|
||||||
self.host_test_id += 1
|
cls.host_test_id += 1
|
||||||
|
|
||||||
# Add Host Vms
|
# Add Host Vms
|
||||||
for j in range(num_of_vms_per_host):
|
for j in range(num_of_vms_per_host):
|
||||||
vm_to_add = add_connected_vertex(g,
|
vm_to_add = add_connected_vertex(g,
|
||||||
RESOURCE,
|
RESOURCE,
|
||||||
NOVA_INSTANCE_DATASOURCE,
|
NOVA_INSTANCE_DATASOURCE,
|
||||||
self.vm_id,
|
cls.vm_id,
|
||||||
ELabel.CONTAINS,
|
ELabel.CONTAINS,
|
||||||
host_to_add,
|
host_to_add,
|
||||||
True)
|
True)
|
||||||
self.vm_id += 1
|
cls.vm_id += 1
|
||||||
self.vms.append(vm_to_add)
|
cls.vms.append(vm_to_add)
|
||||||
|
|
||||||
# Add Instance Alarms
|
# Add Instance Alarms
|
||||||
for k in range(num_of_alarms_per_vm):
|
for k in range(num_of_alarms_per_vm):
|
||||||
add_connected_vertex(g, ALARM, ALARM_ON_VM,
|
add_connected_vertex(g, ALARM, ALARM_ON_VM,
|
||||||
self.vm_alarm_id, ELabel.ON,
|
cls.vm_alarm_id, ELabel.ON,
|
||||||
vm_to_add)
|
vm_to_add)
|
||||||
self.vm_alarm_id += 1
|
cls.vm_alarm_id += 1
|
||||||
|
|
||||||
end = time.time()
|
end = time.time()
|
||||||
LOG.debug('Graph creation took ' + str(end - start) +
|
LOG.debug('Graph creation took ' + str(end - start) +
|
||||||
@ -205,5 +194,10 @@ class GraphTestBase(base.BaseTest):
|
|||||||
num_of_vms_per_host + num_of_hosts_per_node * \
|
num_of_vms_per_host + num_of_hosts_per_node * \
|
||||||
num_of_vms_per_host * num_of_alarms_per_vm + \
|
num_of_vms_per_host * num_of_alarms_per_vm + \
|
||||||
num_of_tests_per_host * num_of_hosts_per_node
|
num_of_tests_per_host * num_of_hosts_per_node
|
||||||
assert expected_graph_size == len(g), 'Graph size'
|
if not expected_graph_size == len(g):
|
||||||
|
raise VitrageError('Init failed, graph size unexpected {0} != {1}'
|
||||||
|
.format(expected_graph_size, len(g)))
|
||||||
|
# cls.assertEqual(
|
||||||
|
# expected_graph_size,
|
||||||
|
# len(g), 'num of vertex node')
|
||||||
return g
|
return g
|
||||||
|
@ -31,7 +31,7 @@ LOG = logging.getLogger(__name__)
|
|||||||
class TestGraph(GraphTestBase):
|
class TestGraph(GraphTestBase):
|
||||||
|
|
||||||
def test_graph(self):
|
def test_graph(self):
|
||||||
g = create_graph('test_graph')
|
g = NXGraph('test_graph')
|
||||||
self.assertEqual('test_graph', g.name, 'graph name')
|
self.assertEqual('test_graph', g.name, 'graph name')
|
||||||
self.assertEqual(0, len(g), 'graph __len__')
|
self.assertEqual(0, len(g), 'graph __len__')
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ class TestGraph(GraphTestBase):
|
|||||||
'graph copy vertex unchanged after update')
|
'graph copy vertex unchanged after update')
|
||||||
|
|
||||||
def test_vertex_crud(self):
|
def test_vertex_crud(self):
|
||||||
g = create_graph('test_vertex_crud')
|
g = NXGraph('test_vertex_crud')
|
||||||
g.add_vertex(v_node)
|
g.add_vertex(v_node)
|
||||||
v = g.get_vertex(v_node.vertex_id)
|
v = g.get_vertex(v_node.vertex_id)
|
||||||
self.assertEqual(v_node[VProps.ID], v[VProps.ID],
|
self.assertEqual(v_node[VProps.ID], v[VProps.ID],
|
||||||
@ -125,7 +125,7 @@ class TestGraph(GraphTestBase):
|
|||||||
def test_update_vertices(self):
|
def test_update_vertices(self):
|
||||||
|
|
||||||
# Test Setup
|
# Test Setup
|
||||||
g = create_graph('test_update_vertices')
|
g = NXGraph('test_update_vertices')
|
||||||
g.add_vertex(v_node)
|
g.add_vertex(v_node)
|
||||||
v_node_copy = g.get_vertex(v_node.vertex_id)
|
v_node_copy = g.get_vertex(v_node.vertex_id)
|
||||||
v_node_copy[VProps.NAME] = 'test_node'
|
v_node_copy[VProps.NAME] = 'test_node'
|
||||||
@ -147,7 +147,7 @@ class TestGraph(GraphTestBase):
|
|||||||
self.assertEqual('test_host', updated_v_host[VProps.NAME])
|
self.assertEqual('test_host', updated_v_host[VProps.NAME])
|
||||||
|
|
||||||
def test_edge_crud(self):
|
def test_edge_crud(self):
|
||||||
g = create_graph('test_edge_crud')
|
g = NXGraph('test_edge_crud')
|
||||||
g.add_vertex(v_node)
|
g.add_vertex(v_node)
|
||||||
g.add_vertex(v_host)
|
g.add_vertex(v_host)
|
||||||
g.add_edge(e_node_to_host)
|
g.add_edge(e_node_to_host)
|
||||||
@ -256,7 +256,7 @@ class TestGraph(GraphTestBase):
|
|||||||
vitrage_id='kuku',
|
vitrage_id='kuku',
|
||||||
entity_category=NOVA_HOST_DATASOURCE)
|
entity_category=NOVA_HOST_DATASOURCE)
|
||||||
|
|
||||||
g = create_graph('test_neighbors')
|
g = NXGraph('test_neighbors')
|
||||||
g.add_vertex(v1)
|
g.add_vertex(v1)
|
||||||
g.add_vertex(v2)
|
g.add_vertex(v2)
|
||||||
g.add_vertex(v3)
|
g.add_vertex(v3)
|
||||||
@ -386,7 +386,7 @@ class TestGraph(GraphTestBase):
|
|||||||
'Check neighbors for not connected vertex')
|
'Check neighbors for not connected vertex')
|
||||||
|
|
||||||
def test_get_vertices(self):
|
def test_get_vertices(self):
|
||||||
g = create_graph('test_get_vertices')
|
g = NXGraph('test_get_vertices')
|
||||||
g.add_vertex(v_node)
|
g.add_vertex(v_node)
|
||||||
g.add_vertex(v_host)
|
g.add_vertex(v_host)
|
||||||
g.add_edge(e_node_to_host)
|
g.add_edge(e_node_to_host)
|
||||||
@ -436,7 +436,7 @@ class TestGraph(GraphTestBase):
|
|||||||
# noinspection PyAttributeOutsideInit
|
# noinspection PyAttributeOutsideInit
|
||||||
def test_graph_callbacks(self):
|
def test_graph_callbacks(self):
|
||||||
|
|
||||||
g = create_graph('test_graph_callbacks')
|
g = NXGraph('test_graph_callbacks')
|
||||||
self.result = None
|
self.result = None
|
||||||
|
|
||||||
def callback(pre_item,
|
def callback(pre_item,
|
||||||
@ -498,14 +498,14 @@ class TestGraph(GraphTestBase):
|
|||||||
target_id=v4.vertex_id,
|
target_id=v4.vertex_id,
|
||||||
relationship_type='KUKU_v3_v4')
|
relationship_type='KUKU_v3_v4')
|
||||||
|
|
||||||
g1 = create_graph('test_union')
|
g1 = NXGraph('test_union')
|
||||||
g1.add_vertex(v1)
|
g1.add_vertex(v1)
|
||||||
g1.add_vertex(v2)
|
g1.add_vertex(v2)
|
||||||
g1.add_vertex(v3)
|
g1.add_vertex(v3)
|
||||||
g1.add_edge(e_v1_v2)
|
g1.add_edge(e_v1_v2)
|
||||||
g1.add_edge(e_v2_v3)
|
g1.add_edge(e_v2_v3)
|
||||||
|
|
||||||
g2 = create_graph('test_union_')
|
g2 = NXGraph('test_union_')
|
||||||
g2.add_vertex(v3)
|
g2.add_vertex(v3)
|
||||||
g2.add_vertex(v4)
|
g2.add_vertex(v4)
|
||||||
g2.add_edge(e_v3_v4)
|
g2.add_edge(e_v3_v4)
|
||||||
|
@ -23,15 +23,32 @@ Tests for `vitrage` graph driver algorithms
|
|||||||
from vitrage.common.constants import EdgeLabel
|
from vitrage.common.constants import EdgeLabel
|
||||||
from vitrage.common.constants import EdgeProperties as EProps
|
from vitrage.common.constants import EdgeProperties as EProps
|
||||||
from vitrage.common.constants import VertexProperties as VProps
|
from vitrage.common.constants import VertexProperties as VProps
|
||||||
|
from vitrage.graph.algo_driver.algorithm import Mapping
|
||||||
from vitrage.graph.driver.elements import Edge
|
from vitrage.graph.driver.elements import Edge
|
||||||
from vitrage.graph import create_algorithm, Mapping, Direction # noqa
|
from vitrage.graph.driver.graph import Direction
|
||||||
from vitrage.tests.unit.graph.base import * # noqa
|
from vitrage.tests.unit.graph.base import * # noqa
|
||||||
|
|
||||||
|
|
||||||
class GraphAlgorithmTest(GraphTestBase):
|
class GraphAlgorithmTest(GraphTestBase):
|
||||||
|
|
||||||
|
# noinspection PyPep8Naming
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
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):
|
def test_graph_query_vertices(self):
|
||||||
ga = create_algorithm(self.entity_graph)
|
ga = self.entity_graph.algo
|
||||||
|
|
||||||
query = {'==': {VProps.TYPE: OPENSTACK_CLUSTER}}
|
query = {'==': {VProps.TYPE: OPENSTACK_CLUSTER}}
|
||||||
subgraph = ga.graph_query_vertices(query)
|
subgraph = ga.graph_query_vertices(query)
|
||||||
@ -186,11 +203,14 @@ class GraphAlgorithmTest(GraphTestBase):
|
|||||||
'We filtered the ON relationship, so no alarms '
|
'We filtered the ON relationship, so no alarms '
|
||||||
'should exist')
|
'should exist')
|
||||||
|
|
||||||
def test_no_match_graph_query_vertices(self):
|
# Undo changes made by this test
|
||||||
ga = create_algorithm(self.entity_graph)
|
host_instance_edge[VProps.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.TYPE: 'test'}}
|
query = {'==': {VProps.TYPE: 'test'}}
|
||||||
subgraph = ga.graph_query_vertices(query)
|
subgraph = self.entity_graph.algo.graph_query_vertices(query)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
0,
|
0,
|
||||||
subgraph.num_vertices(), 'num of vertex node')
|
subgraph.num_vertices(), 'num of vertex node')
|
||||||
@ -201,7 +221,7 @@ class GraphAlgorithmTest(GraphTestBase):
|
|||||||
Using the entity graph (created above) as a big graph we search
|
Using the entity graph (created above) as a big graph we search
|
||||||
for a sub graph match
|
for a sub graph match
|
||||||
"""
|
"""
|
||||||
ga = create_algorithm(self.entity_graph)
|
ga = self.entity_graph.algo
|
||||||
|
|
||||||
# Get ids of some of the elements in the entity graph:
|
# Get ids of some of the elements in the entity graph:
|
||||||
vm_alarm = self.entity_graph.get_vertex(
|
vm_alarm = self.entity_graph.get_vertex(
|
||||||
@ -210,7 +230,7 @@ class GraphAlgorithmTest(GraphTestBase):
|
|||||||
ALARM_ON_HOST + str(self.host_alarm_id - 1))
|
ALARM_ON_HOST + str(self.host_alarm_id - 1))
|
||||||
|
|
||||||
# Create a template for template matching
|
# Create a template for template matching
|
||||||
t = create_graph('template_graph')
|
t = NXGraph('template_graph')
|
||||||
t_v_host_alarm = graph_utils.create_vertex(
|
t_v_host_alarm = graph_utils.create_vertex(
|
||||||
vitrage_id='1', entity_category=ALARM, entity_type=ALARM_ON_HOST)
|
vitrage_id='1', entity_category=ALARM, entity_type=ALARM_ON_HOST)
|
||||||
t_v_alarm_fail = graph_utils.create_vertex(
|
t_v_alarm_fail = graph_utils.create_vertex(
|
||||||
|
@ -29,8 +29,8 @@ from vitrage.datasources import NOVA_INSTANCE_DATASOURCE
|
|||||||
from vitrage.datasources import NOVA_ZONE_DATASOURCE
|
from vitrage.datasources import NOVA_ZONE_DATASOURCE
|
||||||
from vitrage.datasources import OPENSTACK_CLUSTER
|
from vitrage.datasources import OPENSTACK_CLUSTER
|
||||||
from vitrage.datasources.static_physical import SWITCH
|
from vitrage.datasources.static_physical import SWITCH
|
||||||
|
from vitrage.graph.driver.networkx_graph import NXGraph
|
||||||
from vitrage.graph import Edge
|
from vitrage.graph import Edge
|
||||||
from vitrage.graph import NXGraph
|
|
||||||
from vitrage.graph import Vertex
|
from vitrage.graph import Vertex
|
||||||
from vitrage import keystone_client
|
from vitrage import keystone_client
|
||||||
from vitrage import os_clients
|
from vitrage import os_clients
|
||||||
|
Loading…
Reference in New Issue
Block a user