adding support for networkx 2.0

Change-Id: Ieced246b384b6a4be52583007ffbf3f767e18673
Partial-Bug: #1718576
This commit is contained in:
Anna 2018-02-14 10:13:49 +00:00
parent 0ed2676b86
commit 457c55d8a2
4 changed files with 62 additions and 33 deletions

View File

@ -82,9 +82,6 @@ class TopologyApis(EntityGraphApisBase):
is_admin_project,
root_id)
alarms = graph.get_vertices(query_dict=ALARMS_ALL_QUERY)
graph.update_vertices(alarms)
return graph.json_output_graph()
def _get_topology_for_specific_project(self,
@ -179,7 +176,7 @@ class TopologyApis(EntityGraphApisBase):
def _create_graph_of_connected_components(self, ga, tmp_graph, root):
return ga.subgraph(self._topology_for_unrooted_graph(ga,
tmp_graph,
root))
root)).copy()
def _topology_for_unrooted_graph(self, ga, subgraph, root):
"""Finds topology for unrooted subgraph
@ -204,7 +201,7 @@ class TopologyApis(EntityGraphApisBase):
ga.connected_component_subgraphs(subgraph)
for component_subgraph in local_connected_component_subgraphs:
entities += component_subgraph.nodes()
entities += list(component_subgraph.nodes())
instance_in_component_subgraph = \
self._find_instance_in_graph(component_subgraph)
if instance_in_component_subgraph:
@ -227,7 +224,7 @@ class TopologyApis(EntityGraphApisBase):
@staticmethod
def _find_instance_in_graph(graph):
for node, node_data in graph.nodes_iter(data=True):
for node, node_data in graph.nodes(data=True):
if node_data[VProps.VITRAGE_CATEGORY] == \
EntityCategory.RESOURCE \
and node_data[VProps.VITRAGE_TYPE] == \

View File

@ -90,11 +90,11 @@ class NXAlgorithm(GraphAlgorithm):
edges=self._edge_result_to_list(e_result))
LOG.debug('graph_query_vertices: find graph: nodes %s, edges %s',
str(graph._g.nodes(data=True)),
str(graph._g.edges(data=True)))
str(list(graph._g.nodes(data=True))),
str(list(graph._g.edges(data=True))))
LOG.debug('graph_query_vertices: real graph: nodes %s, edges %s',
str(self.graph._g.nodes(data=True)),
str(self.graph._g.edges(data=True)))
str(list(self.graph._g.nodes(data=True))),
str(list(self.graph._g.edges(data=True))))
return graph
def sub_graph_matching(self,
@ -148,18 +148,18 @@ class NXAlgorithm(GraphAlgorithm):
vertices_ids = [vertex.vertex_id for vertex in vertices]
graph = self._create_new_graph('graph')
graph._g = self.graph._g.subgraph(vertices_ids)
graph._g = self.graph._g.subgraph(vertices_ids).copy()
# delete non matching edges
if edge_attr_filter:
self._apply_edge_attr_filter(graph, edge_attr_filter)
LOG.debug('match query, find graph: nodes %s, edges %s',
str(graph._g.nodes(data=True)),
str(graph._g.edges(data=True)))
str(list(graph._g.nodes(data=True))),
str(list(graph._g.edges(data=True))))
LOG.debug('match query, real graph: nodes %s, edges %s',
str(self.graph._g.nodes(data=True)),
str(self.graph._g.edges(data=True)))
str(list(self.graph._g.nodes(data=True))),
str(list(self.graph._g.edges(data=True))))
return graph
@ -230,8 +230,8 @@ class NXAlgorithm(GraphAlgorithm):
@staticmethod
def _apply_edge_attr_filter(graph, edge_attr_filter):
edges_iter = graph._g.edges_iter(data=True, keys=True)
edges_to_remove = [(u, v, k) for (u, v, k, d) in edges_iter
edges = graph._g.edges(data=True, keys=True)
edges_to_remove = [(u, v, k) for (u, v, k, d) in edges
if not check_filter(d, edge_attr_filter)]
for source, target, key in edges_to_remove:
graph._g.remove_edge(u=source, v=target, key=key)

View File

@ -64,9 +64,9 @@ class NXGraph(Graph):
def copy(self):
# Networkx graph copy is very slow, so we implement
nodes = self._g.nodes_iter(data=True)
nodes = self._g.nodes(data=True)
vertices = [Vertex(vertex_id=n, properties=data) for n, data in nodes]
edges_iter = self._g.edges_iter(data=True, keys=True)
edges_iter = self._g.edges(data=True, keys=True)
edges = [Edge(source_id=u, target_id=v, label=l, properties=data)
for u, v, l, data in edges_iter]
return NXGraph(self.name, vertices, edges)
@ -82,7 +82,10 @@ class NXGraph(Graph):
def _add_vertex(self, v):
properties_copy = copy.copy(v.properties)
self._g.add_node(n=v.vertex_id, attr_dict=properties_copy)
if properties_copy:
self._g.add_node(n=v.vertex_id, **properties_copy)
else:
self._g.add_node(n=v.vertex_id)
@Notifier.update_notify
def add_edge(self, e):
@ -95,8 +98,12 @@ class NXGraph(Graph):
def _add_edge(self, e):
properties_copy = copy.copy(e.properties)
self._g.add_edge(u=e.source_id, v=e.target_id,
key=e.label, attr_dict=properties_copy)
if properties_copy:
self._g.add_edge(u=e.source_id, v=e.target_id,
key=e.label, **properties_copy)
else:
self._g.add_edge(u=e.source_id, v=e.target_id,
key=e.label)
def get_vertex(self, v_id):
"""Fetch a vertex from the graph
@ -175,8 +182,10 @@ class NXGraph(Graph):
if not orig_prop:
self._add_vertex(v)
return
new_prop = self._merge_properties(orig_prop, v.properties)
self._g.node[v.vertex_id] = new_prop
self._g.node[v.vertex_id].update(v.properties)
for prop, value in v.properties.items():
if value is None:
del self._g.node[v.vertex_id][prop]
@Notifier.update_notify
def update_edge(self, e):
@ -184,15 +193,17 @@ class NXGraph(Graph):
:type e: Edge
"""
orig_prop = self._g.edge.get(
orig_prop = self._g.adj.get(
e.source_id, {}).get(
e.target_id, {}).get(
e.label, None)
if not orig_prop:
self._add_edge(e)
return
new_prop = self._merge_properties(orig_prop, e.properties)
self._g.edge[e.source_id][e.target_id][e.label] = new_prop
self._g.adj[e.source_id][e.target_id][e.label].update(e.properties)
for prop, value in e.properties.items():
if value is None:
del self._g.adj[e.source_id][e.target_id][e.label][prop]
def remove_vertex(self, v):
"""Remove Vertex v and its edges from the graph
@ -216,12 +227,12 @@ class NXGraph(Graph):
return check_filter(vertex_data[1], vertex_attr_filter)
if not query_dict:
items = filter(check_vertex, self._g.nodes_iter(data=True))
items = filter(check_vertex, list(self._g.nodes(data=True)))
return [vertex_copy(node, node_data) for node, node_data in items]
elif not vertex_attr_filter:
vertices = []
match_func = create_predicate(query_dict)
for node, node_data in self._g.nodes_iter(data=True):
for node, node_data in self._g.nodes(data=True):
v = vertex_copy(node, node_data)
if match_func(v):
vertices.append(v)
@ -283,14 +294,34 @@ class NXGraph(Graph):
return nodes, edges_filtered2
def json_output_graph(self, **kwargs):
"""supports both 1.10<=networkx<2.0 and networx>=2.0 by returning the
same json output regardless networx version
:return: graph in json format
"""
# TODO(annarez): when we decide to support networkx 2.0 with
# versioning of Vitrage, we can move part of the logic to vitrageclient
node_link_data = json_graph.node_link_data(self._g)
node_link_data.update(kwargs)
vitrage_id_to_index = dict()
for index, node in enumerate(node_link_data['nodes']):
vitrage_id_to_index[node[VProps.VITRAGE_ID]] = index
if VProps.ID in self._g.node[node[VProps.ID]]:
node[VProps.ID] = self._g.node[node[VProps.ID]][VProps.ID]
node[VProps.GRAPH_INDEX] = index
vers = nx.__version__
if vers >= '2.0':
for i in range(len(node_link_data['links'])):
node_link_data['links'][i]['source'] = vitrage_id_to_index[
node_link_data['links'][i]['source']]
node_link_data['links'][i]['target'] = vitrage_id_to_index[
node_link_data['links'][i]['target']]
return json.dumps(node_link_data)
def to_json(self):

View File

@ -72,9 +72,9 @@ class BaseTest(base.BaseTestCase):
edges of each graph.
"""
g1_nodes = g1._g.node
g1_edges = g1._g.edge
g1_edges = g1._g.adj
g2_nodes = g2._g.node
g2_edges = g2._g.edge
g2_edges = g2._g.adj
self.assertEqual(g1.num_vertices(), g2.num_vertices(),
"Two graphs have different amount of nodes")
self.assertEqual(g1.num_edges(), g2.num_edges(),
@ -83,9 +83,10 @@ class BaseTest(base.BaseTestCase):
self.assert_dict_equal(g1_nodes.get(n_id),
g2_nodes.get(n_id),
"Nodes of each graph are not equal")
for e_source_id in g1_edges:
self.assert_dict_equal(g1_edges.get(e_source_id),
g2_edges.get(e_source_id),
self.assert_dict_equal(dict(g1_edges.get(e_source_id)),
dict(g2_edges.get(e_source_id)),
"Edges of each graph are not equal")
@staticmethod