Browse Source

Merge "add test_diff_proj_same_vn_vm_add_delete"

Jenkins 2 years ago
parent
commit
8d697733f2

+ 2
- 0
plugin_test/vapor/requirements.txt View File

@@ -5,3 +5,5 @@ dpath
5 5
 jmespath==0.9.0
6 6
 contextlib2==0.5.4; python_version < '3.2'
7 7
 kazoo==2.2.1
8
+logbook
9
+xmltodict

+ 24
- 3
plugin_test/vapor/vapor/fixtures/contrail.py View File

@@ -1,15 +1,18 @@
1 1
 import os
2
+import six
2 3
 import uuid
4
+import pytest
5
+import logbook
3 6
 
4 7
 import pycontrail.client as client
5
-import pytest
6
-import six
7 8
 from six.moves import configparser
8 9
 from six.moves.urllib import parse
9 10
 
10 11
 from vapor import settings
11 12
 from vapor.helpers import clients
12 13
 
14
+LOGGER = logbook.Logger(__name__)
15
+
13 16
 
14 17
 @pytest.fixture
15 18
 def client_contrail(session, contrail_api_endpoint):
@@ -23,6 +26,15 @@ def client_contrail_analytics(session, contrail_analytics_endpoint):
23 26
                                            contrail_analytics_endpoint)
24 27
 
25 28
 
29
+@pytest.fixture
30
+def client_contrail_vrouter_agent(contrail_vrouter_agent_endpoint):
31
+    LOGGER.debug('VRouter endpoint: {0}'.format(
32
+        contrail_vrouter_agent_endpoint))
33
+    return clients.ContrailVRouterAgentClient(
34
+        agent_ip=contrail_vrouter_agent_endpoint['ip'],
35
+        agent_port=contrail_vrouter_agent_endpoint['port'])
36
+
37
+
26 38
 def get_nodes_fixture(cmd, scope='function'):
27 39
     """Fixtures to gen nodes by cmd factory."""
28 40
 
@@ -77,7 +89,16 @@ def contrail_analytics_endpoint(contrail_api_endpoint):
77 89
     """Return contrail analytics endpoint."""
78 90
     parse_result = parse.urlparse(contrail_api_endpoint)
79 91
     return parse_result._replace(netloc="{}:{}".format(
80
-        parse_result.hostname, settings.CONTAIL_ANALYTICS_PORT)).geturl()
92
+        parse_result.hostname, settings.CONTRAIL_ANALYTICS_PORT)).geturl()
93
+
94
+
95
+@pytest.fixture(scope='module')
96
+def contrail_vrouter_agent_endpoint(contrail_services_http_introspect_ports):
97
+    """Return contrail agent endpoint."""
98
+    service_name = 'contrail-vrouter-agent'
99
+    ip = contrail_services_http_introspect_ports[service_name]['ips'][0]
100
+    port = contrail_services_http_introspect_ports[service_name]['port']
101
+    return {'ip': ip, 'port': port}
81 102
 
82 103
 
83 104
 @pytest.fixture(scope='module')

+ 17
- 10
plugin_test/vapor/vapor/fixtures/different_tenants_resources.py View File

@@ -135,7 +135,7 @@ def project_2(create_user_with_project):
135 135
 
136 136
 
137 137
 @pytest.fixture
