add neutron test and fix bug 1593447: vitrage topology show doesn't show all the graph for type graph

Change-Id: I751734d2dc3656a54d0a9cec8d64ea30521b8a87
This commit is contained in:
Marina Koushnir 2016-06-22 09:26:05 +00:00
parent 7a8e1edb3b
commit b313967793
4 changed files with 287 additions and 57 deletions
vitrage_tempest_tests/tests/api

@ -57,6 +57,7 @@ class BaseApiTest(base.BaseTestCase):
v_client.Client('1', session=keystone_client.get_session(cls.conf))
cls.nova_client = clients.nova_client(cls.conf)
cls.cinder_client = clients.cinder_client(cls.conf)
cls.neutron_client = clients.neutron_client(cls.conf)
@staticmethod
def _filter_list_by_pairs_parameters(origin_list,
@ -96,14 +97,20 @@ class BaseApiTest(base.BaseTestCase):
topology['nodes'])
return host[0]
def _create_instances(self, num_instances):
def _create_instances(self, num_instances, set_public_network=False):
kwargs = {}
flavors_list = self.nova_client.flavors.list()
images_list = self.nova_client.images.list()
if set_public_network:
public_net = self._get_public_network()
if public_net:
kwargs.update({"networks": [{'uuid': public_net['id']}]})
resources = [self.nova_client.servers.create(
name='%s-%s' % ('vm', index),
flavor=flavors_list[0],
image=images_list[0]) for index in range(num_instances)]
image=images_list[0],
**kwargs) for index in range(num_instances)]
self._wait_for_status(30,
self._check_num_instances,
@ -234,45 +241,60 @@ class BaseApiTest(base.BaseTestCase):
# nova.instance
props = {VProps.CATEGORY: EntityCategory.RESOURCE,
VProps.TYPE: NOVA_INSTANCE_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get('instance_entities',
0),
self.NUM_EDGES_PER_TYPE: kwargs.get('instance_edges', 0)}
self.NUM_VERTICES_PER_TYPE: kwargs.get(
'instance_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get(
'instance_edges', 0)}
validation_data.append(props)
# cinder.volume
props = {VProps.CATEGORY: EntityCategory.RESOURCE,
VProps.TYPE: CINDER_VOLUME_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get('volume_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get('volume_edges', 0)}
self.NUM_VERTICES_PER_TYPE: kwargs.get(
'volume_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get(
'volume_edges', 0)}
validation_data.append(props)
# switch
props = {VProps.CATEGORY: EntityCategory.RESOURCE,
VProps.TYPE: SWITCH,
self.NUM_VERTICES_PER_TYPE: kwargs.get('switch_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get('switch_edges', 0)}
validation_data.append(props)
if kwargs.get('switch_entities') is not None:
props = {VProps.CATEGORY: EntityCategory.RESOURCE,
VProps.TYPE: SWITCH,
self.NUM_VERTICES_PER_TYPE: kwargs.get(
'switch_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get(
'switch_edges', 0)}
validation_data.append(props)
# aodh
props = {VProps.CATEGORY: EntityCategory.ALARM,
VProps.TYPE: AODH_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get('aodh_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get('aodh_edges', 0)}
validation_data.append(props)
if kwargs.get('aodh_entities') is not None:
props = {VProps.CATEGORY: EntityCategory.ALARM,
VProps.TYPE: AODH_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get(
'aodh_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get(
'aodh_edges', 0)}
validation_data.append(props)
# neutron.network
props = {VProps.CATEGORY: EntityCategory.RESOURCE,
VProps.TYPE: NEUTRON_NETWORK_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get('network_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get('network_edges', 0)}
validation_data.append(props)
if kwargs.get('network_entities') is not None:
props = {VProps.CATEGORY: EntityCategory.RESOURCE,
VProps.TYPE: NEUTRON_NETWORK_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get(
'network_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get(
'network_edges', 0)}
validation_data.append(props)
# neutron.port
props = {VProps.CATEGORY: EntityCategory.RESOURCE,
VProps.TYPE: NEUTRON_PORT_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get('port_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get('port_edges', 0)}
validation_data.append(props)
if kwargs.get('port_entities') is not None:
props = {VProps.CATEGORY: EntityCategory.RESOURCE,
VProps.TYPE: NEUTRON_PORT_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get(
'port_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get(
'port_edges', 0)}
validation_data.append(props)
return validation_data
@ -309,3 +331,12 @@ class BaseApiTest(base.BaseTestCase):
@staticmethod
def _get_value(item, key):
return utils.uni2str(item[key])
def _get_public_network(self):
networks = self.neutron_client.list_networks()
public_nets = filter(
lambda item: self._get_value(item, VProps.NAME) == 'public',
networks['networks'])
if not public_nets:
return None
return public_nets[0]

@ -0,0 +1,100 @@
# Copyright 2016 - Nokia
#
# 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.
from oslo_log import log as logging
from vitrage.common.constants import VertexProperties as VProps
from vitrage_tempest_tests.tests.api.topology.base import BaseTopologyTest
LOG = logging.getLogger(__name__)
INSTANCE_NUM = 3
class TestNeutronNetwork(BaseTopologyTest):
@classmethod
def setUpClass(cls):
super(TestNeutronNetwork, cls).setUpClass()
def test_neutron(self):
"""neutron test
This test validate correctness topology graph with neutron module
"""
try:
# create entities
instances = self._create_instances(
num_instances=INSTANCE_NUM, set_public_network=True)
network_list = self.neutron_client.list_networks()['networks']
port_list = self.neutron_client.list_ports()['ports']
network_name = self._get_network_name(instances[0], network_list)
port_to_inst_edges = self._port_to_inst_edges(
instances, network_name, port_list)
port_to_network_edges = self._port_to_network_edges(
network_list, port_list)
api_graph = self.vitrage_client.topology.get()
graph = self._create_graph_from_graph_dictionary(api_graph)
entities = self._entities_validation_data(
host_entities=1,
host_edges=1 + INSTANCE_NUM,
instance_entities=INSTANCE_NUM,
instance_edges=INSTANCE_NUM + port_to_inst_edges,
network_entities=len(network_list),
network_edges=port_to_network_edges,
port_entities=len(port_list),
port_edges=port_to_inst_edges + port_to_network_edges)
expected_entities = \
3 + INSTANCE_NUM + len(network_list) + len(port_list)
expected_edges = \
2 + INSTANCE_NUM + port_to_inst_edges + port_to_network_edges
self._validate_graph_correctness(
graph, expected_entities, expected_edges, entities)
except Exception as e:
LOG.exception(e)
finally:
self._delete_instances()
@staticmethod
def _get_network_name(instance, networks):
for network in networks:
try:
if len(instance.networks[network[VProps.NAME]]) > 0:
return network[VProps.NAME]
except Exception:
pass
return None
@staticmethod
def _port_to_inst_edges(instances, network_name, ports):
counter = 0
for vm in instances:
for port in ports:
ips_number = 0
for vm_ip in vm.addresses[network_name]:
for port_ip in port['fixed_ips']:
if vm_ip['addr'] == port_ip['ip_address']:
ips_number += 1
break
if ips_number == len(vm.addresses[network_name]):
counter += 1
break
return counter
def _port_to_network_edges(self, networks, ports):
counter = 0
for net in networks:
counter += len(self._filter_list_by_pairs_parameters(
ports, ['network_id'], [net['id']]))
return counter

@ -33,7 +33,8 @@ class BaseTopologyTest(BaseApiTest):
def _rollback_to_default(self):
self._delete_entities()
api_graph = self.vitrage_client.topology.get()
api_graph = self.vitrage_client.topology.get(
limit=4, root='RESOURCE:openstack.cluster')
graph = self._create_graph_from_graph_dictionary(api_graph)
entities = self._entities_validation_data()
self._validate_graph_correctness(graph, 3, 2, entities)

@ -19,6 +19,8 @@ import vitrage_tempest_tests.tests.utils as utils
from vitrageclient.exc import ClientException
LOG = logging.getLogger(__name__)
NUM_INSTANCE = 3
NUM_VOLUME = 1
NOVA_QUERY = '{"and": [{"==": {"category": "RESOURCE"}},' \
'{"==": {"is_deleted": false}},' \
'{"==": {"is_placeholder": false}},' \
@ -34,43 +36,71 @@ class TestTopology(BaseTopologyTest):
@classmethod
def setUpClass(cls):
super(TestTopology, cls).setUpClass()
cls.default_networks = \
len(cls.neutron_client.list_networks()['networks'])
cls.default_ports = \
len(cls.neutron_client.list_ports()['ports'])
def test_compare_api_and_cli(self):
"""Wrapper that returns a test graph."""
"""compare_api_and_cli
This test validate correctness of topology graph:
cli via api
"""
api_graph = self.vitrage_client.topology.get()
cli_graph = utils.run_vitrage_command('vitrage topology show',
self.conf)
self._compare_graphs(api_graph, cli_graph)
def test_default_graph(self):
"""default_graph
This test validate correctness of default topology graph
"""
try:
# create entities
self._create_entities(num_instances=3, num_volumes=1)
self._create_entities(num_instances=NUM_INSTANCE,
num_volumes=NUM_VOLUME)
api_graph = self.vitrage_client.topology.get()
self.assertIsNotNone(api_graph)
graph = self._create_graph_from_graph_dictionary(api_graph)
entities = self._entities_validation_data(
host_entities=1, host_edges=4,
instance_entities=3, instance_edges=4,
volume_entities=1, volume_edges=1)
self._validate_graph_correctness(graph, 7, 6, entities)
host_entities=1,
host_edges=NUM_INSTANCE + 1,
instance_entities=NUM_INSTANCE,
instance_edges=2 * NUM_INSTANCE + NUM_VOLUME,
volume_entities=NUM_VOLUME,
volume_edges=NUM_VOLUME)
self._validate_graph_correctness(
graph,
3 + 2 * NUM_INSTANCE + NUM_VOLUME +
self.default_networks + self.default_ports,
2 + 3 * NUM_INSTANCE + NUM_VOLUME + self.default_ports,
entities)
except Exception as e:
LOG.exception(e)
finally:
self._rollback_to_default()
def test_graph_with_query(self):
"""graph_with_query
This test validate correctness of topology graph
with query
"""
try:
# create entities
self._create_entities(num_instances=3, num_volumes=1)
self._create_entities(num_instances=NUM_INSTANCE,
num_volumes=NUM_VOLUME)
api_graph = self.vitrage_client.topology.get(
query=self._graph_query())
self.assertIsNotNone(api_graph)
graph = self._create_graph_from_graph_dictionary(api_graph)
entities = self._entities_validation_data(
host_entities=1, host_edges=4,
instance_entities=3, instance_edges=3)
host_entities=1,
host_edges=NUM_INSTANCE + 1,
instance_entities=NUM_INSTANCE,
instance_edges=NUM_INSTANCE)
self._validate_graph_correctness(graph, 6, 5, entities)
except Exception as e:
LOG.exception(e)
@ -78,16 +108,23 @@ class TestTopology(BaseTopologyTest):
self._rollback_to_default()
def test_nova_tree(self):
"""nova_tree
This test validate correctness of topology tree
"""
try:
# create entities
self._create_entities(num_instances=3, num_volumes=1)
api_graph = self.vitrage_client.topology.get(graph_type='tree',
query=NOVA_QUERY)
self._create_entities(num_instances=NUM_INSTANCE,
num_volumes=NUM_VOLUME)
api_graph = self.vitrage_client.topology.get(
graph_type='tree', query=NOVA_QUERY)
self.assertIsNotNone(api_graph)
graph = self._create_graph_from_tree_dictionary(api_graph)
entities = self._entities_validation_data(
host_entities=1, host_edges=4,
instance_entities=3, instance_edges=3)
host_entities=1,
host_edges=NUM_INSTANCE + 1,
instance_entities=NUM_INSTANCE,
instance_edges=NUM_INSTANCE)
self._validate_graph_correctness(graph, 6, 5, entities)
except Exception as e:
LOG.exception(e)
@ -95,9 +132,14 @@ class TestTopology(BaseTopologyTest):
self._rollback_to_default()
def test_tree_with_query(self):
"""tree_with_query
This test validate correctness of topology tree
with query
"""
try:
# create entities
self._create_entities(num_instances=3)
self._create_entities(num_instances=NUM_INSTANCE)
api_graph = self.vitrage_client.topology.get(
graph_type='tree', query=self._tree_query())
self.assertIsNotNone(api_graph)
@ -111,9 +153,14 @@ class TestTopology(BaseTopologyTest):
self._rollback_to_default()
def test_tree_with_depth_exclude_instance(self):
"""tree_with_query
This test validate correctness of topology tree
with query
"""
try:
# create entities
self._create_entities(num_instances=3)
self._create_entities(num_instances=NUM_INSTANCE)
api_graph = self.vitrage_client.topology.get(
limit=2, graph_type='tree', query=NOVA_QUERY)
self.assertIsNotNone(api_graph)
@ -121,55 +168,91 @@ class TestTopology(BaseTopologyTest):
entities = self._entities_validation_data(
host_entities=1, host_edges=1)
self._validate_graph_correctness(graph, 3, 2, entities)
except Exception as e:
LOG.exception(e)
finally:
self._rollback_to_default()
def test_tree_with_depth_include_instance(self):
"""tree_with_query
This test validate correctness of topology tree
with query
"""
try:
# create entities
self._create_entities(num_instances=3)
self._create_entities(num_instances=NUM_INSTANCE)
api_graph = self.vitrage_client.topology.get(
limit=3, graph_type='tree', query=NOVA_QUERY)
self.assertIsNotNone(api_graph)
graph = self._create_graph_from_tree_dictionary(api_graph)
entities = self._entities_validation_data(
host_entities=1, host_edges=4,
instance_entities=3, instance_edges=3)
host_entities=1,
host_edges=NUM_INSTANCE + 1,
instance_entities=NUM_INSTANCE,
instance_edges=NUM_INSTANCE)
self._validate_graph_correctness(graph, 6, 5, entities)
except Exception as e:
LOG.exception(e)
finally:
self._rollback_to_default()
def test_graph_with_root_and_depth_exclude_instance(self):
"""tree_with_query
This test validate correctness of topology graph
with root and depth exclude instance
"""
try:
# create entities
self._create_entities(num_instances=3)
self._create_entities(num_instances=NUM_INSTANCE)
api_graph = self.vitrage_client.topology.get(
limit=2, root="RESOURCE:openstack.cluster")
limit=2, root='RESOURCE:openstack.cluster')
self.assertIsNotNone(api_graph)
graph = self._create_graph_from_graph_dictionary(api_graph)
entities = self._entities_validation_data(
host_entities=1, host_edges=1)
self._validate_graph_correctness(graph, 3, 2, entities)
except Exception as e:
LOG.exception(e)
finally:
self._rollback_to_default()
def test_graph_with_root_and_depth_include_instance(self):
"""graph_with_root_and_depth_include_instance
This test validate correctness of topology graph
with root and depth include instance
"""
try:
# create entities
self._create_entities(num_instances=3, num_volumes=1)
self._create_entities(num_instances=NUM_INSTANCE,
num_volumes=NUM_VOLUME)
api_graph = self.vitrage_client.topology.get(
limit=4, root="RESOURCE:openstack.cluster")
limit=4, root='RESOURCE:openstack.cluster')
self.assertIsNotNone(api_graph)
graph = self._create_graph_from_graph_dictionary(api_graph)
entities = self._entities_validation_data(
host_entities=1, host_edges=4,
instance_entities=3, instance_edges=4,
volume_entities=1, volume_edges=1)
self._validate_graph_correctness(graph, 7, 6, entities)
host_entities=1,
host_edges=NUM_INSTANCE + 1,
instance_entities=NUM_INSTANCE,
instance_edges=NUM_INSTANCE + NUM_VOLUME,
volume_entities=NUM_VOLUME,
volume_edges=NUM_VOLUME)
self._validate_graph_correctness(
graph, 3 + NUM_INSTANCE + NUM_VOLUME,
2 + NUM_INSTANCE + NUM_VOLUME, entities)
except Exception as e:
LOG.exception(e)
finally:
self._rollback_to_default()
def test_graph_with_depth_and_no_root(self):
"""graph_with_depth_and_no_root
This test validate correctness of topology
graph with depth and without root
"""
try:
# create entities
self._create_entities(num_instances=3, num_volumes=1)
@ -183,9 +266,15 @@ class TestTopology(BaseTopologyTest):
self._rollback_to_default()
def test_graph_with_no_match_query(self):
"""graph_with_no_match_query
This test validate correctness of topology graph
with no match query
"""
try:
# create entities
self._create_entities(num_instances=3, num_volumes=1)
self._create_entities(num_instances=NUM_INSTANCE,
num_volumes=NUM_VOLUME)
api_graph = self.vitrage_client.topology.get(
query=self._graph_no_match_query())
self.assertEqual(
@ -194,15 +283,24 @@ class TestTopology(BaseTopologyTest):
self.assertEqual(
0,
len(api_graph['links']), 'num of edges')
except Exception as e:
LOG.exception(e)
finally:
self._rollback_to_default()
def test_tree_with_no_match_query(self):
"""tree_with_no_match_query
This test validate correctness of topology tree
with no match query
"""
try:
# create entities
self._create_entities(num_instances=3)
self._create_entities(num_instances=NUM_INSTANCE)
api_graph = self.vitrage_client.topology.get(
graph_type='tree', query=self._tree_no_match_query())
self.assertEqual({}, api_graph)
except Exception as e:
LOG.exception(e)
finally:
self._rollback_to_default()