add test_diff_proj_same_vn_vm_add_delete
Change-Id: Ide6dbcec61ee591e56709c068e47e7bfb29b4d36
This commit is contained in:
parent
53de7df81f
commit
429f2ef710
|
@ -5,3 +5,5 @@ dpath
|
|||
jmespath==0.9.0
|
||||
contextlib2==0.5.4; python_version < '3.2'
|
||||
kazoo==2.2.1
|
||||
logbook
|
||||
xmltodict
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
import os
|
||||
import six
|
||||
import uuid
|
||||
import pytest
|
||||
import logbook
|
||||
|
||||
import pycontrail.client as client
|
||||
import pytest
|
||||
import six
|
||||
from six.moves import configparser
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from vapor import settings
|
||||
from vapor.helpers import clients
|
||||
|
||||
LOGGER = logbook.Logger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client_contrail(session, contrail_api_endpoint):
|
||||
|
@ -23,6 +26,15 @@ def client_contrail_analytics(session, contrail_analytics_endpoint):
|
|||
contrail_analytics_endpoint)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client_contrail_vrouter_agent(contrail_vrouter_agent_endpoint):
|
||||
LOGGER.debug('VRouter endpoint: {0}'.format(
|
||||
contrail_vrouter_agent_endpoint))
|
||||
return clients.ContrailVRouterAgentClient(
|
||||
agent_ip=contrail_vrouter_agent_endpoint['ip'],
|
||||
agent_port=contrail_vrouter_agent_endpoint['port'])
|
||||
|
||||
|
||||
def get_nodes_fixture(cmd, scope='function'):
|
||||
"""Fixtures to gen nodes by cmd factory."""
|
||||
|
||||
|
@ -77,7 +89,16 @@ def contrail_analytics_endpoint(contrail_api_endpoint):
|
|||
"""Return contrail analytics endpoint."""
|
||||
parse_result = parse.urlparse(contrail_api_endpoint)
|
||||
return parse_result._replace(netloc="{}:{}".format(
|
||||
parse_result.hostname, settings.CONTAIL_ANALYTICS_PORT)).geturl()
|
||||
parse_result.hostname, settings.CONTRAIL_ANALYTICS_PORT)).geturl()
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def contrail_vrouter_agent_endpoint(contrail_services_http_introspect_ports):
|
||||
"""Return contrail agent endpoint."""
|
||||
service_name = 'contrail-vrouter-agent'
|
||||
ip = contrail_services_http_introspect_ports[service_name]['ips'][0]
|
||||
port = contrail_services_http_introspect_ports[service_name]['port']
|
||||
return {'ip': ip, 'port': port}
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
|
|
|
@ -135,7 +135,7 @@ def project_2(create_user_with_project):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def different_tenants_resources(
|
||||
def different_tenants_resources(request,
|
||||
project_2, credentials, create_user_with_project, cirros_image,
|
||||
sorted_hypervisors, get_network_steps, get_subnet_steps,
|
||||
get_server_steps, port_steps, get_floating_ip_steps, public_flavor,
|
||||
|
@ -149,15 +149,23 @@ def different_tenants_resources(
|
|||
Returns:
|
||||
list: list of AttrDict with created resources
|
||||
"""
|
||||
default_params = {
|
||||
'subnet_cidr': '10.0.0.0/24',
|
||||
'base_name': next(utils.generate_ids()),
|
||||
'ips': ('10.0.0.11', '10.0.0.21',)
|
||||
}
|
||||
default_params.update(getattr(request, 'param', {}))
|
||||
|
||||
subnet_cidr = default_params['subnet_cidr']
|
||||
base_name = default_params['base_name']
|
||||
ips = default_params['ips']
|
||||
|
||||
hypervisor = sorted_hypervisors[0]
|
||||
|
||||
host = next(
|
||||
host for host in nova_availability_zone_hosts
|
||||
if hypervisor.hypervisor_hostname.startswith(host))
|
||||
|
||||
subnet_cidr = '10.0.0.0/24'
|
||||
base_name = next(utils.generate_ids())
|
||||
|
||||
with contextlib.ExitStack() as stack:
|
||||
|
||||
mrg = ResourceManager(stack, base_name, get_network_steps,
|
||||
|
@ -167,16 +175,15 @@ def different_tenants_resources(
|
|||
|
||||
projects_resources = []
|
||||
|
||||
project_resources = mrg.create(subnet_cidr, '10.0.0.10', cirros_image,
|
||||
project_resources = mrg.create(subnet_cidr, ips[0], cirros_image,
|
||||
public_flavor, host)
|
||||
|
||||
projects_resources.append(project_resources)
|
||||
|
||||
with credentials.change(project_2):
|
||||
|
||||
project_resources = mrg.create(subnet_cidr, '10.0.0.20',
|
||||
cirros_image, public_flavor, host)
|
||||
|
||||
project_resources = mrg.create(subnet_cidr, ips[1],
|
||||
cirros_image, public_flavor,
|
||||
host)
|
||||
projects_resources.append(project_resources)
|
||||
|
||||
yield projects_resources
|
||||
yield projects_resources
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
from .contrail_api import ContrailClient
|
||||
from .analytics import ContrailAnalyticsClient
|
||||
from .contrail_agent import ContrailVRouterAgentClient
|
||||
|
||||
__all__ = [
|
||||
'ContrailClient',
|
||||
'ContrailAnalyticsClient',
|
||||
'ContrailVRouterAgentClient',
|
||||
]
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
import six
|
||||
import copy
|
||||
import xmltodict
|
||||
from collections import OrderedDict
|
||||
|
||||
from vapor.settings import logger
|
||||
|
||||
if six.PY2:
|
||||
from urllib2 import Request, urlopen
|
||||
else:
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
|
||||
__all__ = ['ContrailVRouterAgentClient']
|
||||
|
||||
|
||||
class ClientContrailVRouterAgentBase(object):
|
||||
def __init__(self, agent_ip, agent_port):
|
||||
self.ip = agent_ip
|
||||
self.port = agent_port
|
||||
|
||||
def get_snh_dict_data(self, data):
|
||||
key = data.keys()
|
||||
if key[0].find(r'__') == 0:
|
||||
data = data[key[0]]
|
||||
data = self.del_unused_key(data)
|
||||
return_dict = {}
|
||||
key = data.keys()
|
||||
for i in key:
|
||||
return_dict[i] = self.get_data(data[i])
|
||||
return return_dict
|
||||
|
||||
def get_resource(self, path):
|
||||
url = 'http://%s:%s/%s' % (self.ip, self.port, path)
|
||||
req = Request(url)
|
||||
try:
|
||||
response = urlopen(req)
|
||||
xmldata = response.read()
|
||||
except Exception as e:
|
||||
logger.error('get_xml exception: {} url: {}'.format(e, url))
|
||||
raise
|
||||
xml_dict = xmltodict.parse(xmldata)
|
||||
return xml_dict
|
||||
|
||||
@staticmethod
|
||||
def del_unused_key(data):
|
||||
key_list = ['@type', '@identifier', '@size', 'more',
|
||||
'Pagination', 'OvsdbPageResp', 'next_batch']
|
||||
return OrderedDict({k: v for (k, v) in data.items()
|
||||
if k not in key_list})
|
||||
|
||||
def get_data(self, data):
|
||||
if isinstance(data, list):
|
||||
data_list = []
|
||||
for i in data:
|
||||
data_dict = self.get_data(i)
|
||||
data_list.append(data_dict)
|
||||
return_data = data_list
|
||||
else:
|
||||
if '@type' in data:
|
||||
if data['@type'] == 'sandesh':
|
||||
sandesh_dict = {}
|
||||
data = self.del_unused_key(data)
|
||||
key = data.keys()
|
||||
for i in key:
|
||||
sandesh_dict[i] = self.get_data(data[i])
|
||||
return_data = sandesh_dict
|
||||
elif data['@type'] == 'list':
|
||||
data = self.del_unused_key(data)
|
||||
key = data.keys()
|
||||
data = data[key[0]]
|
||||
return_data = self.get_data(data)
|
||||
elif data['@type'] == 'struct':
|
||||
return_list = []
|
||||
data = self.del_unused_key(data)
|
||||
if len(data) == 0:
|
||||
return ''
|
||||
keys = data.keys()
|
||||
for i in keys:
|
||||
sdata = self.get_data(data[i])
|
||||
return_data = sdata
|
||||
elif data['@type'] in ['i64', 'i32', 'i16', 'u64', 'u32',
|
||||
'u16', 'double', 'string', 'bool']:
|
||||
if '#text' in data:
|
||||
return_data = data['#text']
|
||||
else:
|
||||
return_data = ''
|
||||
elif 'element' in data:
|
||||
return_data = data['#text']
|
||||
else:
|
||||
data_dict = {}
|
||||
data = self.del_unused_key(data)
|
||||
for i in data:
|
||||
data_dict[i] = self.get_data(data[i])
|
||||
return_data = data_dict
|
||||
return return_data
|
||||
|
||||
def find_ifmap_list(self, data):
|
||||
except_keys = ['@type', '@identifier', '@size',
|
||||
'table_size', 'next_batch', 'more']
|
||||
for k in data:
|
||||
if not isinstance(data[k], list):
|
||||
if k not in except_keys:
|
||||
return self.find_ifmap_list(data[k])
|
||||
else:
|
||||
temp_list = data[k]
|
||||
return copy.copy(temp_list)
|
||||
|
||||
def merge_ifmap_list(self, data, next_list):
|
||||
except_keys = ['@type', '@identifier', '@size', 'table_size',
|
||||
'next_batch', 'more']
|
||||
for k in data:
|
||||
if not isinstance(data[k], list):
|
||||
if k not in except_keys:
|
||||
return self.merge_ifmap_list(data[k], next_list)
|
||||
else:
|
||||
data[k] += next_list
|
||||
return data
|
||||
|
||||
def get_snhdict(self, path):
|
||||
data = self.get_resource(path)
|
||||
all_path = ''
|
||||
try:
|
||||
top_key = data.keys()
|
||||
url = data[top_key[0]]['Pagination']['req']['PageReqData']['all']['#text'] # noqa
|
||||
all_path = 'Snh_PageReq?x=%s' % url
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
top_key = data.keys()
|
||||
url = data[top_key[0]]['OvsdbPageResp']['req']['OvsdbPageRespData']['all']['#text'] # noqa
|
||||
all_path = 'Snh_OvsdbPageReq?x=%s' % url
|
||||
except KeyError:
|
||||
pass
|
||||
if all_path != '':
|
||||
data = self.get_resource(all_path)
|
||||
keys = data.keys()
|
||||
if 'next_batch' in data[keys[0]]:
|
||||
while True:
|
||||
if 'next_batch' in data[keys[0]]:
|
||||
old_data = data.copy()
|
||||
path1 = data[keys[0]]['next_batch']['@link']
|
||||
path2 = data[keys[0]]['next_batch']['#text']
|
||||
path = 'Snh_%s?x=%s' % (path1,path2)
|
||||
data = self.get_resource(path)
|
||||
old_list = self.find_ifmap_list(old_data)
|
||||
self.merge_ifmap_list(data, old_list)
|
||||
else:
|
||||
break
|
||||
return data
|
||||
|
||||
def get_path_to_dict(self, path):
|
||||
# Return path directory info by dict
|
||||
rsp = self.get_snhdict(path)
|
||||
snh_data = self.get_snh_dict_data(rsp)
|
||||
return snh_data
|
||||
|
||||
|
||||
class ContrailVRouterAgentClient(ClientContrailVRouterAgentBase):
|
||||
|
||||
def get_itfs(self):
|
||||
data = self.get_path_to_dict('Snh_ItfReq')
|
||||
return data
|
||||
|
||||
def get_itf_by_name(self, interface_name):
|
||||
data = self.get_path_to_dict('Snh_ItfReq?x={}'.format(interface_name))
|
||||
return data
|
||||
|
||||
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
from . import base
|
||||
import urllib
|
||||
|
||||
|
||||
class ContrailClient(base.ContrailBaseClient):
|
||||
|
|
|
@ -1,8 +1,18 @@
|
|||
# Project, contrail and OpenStack settings
|
||||
|
||||
import os
|
||||
|
||||
import sys
|
||||
import yaml
|
||||
import logbook
|
||||
|
||||
LOG_FILENAME = './vapor.log'
|
||||
logger = logbook.Logger(__name__)
|
||||
logger.handlers.append(logbook.FileHandler(LOG_FILENAME,
|
||||
level='DEBUG',
|
||||
bubble=True))
|
||||
logger.handlers.append(logbook.StreamHandler(sys.stderr,
|
||||
level='DEBUG',
|
||||
bubble=True))
|
||||
|
||||
BASE_DIR = os.path.dirname(__file__)
|
||||
|
||||
|
@ -17,10 +27,11 @@ KEYSTONE_CREDS = {
|
|||
|
||||
CONTRAIL_CREDS = {'controller_addr': '192.168.1.127'}
|
||||
|
||||
CONTAIL_API_PORT = 8082
|
||||
CONTAIL_ANALYTICS_PORT = 8081
|
||||
CONTRAIL_ANALYTICS_PORT = 8081
|
||||
|
||||
NEUTRON_CONTRAIL_PLUGIN_CONFIG_PATH = (
|
||||
'/etc/neutron/plugins/opencontrail/ContrailPlugin.ini')
|
||||
|
||||
NEUTRON_CONTRAIL_PLUGIN_CONFIG_PATH = '/etc/neutron/plugins/opencontrail/ContrailPlugin.ini' # noqa
|
||||
CONTRAIL_CONFIG_PATH = '/etc/contrail/'
|
||||
|
||||
# Time between poweroff and start contrail controller node
|
||||
|
|
|
@ -27,6 +27,7 @@ from vapor.helpers import asserts
|
|||
from vapor.helpers import contrail_status, policy, connectivity
|
||||
from vapor import settings
|
||||
from vapor.helpers import contrail_status, nodes_steps
|
||||
from vapor.settings import logger
|
||||
|
||||
|
||||
def test_network_deleting_with_server(network, server, contrail_api_client):
|
||||
|
@ -593,3 +594,37 @@ def test_update_vm_ip(server, subnet, port_steps, server_steps):
|
|||
check=False,
|
||||
**port_dict),
|
||||
raises(neutron_exceptions.BadRequest))
|
||||
|
||||
|
||||
@pytest.mark.parametrize('different_tenants_resources',
|
||||
[dict(ips=('10.0.0.10', '10.0.0.20'))],
|
||||
indirect=True)
|
||||
def test_diff_proj_same_vn_vm_add_delete(different_tenants_resources,
|
||||
client_contrail_vrouter_agent):
|
||||
"""Test to validate that a VN and VM with the same name and same subnet
|
||||
can be created in two different projects.
|
||||
|
||||
Test steps:
|
||||
#. Create 2 different projects.
|
||||
#. Create a VN with the same name and subnet under each project.
|
||||
#. Launch a VM under the VN in both the projects.
|
||||
|
||||
Pass criteria:
|
||||
The label allocated to the VM's should be different.
|
||||
"""
|
||||
resources = different_tenants_resources
|
||||
|
||||
itfs = client_contrail_vrouter_agent.get_itfs()['ItfResp'][
|
||||
'itf_list']
|
||||
|
||||
s1_net_label = next(vrif['label'] for vrif in itfs
|
||||
if vrif['vm_uuid'] == resources[0].server.id)
|
||||
|
||||
s2_net_label = next(vrif['label'] for vrif in itfs
|
||||
if vrif['vm_uuid'] == resources[1].server.id)
|
||||
|
||||
logger.debug('label1 = {}; label2 = {}'.format(s1_net_label,
|
||||
s2_net_label))
|
||||
|
||||
assert_that(s1_net_label, is_not(equal_to(s2_net_label)))
|
||||
|
||||
|
|
Loading…
Reference in New Issue