vitrage/vitrage_tempest_tests/tests/api/base.py
Eyal 2b6fc051cf make tempest work under py3
use the -E for sudo when running testr
this will pass the PYTHON environment variable
so python3 will run

Change-Id: I231090694fafb8dcc71c9595174ba82185b59348
2017-08-10 21:31:16 +03:00

395 lines
15 KiB
Python

# 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.
import time
import traceback
from oslo_log import log as logging
from oslotest import base
from six.moves import filter
from vitrage.common.constants import EdgeProperties
from vitrage.common.constants import EntityCategory
from vitrage.common.constants import VertexProperties as VProps
from vitrage.datasources.aodh import AODH_DATASOURCE
from vitrage.datasources.cinder.volume import CINDER_VOLUME_DATASOURCE
from vitrage.datasources.heat.stack import HEAT_STACK_DATASOURCE
from vitrage.datasources.neutron.network import NEUTRON_NETWORK_DATASOURCE
from vitrage.datasources.neutron.port import NEUTRON_PORT_DATASOURCE
from vitrage.datasources import NOVA_HOST_DATASOURCE
from vitrage.datasources import NOVA_INSTANCE_DATASOURCE
from vitrage.datasources import NOVA_ZONE_DATASOURCE
from vitrage.datasources import OPENSTACK_CLUSTER
from vitrage.datasources.static_physical import SWITCH
from vitrage.graph.driver.networkx_graph import NXGraph
from vitrage.graph import Edge
from vitrage.graph import Vertex
from vitrage import keystone_client
from vitrage import os_clients
from vitrage import service
import vitrage_tempest_tests.tests.utils as utils
from vitrageclient import client as v_client
LOG = logging.getLogger(__name__)
class BaseApiTest(base.BaseTestCase):
"""Base test class for Vitrage API tests."""
NUM_VERTICES_PER_TYPE = 'num_vertices'
NUM_EDGES_PER_TYPE = 'num_edges_per_type'
# noinspection PyPep8Naming
@classmethod
def setUpClass(cls):
super(BaseApiTest, cls).setUpClass()
cls.conf = service.prepare_service([])
cls.vitrage_client = \
v_client.Client('1', session=keystone_client.get_session(cls.conf))
cls.nova_client = cls._create_client(os_clients.nova_client, cls.conf)
cls.cinder_client = cls._create_client(os_clients.cinder_client,
cls.conf)
cls.glance_client = cls._create_client(os_clients.glance_client,
cls.conf)
cls.neutron_client = cls._create_client(os_clients.neutron_client,
cls.conf)
cls.heat_client = cls._create_client(os_clients.heat_client, cls.conf)
cls.num_default_networks = \
len(cls.neutron_client.list_networks()['networks'])
cls.num_default_ports = \
len(cls.neutron_client.list_ports()['ports'])
cls.num_default_entities = 3
cls.num_default_edges = 2
@staticmethod
def _create_client(client_func, conf):
count = 0
while count < 40:
LOG.info("wait_for_client - " + client_func.__name__)
client = client_func(conf)
if client:
return client
count += 1
time.sleep(5)
LOG.info("wait_for_client - False")
return None
@staticmethod
def _filter_list_by_pairs_parameters(origin_list,
keys, values):
filtered_list = []
for item in origin_list:
verification = 0
for index in range(len(keys)):
if utils.uni2str(item[keys[index]]) == values[index]:
verification += 1
else:
break
if verification == len(keys):
filtered_list.append(item)
return filtered_list
def _create_volume_and_attach(self, name, size, instance_id, mount_point):
volume = self.cinder_client.volumes.create(name=name,
size=size)
time.sleep(2)
self.cinder_client.volumes.attach(volume=volume,
instance_uuid=instance_id,
mountpoint=mount_point)
self._wait_for_status(30,
self._check_num_volumes,
num_volumes=1,
state='in-use')
time.sleep(2)
return volume
def _get_host(self):
topology = self.vitrage_client.topology.get(all_tenants=True)
host = filter(
lambda item: item[VProps.VITRAGE_TYPE] == NOVA_HOST_DATASOURCE,
topology['nodes'])
return next(host)
def _create_instances(self, num_instances, set_public_network=False):
kwargs = {}
flavors_list = self.nova_client.flavors.list()
images_list = self.glance_client.images.list()
if set_public_network:
public_net = self._get_public_network()
if public_net:
kwargs.update({"networks": [{'uuid': public_net['id']}]})
img = images_list.next()
resources = [self.nova_client.servers.create(
name='%s-%s' % ('vm', index),
flavor=flavors_list[0],
image=img,
**kwargs) for index in range(num_instances)]
self._wait_for_status(30,
self._check_num_instances,
num_instances=num_instances,
state='active')
time.sleep(2)
return resources
def _delete_instances(self):
instances = self.nova_client.servers.list()
for instance in instances:
try:
self.nova_client.servers.delete(instance)
except Exception:
pass
self._wait_for_status(30,
self._check_num_instances,
num_instances=0)
time.sleep(2)
def _delete_volumes(self):
volumes = self.cinder_client.volumes.list()
for volume in volumes:
try:
self.cinder_client.volumes.detach(volume)
self.cinder_client.volumes.force_delete(volume)
except Exception:
self.cinder_client.volumes.force_delete(volume)
self._wait_for_status(30,
self._check_num_volumes,
num_volumes=0)
time.sleep(2)
def _check_num_instances(self, num_instances=0, state=''):
if len(self.nova_client.servers.list()) != num_instances:
return False
return all(instance.__dict__['status'].upper() == state.upper()
for instance in self.nova_client.servers.list())
def _check_num_volumes(self, num_volumes=0, state=''):
if len(self.cinder_client.volumes.list()) != num_volumes:
return False
return all(volume.__dict__['status'].upper() == state.upper() and
len(volume.__dict__['attachments']) == 1
for volume in self.cinder_client.volumes.list())
def _create_graph_from_graph_dictionary(self, api_graph):
self.assertIsNotNone(api_graph)
graph = NXGraph()
nodes = api_graph['nodes']
for i in range(len(nodes)):
graph.add_vertex(Vertex(str(i), nodes[i]))
edges = api_graph['links']
for i in range(len(edges)):
graph.add_edge(Edge(str(edges[i]['source']),
str(edges[i]['target']),
edges[i][EdgeProperties.RELATIONSHIP_TYPE]))
return graph
def _create_graph_from_tree_dictionary(self,
api_graph,
graph=None,
ancestor=None):
children = []
graph = NXGraph() if not graph else graph
if 'children' in api_graph:
children = api_graph.copy()['children']
del api_graph['children']
vertex = Vertex(api_graph[VProps.VITRAGE_ID], api_graph)
graph.add_vertex(vertex)
if ancestor:
graph.add_edge(Edge(ancestor[VProps.VITRAGE_ID],
vertex[VProps.VITRAGE_ID],
'label'))
for entity in children:
self._create_graph_from_tree_dictionary(entity, graph, vertex)
return graph
@staticmethod
def _wait_for_status(max_waiting, func, **kwargs):
count = 0
while count < max_waiting:
if func(**kwargs):
return True
count += 1
time.sleep(2)
LOG.info("wait_for_status - False")
return False
def _entities_validation_data(self, **kwargs):
validation_data = []
# openstack.cluster
props = {VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_TYPE: OPENSTACK_CLUSTER,
self.NUM_VERTICES_PER_TYPE: kwargs.get('cluster_entities', 1),
self.NUM_EDGES_PER_TYPE: kwargs.get('cluster_edges', 1)}
validation_data.append(props)
# nova.zone
props = {VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_TYPE: NOVA_ZONE_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get('zone_entities', 1),
self.NUM_EDGES_PER_TYPE: kwargs.get('zone_edges', 2)}
validation_data.append(props)
# nova.host
props = {VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_TYPE: NOVA_HOST_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get('host_entities', 1),
self.NUM_EDGES_PER_TYPE: kwargs.get('host_edges', 1)}
validation_data.append(props)
# nova.instance
props = {VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_TYPE: NOVA_INSTANCE_DATASOURCE,
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.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_TYPE: CINDER_VOLUME_DATASOURCE,
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.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_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.VITRAGE_CATEGORY: EntityCategory.ALARM,
VProps.VITRAGE_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
if kwargs.get('network_entities') is not None:
props = {VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_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
if kwargs.get('port_entities') is not None:
props = {VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_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)
# heat.stack
props = {VProps.VITRAGE_CATEGORY: EntityCategory.RESOURCE,
VProps.VITRAGE_TYPE: HEAT_STACK_DATASOURCE,
self.NUM_VERTICES_PER_TYPE: kwargs.get(
'stack_entities', 0),
self.NUM_EDGES_PER_TYPE: kwargs.get(
'stack_edges', 0)}
validation_data.append(props)
return validation_data
def _validate_graph_correctness(self,
graph,
num_entities,
num_edges,
entities):
self.assertIsNotNone(graph)
self.assertIsNotNone(entities)
for entity in entities:
query = {
VProps.VITRAGE_CATEGORY: entity[VProps.VITRAGE_CATEGORY],
VProps.VITRAGE_TYPE: entity[VProps.VITRAGE_TYPE],
VProps.VITRAGE_IS_DELETED: False,
VProps.VITRAGE_IS_PLACEHOLDER: False
}
vertices = graph.get_vertices(vertex_attr_filter=query)
self.assertEqual(entity[self.NUM_VERTICES_PER_TYPE],
len(vertices),
'%s%s' % ('Num vertices is incorrect for: ',
entity[VProps.VITRAGE_TYPE]))
entity_num_edges = sum([len(graph.get_edges(vertex.vertex_id))
for vertex in vertices])
self.assertEqual(entity[self.NUM_EDGES_PER_TYPE],
entity_num_edges,
'%s%s' % ('Num edges is incorrect for: ',
entity[VProps.VITRAGE_TYPE]))
self.assertEqual(num_entities, graph.num_vertices())
self.assertEqual(num_edges, graph.num_edges())
@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'])
try:
return next(public_nets)
except StopIteration:
return None
def _print_entity_graph(self):
api_graph = self.vitrage_client.topology.get(all_tenants=True)
graph = self._create_graph_from_graph_dictionary(api_graph)
LOG.info('Entity Graph: \n%s', graph.json_output_graph())
def _handle_exception(self, exception):
traceback.print_exc()
LOG.exception(exception)
self._print_entity_graph()