138
-def different_tenants_resources(
138
+def different_tenants_resources(request,
139 139
         project_2, credentials, create_user_with_project, cirros_image,
140 140
         sorted_hypervisors, get_network_steps, get_subnet_steps,
141 141
         get_server_steps, port_steps, get_floating_ip_steps, public_flavor,
@@ -149,15 +149,23 @@ def different_tenants_resources(
149 149
     Returns:
150 150
         list: list of AttrDict with created resources
151 151
     """
152
+    default_params = {
153
+        'subnet_cidr': '10.0.0.0/24',
154
+        'base_name': next(utils.generate_ids()),
155
+        'ips': ('10.0.0.11', '10.0.0.21',)
156
+    }
157
+    default_params.update(getattr(request, 'param', {}))
158
+
159
+    subnet_cidr = default_params['subnet_cidr']
160
+    base_name = default_params['base_name']
161
+    ips = default_params['ips']
162
+
152 163
     hypervisor = sorted_hypervisors[0]
153 164
 
154 165
     host = next(
155 166
         host for host in nova_availability_zone_hosts
156 167
         if hypervisor.hypervisor_hostname.startswith(host))
157 168
 
158
-    subnet_cidr = '10.0.0.0/24'
159
-    base_name = next(utils.generate_ids())
160
-
161 169
     with contextlib.ExitStack() as stack:
162 170
 
163 171
         mrg = ResourceManager(stack, base_name, get_network_steps,
@@ -167,16 +175,15 @@ def different_tenants_resources(
167 175
 
168 176
         projects_resources = []
169 177
 
170
-        project_resources = mrg.create(subnet_cidr, '10.0.0.10', cirros_image,
178
+        project_resources = mrg.create(subnet_cidr, ips[0], cirros_image,
171 179
                                        public_flavor, host)
172 180
 
173 181
         projects_resources.append(project_resources)
174 182
 
175 183
         with credentials.change(project_2):
176 184
 
177
-            project_resources = mrg.create(subnet_cidr, '10.0.0.20',
178
-                                           cirros_image, public_flavor, host)
179
-
185
+            project_resources = mrg.create(subnet_cidr, ips[1],
186
+                                           cirros_image, public_flavor,
187
+                                           host)
180 188
             projects_resources.append(project_resources)
181
-
182
-        yield projects_resources
189
+            yield projects_resources

+ 2
- 0
plugin_test/vapor/vapor/helpers/clients/__init__.py View File

@@ -1,7 +1,9 @@
1 1
 from .contrail_api import ContrailClient
2 2
 from .analytics import ContrailAnalyticsClient
3
+from .contrail_agent import ContrailVRouterAgentClient
3 4
 
4 5
 __all__ = [
5 6
     'ContrailClient',
6 7
     'ContrailAnalyticsClient',
8
+    'ContrailVRouterAgentClient',
7 9
 ]

+ 170
- 0
plugin_test/vapor/vapor/helpers/clients/contrail_agent.py View File

@@ -0,0 +1,170 @@
1
+import six
2
+import copy
3
+import xmltodict
4
+from collections import OrderedDict
5
+
6
+from vapor.settings import logger
7
+
8
+if six.PY2:
9
+    from urllib2 import Request, urlopen
10
+else:
11
+    from urllib.request import Request, urlopen
12
+
13
+
14
+__all__ = ['ContrailVRouterAgentClient']
15
+
16
+
17
+class ClientContrailVRouterAgentBase(object):
18
+    def __init__(self, agent_ip, agent_port):
19
+        self.ip = agent_ip
20
+        self.port = agent_port
21
+
22
+    def get_snh_dict_data(self, data):
23
+        key = data.keys()
24
+        if key[0].find(r'__') == 0:
25
+            data = data[key[0]]
26
+        data = self.del_unused_key(data)
27
+        return_dict = {}
28
+        key = data.keys()
29
+        for i in key:
30
+            return_dict[i] = self.get_data(data[i])
31
+        return return_dict
32
+
33
+    def get_resource(self, path):
34
+        url = 'http://%s:%s/%s' % (self.ip, self.port, path)
35
+        req = Request(url)
36
+        try:
37
+            response = urlopen(req)
38
+            xmldata = response.read()
39
+        except Exception as e:
40
+            logger.error('get_xml exception: {} url: {}'.format(e, url))
41
+            raise
42
+        xml_dict = xmltodict.parse(xmldata)
43
+        return xml_dict
44
+
45
+    @staticmethod
46
+    def del_unused_key(data):
47
+        key_list = ['@type', '@identifier', '@size', 'more',
48
+                    'Pagination', 'OvsdbPageResp', 'next_batch']
49
+        return OrderedDict({k: v for (k, v) in data.items()
50
+                            if k not in key_list})
51
+
52
+    def get_data(self, data):
53
+        if isinstance(data, list):
54
+            data_list = []
55
+            for i in data:
56
+                data_dict = self.get_data(i)
57
+                data_list.append(data_dict)
58
+            return_data = data_list
59
+        else:
60
+            if '@type' in data:
61
+                if data['@type'] == 'sandesh':
62
+                    sandesh_dict = {}
63
+                    data = self.del_unused_key(data)
64
+                    key = data.keys()
65
+                    for i in key:
66
+                        sandesh_dict[i] = self.get_data(data[i])
67
+                    return_data = sandesh_dict
68
+                elif data['@type'] == 'list':
69
+                    data = self.del_unused_key(data)
70
+                    key = data.keys()
71
+                    data = data[key[0]]
72
+                    return_data = self.get_data(data)
73
+                elif data['@type'] == 'struct':
74
+                    return_list = []
75
+                    data = self.del_unused_key(data)
76
+                    if len(data) == 0:
77
+                        return ''
78
+                    keys = data.keys()
79
+                    for i in keys:
80
+                        sdata = self.get_data(data[i])
81
+                    return_data = sdata
82
+                elif data['@type'] in ['i64', 'i32', 'i16', 'u64', 'u32',
83
+                                       'u16', 'double', 'string', 'bool']:
84
+                    if '#text' in data:
85
+                        return_data = data['#text']
86
+                    else:
87
+                        return_data = ''
88
+            elif 'element' in data:
89
+                return_data = data['#text']
90
+            else:
91
+                data_dict = {}
92
+                data = self.del_unused_key(data)
93
+                for i in data:
94
+                    data_dict[i] = self.get_data(data[i])
95
+                return_data = data_dict
96
+        return return_data
97
+
98
+    def find_ifmap_list(self, data):
99
+        except_keys = ['@type', '@identifier', '@size',
100
+                       'table_size', 'next_batch', 'more']
101
+        for k in data:
102
+            if not isinstance(data[k], list):
103
+                if k not in except_keys:
104
+                    return self.find_ifmap_list(data[k])
105
+            else:
106
+                temp_list = data[k]
107
+                return copy.copy(temp_list)
108
+
109
+    def merge_ifmap_list(self, data, next_list):
110
+        except_keys = ['@type', '@identifier', '@size', 'table_size',
111
+                       'next_batch', 'more']
112
+        for k in data:
113
+            if not isinstance(data[k], list):
114
+                if k not in except_keys:
115
+                    return self.merge_ifmap_list(data[k], next_list)
116
+            else:
117
+                data[k] += next_list
118
+        return data
119
+
120
+    def get_snhdict(self, path):
121
+        data = self.get_resource(path)
122
+        all_path = ''
123
+        try:
124
+            top_key = data.keys()
125
+            url = data[top_key[0]]['Pagination']['req']['PageReqData']['all']['#text']  # noqa
126
+            all_path = 'Snh_PageReq?x=%s' % url
127
+        except KeyError:
128
+            pass
129
+        try:
130
+            top_key = data.keys()
131
+            url = data[top_key[0]]['OvsdbPageResp']['req']['OvsdbPageRespData']['all']['#text']  # noqa
132
+            all_path = 'Snh_OvsdbPageReq?x=%s' % url
133
+        except KeyError:
134
+            pass
135
+        if all_path != '':
136
+            data = self.get_resource(all_path)
137
+        keys = data.keys()
138
+        if 'next_batch' in data[keys[0]]:
139
+            while True:
140
+                if 'next_batch' in data[keys[0]]:
141
+                    old_data = data.copy()
142
+                    path1 = data[keys[0]]['next_batch']['@link']
143
+                    path2 = data[keys[0]]['next_batch']['#text']
144
+                    path = 'Snh_%s?x=%s' % (path1,path2)
145
+                    data = self.get_resource(path)
146
+                    old_list = self.find_ifmap_list(old_data)
147
+                    self.merge_ifmap_list(data, old_list)
148
+                else:
149
+                    break
150
+        return data
151
+
152
+    def get_path_to_dict(self, path):
153
+        # Return path directory info by dict
154
+        rsp = self.get_snhdict(path)
155
+        snh_data = self.get_snh_dict_data(rsp)
156
+        return snh_data
157
+
158
+
159
+class ContrailVRouterAgentClient(ClientContrailVRouterAgentBase):
160
+
161
+    def get_itfs(self):
162
+        data = self.get_path_to_dict('Snh_ItfReq')
163
+        return data
164
+
165
+    def get_itf_by_name(self, interface_name):
166
+        data = self.get_path_to_dict('Snh_ItfReq?x={}'.format(interface_name))
167
+        return data
168
+
169
+
170
+

+ 1
- 0
plugin_test/vapor/vapor/helpers/clients/contrail_api.py View File

@@ -1,4 +1,5 @@
1 1
 from . import base
2
+import urllib
2 3
 
3 4
 
4 5
 class ContrailClient(base.ContrailBaseClient):

+ 15
- 4
plugin_test/vapor/vapor/settings.py View File

@@ -1,8 +1,18 @@
1 1
 # Project, contrail and OpenStack settings
2 2
 
3 3
 import os
4
-
4
+import sys
5 5
 import yaml
6
+import logbook
7
+
8
+LOG_FILENAME = './vapor.log'
9
+logger = logbook.Logger(__name__)
10
+logger.handlers.append(logbook.FileHandler(LOG_FILENAME,
11
+                                           level='DEBUG',
12
+                                           bubble=True))
13
+logger.handlers.append(logbook.StreamHandler(sys.stderr,
14
+                                             level='DEBUG',
15
+                                             bubble=True))
6 16
 
7 17
 BASE_DIR = os.path.dirname(__file__)
8 18
 
@@ -17,10 +27,11 @@ KEYSTONE_CREDS = {
17 27
 
18 28
 CONTRAIL_CREDS = {'controller_addr': '192.168.1.127'}
19 29
 
20
-CONTAIL_API_PORT = 8082
21
-CONTAIL_ANALYTICS_PORT = 8081
30
+CONTRAIL_ANALYTICS_PORT = 8081
31
+
32
+NEUTRON_CONTRAIL_PLUGIN_CONFIG_PATH = (
33
+    '/etc/neutron/plugins/opencontrail/ContrailPlugin.ini')
22 34
 
23
-NEUTRON_CONTRAIL_PLUGIN_CONFIG_PATH = '/etc/neutron/plugins/opencontrail/ContrailPlugin.ini'  # noqa
24 35
 CONTRAIL_CONFIG_PATH = '/etc/contrail/'
25 36
 
26 37
 # Time between poweroff and start contrail controller node

+ 35
- 0
plugin_test/vapor/vapor/tests/common/test_base.py View File

@@ -27,6 +27,7 @@ from vapor.helpers import asserts
27 27
 from vapor.helpers import contrail_status, policy, connectivity
28 28
 from vapor import settings
29 29
 from vapor.helpers import contrail_status, nodes_steps
30
+from vapor.settings import logger
30 31
 
31 32
 
32 33
 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):
593 594
                                              check=False,
594 595
                                              **port_dict),
595 596
         raises(neutron_exceptions.BadRequest))
597
+
598
+
599
+@pytest.mark.parametrize('different_tenants_resources',
600
+                         [dict(ips=('10.0.0.10', '10.0.0.20'))],
601
+                         indirect=True)
602
+def test_diff_proj_same_vn_vm_add_delete(different_tenants_resources,
603
+                                         client_contrail_vrouter_agent):
604
+    """Test to validate that a VN and VM with the same name and same subnet
605
+    can be created in two different projects.
606
+
607
+    Test steps:
608
+        #. Create 2 different projects.
609
+        #. Create a VN with the same name and subnet under each project.
610
+        #. Launch a VM under the VN in both the projects.
611
+
612
+    Pass criteria:
613
+        The label allocated to the VM's should be different.
614
+    """
615
+    resources = different_tenants_resources
616
+
617
+    itfs = client_contrail_vrouter_agent.get_itfs()['ItfResp'][
618
+        'itf_list']
619
+
620
+    s1_net_label = next(vrif['label'] for vrif in itfs
621
+                        if vrif['vm_uuid'] == resources[0].server.id)
622
+
623
+    s2_net_label = next(vrif['label'] for vrif in itfs
624
+                        if vrif['vm_uuid'] == resources[1].server.id)
625
+
626
+    logger.debug('label1 = {}; label2 = {}'.format(s1_net_label,
627
+                                                   s2_net_label))
628
+
629
+    assert_that(s1_net_label, is_not(equal_to(s2_net_label)))
630
+

Loading…
Cancel
Save