Added tests for multi tenancy

When a different tenant queries the topology, it should not get
instances that were created by the default tenant.

Change-Id: I239198ee33a8512e607776b3aa98b00c4a81f0e8
This commit is contained in:
Ifat Afek
2018-03-26 07:08:47 +00:00
parent cc7547df67
commit 80515d0b2a
3 changed files with 138 additions and 0 deletions
@@ -110,6 +110,40 @@ class TestTopology(BaseTopologyTest):
finally:
self._rollback_to_default()
@utils.tempest_logger
def test_default_graph_for_tenant(self):
"""default_graph
This test validate correctness of default topology graph when queried
by another tenant.
"""
try:
# Action - create entities as the default tenant
self._create_entities(num_instances=self.NUM_INSTANCE,
num_volumes=self.NUM_VOLUME)
# Calculate expected results for another tenant - the other tenant
# should not see instances and volumes of the default tenant.
# All it can see is its private network.
tenant_client = self.vitrage_client_for_demo_user
api_graph = tenant_client.topology.get(all_tenants=False)
graph = self._create_graph_from_graph_dictionary(api_graph)
entities = self._entities_validation_data(
cluster_entities=0, cluster_edges=0, zone_entities=0,
zone_edges=0, host_entities=0, host_edges=0,
instance_entities=0, instance_edges=0, volume_entities=0,
volume_edges=0)
num_entities = self.num_demo_tenant_networks
# Test Assertions
self._validate_graph_correctness(graph, num_entities, 0, entities)
except Exception as e:
self._handle_exception(e)
raise
finally:
self._rollback_to_default()
@utils.tempest_logger
def test_graph_with_query(self):
"""graph_with_query
@@ -146,6 +180,38 @@ class TestTopology(BaseTopologyTest):
finally:
self._rollback_to_default()
@utils.tempest_logger
def test_graph_with_query_for_tenant(self):
"""graph_with_query
This test validate correctness of topology graph
with query, when queried by another tenant.
"""
try:
# Action - create entities as the default tenant
self._create_entities(num_instances=self.NUM_INSTANCE,
num_volumes=self.NUM_VOLUME)
# Calculate expected results - the other tenant should not see
# instances and volumes of the default tenant
tenant_client = self.vitrage_client_for_demo_user
api_graph = tenant_client.topology.get(query=self._graph_query())
graph = self._create_graph_from_graph_dictionary(api_graph)
entities = self._entities_validation_data(
cluster_entities=0, cluster_edges=0, zone_entities=0,
zone_edges=0, host_entities=0, host_edges=0,
instance_entities=0, instance_edges=0, volume_entities=0,
volume_edges=0)
# Test Assertions
self._validate_graph_correctness(graph, 0, 0, entities)
except Exception as e:
self._handle_exception(e)
raise
finally:
self._rollback_to_default()
@utils.tempest_logger
def test_nova_tree(self):
"""nova_tree
+26
View File
@@ -59,6 +59,10 @@ class BaseVitrageTempest(base.BaseTestCase):
NUM_VERTICES_PER_TYPE = 'num_vertices'
NUM_EDGES_PER_TYPE = 'num_edges_per_type'
DEMO_USERNAME = 'demo'
DEMO_USER_DOMAIN_ID = 'default'
DEMO_PROJECT_NAME = 'demo'
DEMO_PROJECT_DOMAIN_ID = 'default'
def assert_list_equal(self, l1, l2):
if tuple(sys.version_info)[0:2] < (2, 7):
@@ -121,12 +125,17 @@ class BaseVitrageTempest(base.BaseTestCase):
cls.conf = service.prepare_service([])
TempestClients.class_init(cls.conf)
cls.vitrage_client = TempestClients.vitrage()
cls.vitrage_client_for_demo_user = \
TempestClients.vitrage_client_for_user(
cls.DEMO_USERNAME, cls.DEMO_USER_DOMAIN_ID,
cls.DEMO_PROJECT_NAME, cls.DEMO_PROJECT_DOMAIN_ID)
cls.num_default_networks = \
len(TempestClients.neutron().list_networks()['networks'])
cls.num_default_ports = 0
cls.num_default_entities = 3
cls.num_default_edges = 2
cls.num_demo_tenant_networks = cls._calc_num_demo_tenant_networks()
def _create_graph_from_graph_dictionary(self, api_graph):
self.assertIsNotNone(api_graph)
@@ -302,3 +311,20 @@ class BaseVitrageTempest(base.BaseTestCase):
traceback.print_exc()
LOG.exception(exception)
self._print_entity_graph()
@classmethod
def _calc_num_demo_tenant_networks(cls):
neutron_client = TempestClients.neutron_client_for_user(
cls.DEMO_USERNAME, cls.DEMO_USER_DOMAIN_ID,
cls.DEMO_PROJECT_NAME, cls.DEMO_PROJECT_DOMAIN_ID)
tenant_networks = neutron_client.list_networks(
tenant_id=cls._get_demo_tenant_id())['networks']
return len(tenant_networks)
@classmethod
def _get_demo_tenant_id(cls):
projects = TempestClients.keystone().projects.list()
for project in projects:
if cls.DEMO_PROJECT_NAME == project.name:
return project.id
return None
@@ -12,8 +12,12 @@
# License for the specific language governing permissions and limitations
# under the License.
from keystoneauth1 import loading as ka_loading
from keystoneauth1 import session as ka_session
from neutronclient.v2_0 import client as neutron_client
from vitrage import keystone_client
from vitrage import os_clients
from vitrage_tempest_plugin.tests.utils import get_property_value
from vitrageclient import client as vc
@@ -30,6 +34,7 @@ class TempestClients(object):
cls._heat = None
cls._mistral = None
cls._aodh = None
cls._keystone = None
@classmethod
def vitrage(cls):
@@ -42,6 +47,24 @@ class TempestClients(object):
'1', session=keystone_client.get_session(cls._conf))
return cls._vitrage
@classmethod
def vitrage_client_for_user(cls, username, user_domain_id,
project_name, project_domain_id):
"""vitrage client for a specific user and tenant
:rtype: vitrageclient.v1.client.Client
"""
session = cls._get_session_for_user(
username, user_domain_id, project_name, project_domain_id)
return vc.Client('1', session=session)
@classmethod
def neutron_client_for_user(cls, username, user_domain_id,
project_name, project_domain_id):
session = cls._get_session_for_user(
username, user_domain_id, project_name, project_domain_id)
return neutron_client.Client(session=session)
@classmethod
def ceilometer(cls):
"""ceilometer client
@@ -121,3 +144,26 @@ class TempestClients(object):
if not cls._aodh:
cls._aodh = os_clients.aodh_client(cls._conf)
return cls._aodh
@classmethod
def keystone(cls):
"""keystone client
:rtype: keystoneclient.v3.client.Client
"""
if not cls._keystone:
cls._keystone = keystone_client.get_client(cls._conf)
return cls._keystone
@classmethod
def _get_session_for_user(cls, username, user_domain_id,
project_name, project_domain_id):
password = get_property_value(
'OS_PASSWORD', 'password', 'password', cls._conf)
loader = ka_loading.get_plugin_loader('password')
auth_plugin = loader.load_from_options(
auth_url=cls._conf.service_credentials.auth_url,
username=username, password=password, project_name=project_name,
project_domain_id=project_domain_id,
user_domain_id=user_domain_id)
return ka_session.Session(auth=auth_plugin)