blob: b5a108ad020632fe07e91186c530d52ad29710ab [file] [log] [blame]
Botond Zoltáne0b7aa12017-03-28 08:42:16 +02001# Copyright (c) 2017 Ericsson.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import copy
16import yaml
17
18from heat_integrationtests.functional import functional_base
19
20
21test_template = '''
22heat_template_version: pike
23description: Test template to create, update, delete trunk.
24resources:
25 parent_net:
26 type: OS::Neutron::Net
27 trunk_net_one:
28 type: OS::Neutron::Net
29 trunk_net_two:
30 type: OS::Neutron::Net
31 parent_subnet:
32 type: OS::Neutron::Subnet
33 properties:
34 network: { get_resource: parent_net }
35 cidr: 10.0.0.0/16
36 trunk_subnet_one:
37 type: OS::Neutron::Subnet
38 properties:
39 network: { get_resource: trunk_net_one }
40 cidr: 10.10.0.0/16
41 trunk_subnet_two:
42 type: OS::Neutron::Subnet
43 properties:
44 network: { get_resource: trunk_net_two }
45 cidr: 10.20.0.0/16
46 parent_port:
47 type: OS::Neutron::Port
48 properties:
49 network: { get_resource: parent_net }
50 name: trunk_parent_port
51 sub_port_one:
52 type: OS::Neutron::Port
53 properties:
54 network: { get_resource: trunk_net_one }
55 name: trunk_sub_port_one
56 sub_port_two:
57 type: OS::Neutron::Port
58 properties:
59 network: { get_resource: trunk_net_two }
60 name: trunk_sub_port_two
61 trunk:
62 type: OS::Neutron::Trunk
63 properties:
64 name: test_trunk
65 port: { get_resource: parent_port }
66 sub_ports:
67outputs:
68 trunk_parent_port:
69 value: { get_attr: [trunk, port_id] }
70'''
71
72
73class UpdateTrunkTest(functional_base.FunctionalTestsBase):
74
75 @staticmethod
76 def _sub_ports_dict_to_set(sub_ports):
77 new_sub_ports = copy.deepcopy(sub_ports)
78
79 # NOTE(lajos katona): In the template we have to give the sub port as
80 # port, but from trunk_details we receive back them with port_id.
81 # As an extra trunk_details contains the mac_address as well which is
82 # useless here.
83 # So here we have to make sure that the dictionary (input from
84 # template or output from trunk_details) have the same keys:
85 if any('mac_address' in d for d in new_sub_ports):
86 for sp in new_sub_ports:
87 sp['port'] = sp['port_id']
88 del sp['port_id']
89 del sp['mac_address']
90
91 # NOTE(lajos katona): We receive lists (trunk_details['sub_ports'] and
92 # the input to the template) and we can't be sure that the order is the
93 # same, so by using sets we can compare them.
94 sub_ports_set = {frozenset(d.items()) for d in new_sub_ports}
95 return sub_ports_set
96
97 def test_add_first_sub_port(self):
98 stack_identifier = self.stack_create(template=test_template)
99
100 parsed_template = yaml.safe_load(test_template)
101 new_sub_port = [{'port': {'get_resource': 'sub_port_one'},
102 'segmentation_id': 10,
103 'segmentation_type': 'vlan'}]
104 parsed_template['resources']['trunk']['properties'][
105 'sub_ports'] = new_sub_port
106 updated_template = yaml.safe_dump(parsed_template)
107 self.update_stack(stack_identifier, updated_template)
108
109 # Fix the port_id in the template for assertion
110 new_sub_port[0]['port'] = self.get_physical_resource_id(
111 stack_identifier, 'sub_port_one')
112 parent_id = self.get_stack_output(
113 stack_identifier, 'trunk_parent_port')
114 parent_port = self.network_client.show_port(parent_id)['port']
115 trunk_sub_port = parent_port['trunk_details']['sub_ports']
116
117 self.assertEqual(self._sub_ports_dict_to_set(new_sub_port),
118 self._sub_ports_dict_to_set(trunk_sub_port))
119
120 def test_add_a_second_sub_port(self):
121 parsed_template = yaml.safe_load(test_template)
122 sub_ports = [{'port': {'get_resource': 'sub_port_one'},
123 'segmentation_type': 'vlan',
124 'segmentation_id': 10}, ]
125 parsed_template['resources']['trunk']['properties'][
126 'sub_ports'] = sub_ports
127 template_with_sub_ports = yaml.safe_dump(parsed_template)
128
129 stack_identifier = self.stack_create(template=template_with_sub_ports)
130
131 new_sub_port = {'port': {'get_resource': 'sub_port_two'},
132 'segmentation_id': 20,
133 'segmentation_type': 'vlan'}
134 parsed_template['resources']['trunk']['properties'][
135 'sub_ports'].append(new_sub_port)
136
137 updated_template = yaml.safe_dump(parsed_template)
138
139 self.update_stack(stack_identifier, updated_template)
140
141 # Fix the port_ids in the templates for assertion
142 sub_ports[0]['port'] = self.get_physical_resource_id(
143 stack_identifier, 'sub_port_one')
144 new_sub_port['port'] = self.get_physical_resource_id(
145 stack_identifier, 'sub_port_two')
146 expected_sub_ports = [sub_ports[0], new_sub_port]
147
148 parent_id = self.get_stack_output(
149 stack_identifier, 'trunk_parent_port')
150 parent_port = self.network_client.show_port(parent_id)['port']
151 trunk_sub_ports = parent_port['trunk_details']['sub_ports']
152
153 self.assertEqual(self._sub_ports_dict_to_set(expected_sub_ports),
154 self._sub_ports_dict_to_set(trunk_sub_ports))
155
156 def test_remove_sub_port_from_trunk(self):
157 sub_ports = [{'port': {'get_resource': 'sub_port_one'},
158 'segmentation_type': 'vlan',
159 'segmentation_id': 10},
160 {'port': {'get_resource': 'sub_port_two'},
161 'segmentation_type': 'vlan',
162 'segmentation_id': 20}]
163 parsed_template = yaml.safe_load(test_template)
164 parsed_template['resources']['trunk']['properties'][
165 'sub_ports'] = sub_ports
166 template_with_sub_ports = yaml.safe_dump(parsed_template)
167
168 stack_identifier = self.stack_create(template=template_with_sub_ports)
169
170 sub_port_to_be_removed = {'port': {'get_resource': 'sub_port_two'},
171 'segmentation_type': 'vlan',
172 'segmentation_id': 20}
173 parsed_template['resources']['trunk'][
174 'properties']['sub_ports'].remove(sub_port_to_be_removed)
175 updated_template = yaml.safe_dump(parsed_template)
176
177 self.update_stack(stack_identifier, updated_template)
178
179 # Fix the port_ids in the templates for assertion
180 sub_ports[0]['port'] = self.get_physical_resource_id(
181 stack_identifier, 'sub_port_one')
182 expected_sub_ports = [sub_ports[0]]
183
184 parent_id = self.get_stack_output(
185 stack_identifier, 'trunk_parent_port')
186 parent_port = self.network_client.show_port(parent_id)['port']
187 trunk_sub_ports = parent_port['trunk_details']['sub_ports']
188
189 self.assertEqual(self._sub_ports_dict_to_set(expected_sub_ports),
190 self._sub_ports_dict_to_set(trunk_sub_ports))
191
192 def test_remove_last_sub_port_from_trunk(self):
193 sub_ports = [{'port': {'get_resource': 'sub_port_one'},
194 'segmentation_type': 'vlan',
195 'segmentation_id': 10}]
196 parsed_template = yaml.safe_load(test_template)
197 parsed_template['resources']['trunk']['properties'][
198 'sub_ports'] = sub_ports
199
200 template_with_sub_ports = yaml.safe_dump(parsed_template)
201 stack_identifier = self.stack_create(template=template_with_sub_ports)
202
203 sub_port_to_be_removed = {'port': {'get_resource': 'sub_port_one'},
204 'segmentation_type': 'vlan',
205 'segmentation_id': 10}
206
207 parsed_template['resources']['trunk'][
208 'properties']['sub_ports'] = []
209 updated_template = yaml.safe_dump(parsed_template)
210
211 self.update_stack(stack_identifier, updated_template)
212
213 sub_port_to_be_removed['port'] = self.get_physical_resource_id(
214 stack_identifier, 'sub_port_one')
215 parent_id = self.get_stack_output(
216 stack_identifier, 'trunk_parent_port')
217 parent_port = self.network_client.show_port(parent_id)['port']
218 trunk_sub_ports = parent_port['trunk_details']['sub_ports']
219
220 self.assertNotEqual(
221 self._sub_ports_dict_to_set([sub_port_to_be_removed]),
222 self._sub_ports_dict_to_set(trunk_sub_ports))
223 self.assertFalse(trunk_sub_ports,
224 'The returned sub ports (%s) in trunk_details is '
225 'not empty!' % trunk_sub_ports)
226
227 def test_update_existing_sub_port_on_trunk(self):
228 sub_ports = [{'port': {'get_resource': 'sub_port_one'},
229 'segmentation_type': 'vlan',
230 'segmentation_id': 10}]
231 parsed_template = yaml.safe_load(test_template)
232 parsed_template['resources']['trunk']['properties'][
233 'sub_ports'] = sub_ports
234
235 template_with_sub_ports = yaml.safe_dump(parsed_template)
236 stack_identifier = self.stack_create(template=template_with_sub_ports)
237
238 sub_port_id = self.get_physical_resource_id(
239 stack_identifier, 'sub_port_one')
240 parsed_template['resources']['trunk']['properties']['sub_ports'][0][
241 'segmentation_id'] = 99
242 updated_template = yaml.safe_dump(parsed_template)
243
244 self.update_stack(stack_identifier, updated_template)
245 updated_sub_port = {'port': sub_port_id,
246 'segmentation_type': 'vlan',
247 'segmentation_id': 99}
248 parent_id = self.get_stack_output(
249 stack_identifier, 'trunk_parent_port')
250 parent_port = self.network_client.show_port(parent_id)['port']
251 trunk_sub_ports = parent_port['trunk_details']['sub_ports']
252
253 self.assertEqual(self._sub_ports_dict_to_set([updated_sub_port]),
254 self._sub_ports_dict_to_set(trunk_sub_ports))
255
256 def test_update_trunk_name_and_description(self):
257 new_name = 'pineapple'
258 new_description = 'This is a test trunk'
259
260 stack_identifier = self.stack_create(template=test_template)
261 parsed_template = yaml.safe_load(test_template)
262 parsed_template['resources']['trunk']['properties']['name'] = new_name
263 parsed_template['resources']['trunk']['properties'][
264 'description'] = new_description
265 updated_template = yaml.safe_dump(parsed_template)
266 self.update_stack(stack_identifier, template=updated_template)
267
268 parent_id = self.get_stack_output(
269 stack_identifier, 'trunk_parent_port')
270 parent_port = self.network_client.show_port(parent_id)['port']
271 trunk_id = parent_port['trunk_details']['trunk_id']
272
273 trunk = self.network_client.show_trunk(trunk_id)['trunk']
274 self.assertEqual(new_name, trunk['name'])
275 self.assertEqual(new_description, trunk['description'])