Feature 10960 Performance optimizations for the polling of VM status in RO
[osm/RO.git] / RO-VIM-openstack / osm_rovim_openstack / tests / test_vimconn_openstack.py
1 # -*- coding: utf-8 -*-
2
3 ##
4 # Copyright 2017 Intel Corporation.
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
16 # under the License.
17 #
18 # For those usages not covered by the Apache License, Version 2.0 please
19 # contact with: nfvlabs@tid.es
20 ##
21
22 """
23 This module contains unit tests for the OpenStack VIM connector
24 Run this directly with python2 or python3.
25 """
26 import copy
27 from copy import deepcopy
28 import logging
29 import unittest
30
31 import mock
32 from mock import MagicMock, patch
33 from neutronclient.v2_0.client import Client
34 from novaclient import exceptions as nvExceptions
35 from novaclient.exceptions import ClientException, Conflict
36 from osm_ro_plugin import vimconn
37 from osm_ro_plugin.vimconn import (
38 VimConnConnectionException,
39 VimConnException,
40 VimConnNotFoundException,
41 )
42 from osm_rovim_openstack.vimconn_openstack import vimconnector
43
44 __author__ = "Igor D.C."
45 __date__ = "$23-aug-2017 23:59:59$"
46
47 # Variables Used in TestNewVmInstance Class
48 name = "basicvm"
49 description = "my firewall"
50 start = True
51 image_id = "408b73-e9cc-5a6a-t270-82cc4811bd4a"
52 flavor_id = "208b73-e9cc-5a6a-t270-82cc4811bd4a"
53 affinity_group_list = []
54 net_list = []
55 cloud_config = {}
56 disk_list = []
57 disk_list2 = [
58 {"size": 10, "image_id": image_id},
59 {"size": 20},
60 ]
61 availability_zone_index = 0
62 availability_zone_list = ["nova"]
63 floating_network_vim_id = "108b73-e9cc-5a6a-t270-82cc4811bd4a"
64 net_id = "83372685-f67f-49fd-8722-eabb7692fc22"
65 net2_id = "46472685-f67f-49fd-8722-eabb7692fc22"
66 mac_address = "00:00:5e:00:53:af"
67 port_id = "03372685-f67f-49fd-8722-eabb7692fc22"
68 time_return_value = 156570000
69 port2_id = "17472685-f67f-49fd-8722-eabb7692fc22"
70 root_vol_id = "tc408b73-r9cc-5a6a-a270-82cc4811bd4a"
71 ip_addr1 = "20.3.4.5"
72 volume_id = "ac408b73-b9cc-4a6a-a270-82cc4811bd4a"
73 volume_id2 = "o4e0e83-b9uu-4akk-a234-89cc4811bd4a"
74 volume_id3 = "44e0e83-t9uu-4akk-a234-p9cc4811bd4a"
75 virtual_mac_id = "64e0e83-t9uu-4akk-a234-p9cc4811bd4a"
76 created_items_all_true = {
77 f"floating_ip:{floating_network_vim_id}": True,
78 f"volume:{volume_id}": True,
79 f"port:{port_id}": True,
80 }
81
82
83 # Variables used in TestNewFlavor Class
84 name1 = "sample-flavor"
85 extended = (
86 {
87 "cpu-quota": {"limit": 3},
88 "mem-quota": {"limit": 1},
89 "mempage-size": "LARGE",
90 "cpu-pinning-policy": "DEDICATED",
91 "mem-policy": "STRICT",
92 },
93 )
94 flavor_data = {
95 "name": name1,
96 "ram": 3,
97 "vcpus": 8,
98 "disk": 50,
99 "extended": extended,
100 }
101
102 flavor_data2 = {
103 "name": name1,
104 "ram": 3,
105 "vcpus": 8,
106 "disk": 50,
107 }
108
109
110 class TestSfcOperations(unittest.TestCase):
111 @mock.patch("logging.getLogger", autospec=True)
112 def setUp(self, mock_logger):
113 # Instantiate dummy VIM connector so we can test it
114 # It throws exception because of dummy parameters,
115 # We are disabling the logging of exception not to print them to console.
116 mock_logger = logging.getLogger()
117 mock_logger.disabled = True
118 self.vimconn = vimconnector(
119 "123",
120 "openstackvim",
121 "456",
122 "789",
123 "http://dummy.url",
124 None,
125 "user",
126 "pass",
127 )
128
129 def _test_new_sfi(
130 self,
131 create_sfc_port_pair,
132 sfc_encap,
133 ingress_ports=["5311c75d-d718-4369-bbda-cdcc6da60fcc"],
134 egress_ports=["230cdf1b-de37-4891-bc07-f9010cf1f967"],
135 ):
136 # input to VIM connector
137 name = "osm_sfi"
138 # + ingress_ports
139 # + egress_ports
140 # TODO(igordc): must be changed to NSH in Queens (MPLS is a workaround)
141 correlation = "nsh"
142 if sfc_encap is not None:
143 if not sfc_encap:
144 correlation = None
145
146 # what OpenStack is assumed to respond (patch OpenStack"s return value)
147 dict_from_neutron = {
148 "port_pair": {
149 "id": "3d7ddc13-923c-4332-971e-708ed82902ce",
150 "name": name,
151 "description": "",
152 "tenant_id": "130b1e97-b0f1-40a8-8804-b6ad9b8c3e0c",
153 "project_id": "130b1e97-b0f1-40a8-8804-b6ad9b8c3e0c",
154 "ingress": ingress_ports[0] if len(ingress_ports) else None,
155 "egress": egress_ports[0] if len(egress_ports) else None,
156 "service_function_parameters": {"correlation": correlation},
157 }
158 }
159 create_sfc_port_pair.return_value = dict_from_neutron
160
161 # what the VIM connector is expected to
162 # send to OpenStack based on the input
163 dict_to_neutron = {
164 "port_pair": {
165 "name": name,
166 "ingress": "5311c75d-d718-4369-bbda-cdcc6da60fcc",
167 "egress": "230cdf1b-de37-4891-bc07-f9010cf1f967",
168 "service_function_parameters": {"correlation": correlation},
169 }
170 }
171
172 # call the VIM connector
173 if sfc_encap is None:
174 result = self.vimconn.new_sfi(name, ingress_ports, egress_ports)
175 else:
176 result = self.vimconn.new_sfi(name, ingress_ports, egress_ports, sfc_encap)
177
178 # assert that the VIM connector made the expected call to OpenStack
179 create_sfc_port_pair.assert_called_with(dict_to_neutron)
180 # assert that the VIM connector had the expected result / return value
181 self.assertEqual(result, dict_from_neutron["port_pair"]["id"])
182
183 def _test_new_sf(self, create_sfc_port_pair_group):
184 # input to VIM connector
185 name = "osm_sf"
186 instances = [
187 "bbd01220-cf72-41f2-9e70-0669c2e5c4cd",
188 "12ba215e-3987-4892-bd3a-d0fd91eecf98",
189 "e25a7c79-14c8-469a-9ae1-f601c9371ffd",
190 ]
191
192 # what OpenStack is assumed to respond (patch OpenStack"s return value)
193 dict_from_neutron = {
194 "port_pair_group": {
195 "id": "3d7ddc13-923c-4332-971e-708ed82902ce",
196 "name": name,
197 "description": "",
198 "tenant_id": "130b1e97-b0f1-40a8-8804-b6ad9b8c3e0c",
199 "project_id": "130b1e97-b0f1-40a8-8804-b6ad9b8c3e0c",
200 "port_pairs": instances,
201 "group_id": 1,
202 "port_pair_group_parameters": {
203 "lb_fields": [],
204 "ppg_n_tuple_mapping": {
205 "ingress_n_tuple": {},
206 "egress_n_tuple": {},
207 },
208 },
209 }
210 }
211 create_sfc_port_pair_group.return_value = dict_from_neutron
212
213 # what the VIM connector is expected to
214 # send to OpenStack based on the input
215 dict_to_neutron = {
216 "port_pair_group": {
217 "name": name,
218 "port_pairs": [
219 "bbd01220-cf72-41f2-9e70-0669c2e5c4cd",
220 "12ba215e-3987-4892-bd3a-d0fd91eecf98",
221 "e25a7c79-14c8-469a-9ae1-f601c9371ffd",
222 ],
223 }
224 }
225
226 # call the VIM connector
227 result = self.vimconn.new_sf(name, instances)
228
229 # assert that the VIM connector made the expected call to OpenStack
230 create_sfc_port_pair_group.assert_called_with(dict_to_neutron)
231 # assert that the VIM connector had the expected result / return value
232 self.assertEqual(result, dict_from_neutron["port_pair_group"]["id"])
233
234 def _test_new_sfp(self, create_sfc_port_chain, sfc_encap, spi):
235 # input to VIM connector
236 name = "osm_sfp"
237 classifications = [
238 "2bd2a2e5-c5fd-4eac-a297-d5e255c35c19",
239 "00f23389-bdfa-43c2-8b16-5815f2582fa8",
240 ]
241 sfs = [
242 "2314daec-c262-414a-86e3-69bb6fa5bc16",
243 "d8bfdb5d-195e-4f34-81aa-6135705317df",
244 ]
245
246 # TODO(igordc): must be changed to NSH in Queens (MPLS is a workaround)
247 correlation = "nsh"
248 chain_id = 33
249 if spi:
250 chain_id = spi
251
252 # what OpenStack is assumed to respond (patch OpenStack"s return value)
253 dict_from_neutron = {
254 "port_chain": {
255 "id": "5bc05721-079b-4b6e-a235-47cac331cbb6",
256 "name": name,
257 "description": "",
258 "tenant_id": "130b1e97-b0f1-40a8-8804-b6ad9b8c3e0c",
259 "project_id": "130b1e97-b0f1-40a8-8804-b6ad9b8c3e0c",
260 "chain_id": chain_id,
261 "flow_classifiers": classifications,
262 "port_pair_groups": sfs,
263 "chain_parameters": {"correlation": correlation},
264 }
265 }
266 create_sfc_port_chain.return_value = dict_from_neutron
267
268 # what the VIM connector is expected to
269 # send to OpenStack based on the input
270 dict_to_neutron = {
271 "port_chain": {
272 "name": name,
273 "flow_classifiers": [
274 "2bd2a2e5-c5fd-4eac-a297-d5e255c35c19",
275 "00f23389-bdfa-43c2-8b16-5815f2582fa8",
276 ],
277 "port_pair_groups": [
278 "2314daec-c262-414a-86e3-69bb6fa5bc16",
279 "d8bfdb5d-195e-4f34-81aa-6135705317df",
280 ],
281 "chain_parameters": {"correlation": correlation},
282 }
283 }
284 if spi:
285 dict_to_neutron["port_chain"]["chain_id"] = spi
286
287 # call the VIM connector
288 if sfc_encap is None:
289 dict_to_neutron["port_chain"]["chain_parameters"] = {"correlation": "mpls"}
290 if spi is None:
291 result = self.vimconn.new_sfp(
292 name, classifications, sfs, sfc_encap=False
293 )
294 else:
295 result = self.vimconn.new_sfp(
296 name, classifications, sfs, sfc_encap=False, spi=spi
297 )
298 else:
299 if spi is None:
300 result = self.vimconn.new_sfp(name, classifications, sfs, sfc_encap)
301 else:
302 result = self.vimconn.new_sfp(
303 name, classifications, sfs, sfc_encap, spi
304 )
305
306 # assert that the VIM connector made the expected call to OpenStack
307 create_sfc_port_chain.assert_called_with(dict_to_neutron)
308 # assert that the VIM connector had the expected result / return value
309 self.assertEqual(result, dict_from_neutron["port_chain"]["id"])
310
311 def _test_new_classification(self, create_sfc_flow_classifier, ctype):
312 # input to VIM connector
313 name = "osm_classification"
314 definition = {
315 "ethertype": "IPv4",
316 "logical_source_port": "aaab0ab0-1452-4636-bb3b-11dca833fa2b",
317 "protocol": "tcp",
318 "source_ip_prefix": "192.168.2.0/24",
319 "source_port_range_max": 99,
320 "source_port_range_min": 50,
321 }
322
323 # what OpenStack is assumed to respond (patch OpenStack"s return value)
324 dict_from_neutron = {"flow_classifier": copy.copy(definition)}
325 dict_from_neutron["flow_classifier"][
326 "id"
327 ] = "7735ec2c-fddf-4130-9712-32ed2ab6a372"
328 dict_from_neutron["flow_classifier"]["name"] = name
329 dict_from_neutron["flow_classifier"]["description"] = ""
330 dict_from_neutron["flow_classifier"][
331 "tenant_id"
332 ] = "130b1e97-b0f1-40a8-8804-b6ad9b8c3e0c"
333 dict_from_neutron["flow_classifier"][
334 "project_id"
335 ] = "130b1e97-b0f1-40a8-8804-b6ad9b8c3e0c"
336 create_sfc_flow_classifier.return_value = dict_from_neutron
337
338 # what the VIM connector is expected to
339 # send to OpenStack based on the input
340 dict_to_neutron = {"flow_classifier": copy.copy(definition)}
341 dict_to_neutron["flow_classifier"]["name"] = "osm_classification"
342
343 # call the VIM connector
344 result = self.vimconn.new_classification(name, ctype, definition)
345
346 # assert that the VIM connector made the expected call to OpenStack
347 create_sfc_flow_classifier.assert_called_with(dict_to_neutron)
348 # assert that the VIM connector had the expected result / return value
349 self.assertEqual(result, dict_from_neutron["flow_classifier"]["id"])
350
351 @mock.patch.object(Client, "create_sfc_flow_classifier")
352 def test_new_classification(self, create_sfc_flow_classifier):
353 self._test_new_classification(
354 create_sfc_flow_classifier, "legacy_flow_classifier"
355 )
356
357 @mock.patch.object(Client, "create_sfc_flow_classifier")
358 def test_new_classification_unsupported_type(self, create_sfc_flow_classifier):
359 self.assertRaises(
360 vimconn.VimConnNotSupportedException,
361 self._test_new_classification,
362 create_sfc_flow_classifier,
363 "h265",
364 )
365
366 @mock.patch.object(Client, "create_sfc_port_pair")
367 def test_new_sfi_with_sfc_encap(self, create_sfc_port_pair):
368 self._test_new_sfi(create_sfc_port_pair, True)
369
370 @mock.patch.object(Client, "create_sfc_port_pair")
371 def test_new_sfi_without_sfc_encap(self, create_sfc_port_pair):
372 self._test_new_sfi(create_sfc_port_pair, False)
373
374 @mock.patch.object(Client, "create_sfc_port_pair")
375 def test_new_sfi_default_sfc_encap(self, create_sfc_port_pair):
376 self._test_new_sfi(create_sfc_port_pair, None)
377
378 @mock.patch.object(Client, "create_sfc_port_pair")
379 def test_new_sfi_bad_ingress_ports(self, create_sfc_port_pair):
380 ingress_ports = [
381 "5311c75d-d718-4369-bbda-cdcc6da60fcc",
382 "a0273f64-82c9-11e7-b08f-6328e53f0fa7",
383 ]
384 self.assertRaises(
385 vimconn.VimConnNotSupportedException,
386 self._test_new_sfi,
387 create_sfc_port_pair,
388 True,
389 ingress_ports=ingress_ports,
390 )
391 ingress_ports = []
392 self.assertRaises(
393 vimconn.VimConnNotSupportedException,
394 self._test_new_sfi,
395 create_sfc_port_pair,
396 True,
397 ingress_ports=ingress_ports,
398 )
399
400 @mock.patch.object(Client, "create_sfc_port_pair")
401 def test_new_sfi_bad_egress_ports(self, create_sfc_port_pair):
402 egress_ports = [
403 "230cdf1b-de37-4891-bc07-f9010cf1f967",
404 "b41228fe-82c9-11e7-9b44-17504174320b",
405 ]
406 self.assertRaises(
407 vimconn.VimConnNotSupportedException,
408 self._test_new_sfi,
409 create_sfc_port_pair,
410 True,
411 egress_ports=egress_ports,
412 )
413 egress_ports = []
414 self.assertRaises(
415 vimconn.VimConnNotSupportedException,
416 self._test_new_sfi,
417 create_sfc_port_pair,
418 True,
419 egress_ports=egress_ports,
420 )
421
422 @mock.patch.object(vimconnector, "get_sfi")
423 @mock.patch.object(Client, "create_sfc_port_pair_group")
424 def test_new_sf(self, create_sfc_port_pair_group, get_sfi):
425 get_sfi.return_value = {"sfc_encap": True}
426 self._test_new_sf(create_sfc_port_pair_group)
427
428 @mock.patch.object(vimconnector, "get_sfi")
429 @mock.patch.object(Client, "create_sfc_port_pair_group")
430 def test_new_sf_inconsistent_sfc_encap(self, create_sfc_port_pair_group, get_sfi):
431 get_sfi.return_value = {"sfc_encap": "nsh"}
432 self.assertRaises(
433 vimconn.VimConnNotSupportedException,
434 self._test_new_sf,
435 create_sfc_port_pair_group,
436 )
437
438 @mock.patch.object(Client, "create_sfc_port_chain")
439 def test_new_sfp_with_sfc_encap(self, create_sfc_port_chain):
440 self._test_new_sfp(create_sfc_port_chain, True, None)
441
442 @mock.patch.object(Client, "create_sfc_port_chain")
443 def test_new_sfp_without_sfc_encap(self, create_sfc_port_chain):
444 self._test_new_sfp(create_sfc_port_chain, None, None)
445 self._test_new_sfp(create_sfc_port_chain, None, 25)
446
447 @mock.patch.object(Client, "create_sfc_port_chain")
448 def test_new_sfp_default_sfc_encap(self, create_sfc_port_chain):
449 self._test_new_sfp(create_sfc_port_chain, None, None)
450
451 @mock.patch.object(Client, "create_sfc_port_chain")
452 def test_new_sfp_with_sfc_encap_spi(self, create_sfc_port_chain):
453 self._test_new_sfp(create_sfc_port_chain, True, 25)
454
455 @mock.patch.object(Client, "create_sfc_port_chain")
456 def test_new_sfp_default_sfc_encap_spi(self, create_sfc_port_chain):
457 self._test_new_sfp(create_sfc_port_chain, None, 25)
458
459 @mock.patch.object(Client, "list_sfc_flow_classifiers")
460 def test_get_classification_list(self, list_sfc_flow_classifiers):
461 # what OpenStack is assumed to return to the VIM connector
462 list_sfc_flow_classifiers.return_value = {
463 "flow_classifiers": [
464 {
465 "source_port_range_min": 2000,
466 "destination_ip_prefix": "192.168.3.0/24",
467 "protocol": "udp",
468 "description": "",
469 "ethertype": "IPv4",
470 "l7_parameters": {},
471 "source_port_range_max": 2000,
472 "destination_port_range_min": 3000,
473 "source_ip_prefix": "192.168.2.0/24",
474 "logical_destination_port": None,
475 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
476 "destination_port_range_max": None,
477 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
478 "logical_source_port": "aaab0ab0-1452-4636-bb3b-11dca833fa2b",
479 "id": "22198366-d4e8-4d6b-b4d2-637d5d6cbb7d",
480 "name": "fc1",
481 }
482 ]
483 }
484
485 # call the VIM connector
486 filter_dict = {"protocol": "tcp", "ethertype": "IPv4"}
487 result = self.vimconn.get_classification_list(filter_dict.copy())
488
489 # assert that VIM connector called OpenStack with the expected filter
490 list_sfc_flow_classifiers.assert_called_with(**filter_dict)
491 # assert that the VIM connector successfully
492 # translated and returned the OpenStack result
493 self.assertEqual(
494 result,
495 [
496 {
497 "id": "22198366-d4e8-4d6b-b4d2-637d5d6cbb7d",
498 "name": "fc1",
499 "description": "",
500 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
501 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
502 "ctype": "legacy_flow_classifier",
503 "definition": {
504 "source_port_range_min": 2000,
505 "destination_ip_prefix": "192.168.3.0/24",
506 "protocol": "udp",
507 "ethertype": "IPv4",
508 "l7_parameters": {},
509 "source_port_range_max": 2000,
510 "destination_port_range_min": 3000,
511 "source_ip_prefix": "192.168.2.0/24",
512 "logical_destination_port": None,
513 "destination_port_range_max": None,
514 "logical_source_port": "aaab0ab0-1452-4636-bb3b-11dca833fa2b",
515 },
516 }
517 ],
518 )
519
520 def _test_get_sfi_list(self, list_port_pair, correlation, sfc_encap):
521 # what OpenStack is assumed to return to the VIM connector
522 list_port_pair.return_value = {
523 "port_pairs": [
524 {
525 "ingress": "5311c75d-d718-4369-bbda-cdcc6da60fcc",
526 "description": "",
527 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
528 "egress": "5311c75d-d718-4369-bbda-cdcc6da60fcc",
529 "service_function_parameters": {"correlation": correlation},
530 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
531 "id": "c121ebdd-7f2d-4213-b933-3325298a6966",
532 "name": "osm_sfi",
533 }
534 ]
535 }
536
537 # call the VIM connector
538 filter_dict = {"name": "osm_sfi", "description": ""}
539 result = self.vimconn.get_sfi_list(filter_dict.copy())
540
541 # assert that VIM connector called OpenStack with the expected filter
542 list_port_pair.assert_called_with(**filter_dict)
543 # assert that the VIM connector successfully
544 # translated and returned the OpenStack result
545 self.assertEqual(
546 result,
547 [
548 {
549 "ingress_ports": ["5311c75d-d718-4369-bbda-cdcc6da60fcc"],
550 "description": "",
551 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
552 "egress_ports": ["5311c75d-d718-4369-bbda-cdcc6da60fcc"],
553 "sfc_encap": sfc_encap,
554 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
555 "id": "c121ebdd-7f2d-4213-b933-3325298a6966",
556 "name": "osm_sfi",
557 }
558 ],
559 )
560
561 @mock.patch.object(Client, "list_sfc_port_pairs")
562 def test_get_sfi_list_with_sfc_encap(self, list_sfc_port_pairs):
563 self._test_get_sfi_list(list_sfc_port_pairs, "nsh", True)
564
565 @mock.patch.object(Client, "list_sfc_port_pairs")
566 def test_get_sfi_list_without_sfc_encap(self, list_sfc_port_pairs):
567 self._test_get_sfi_list(list_sfc_port_pairs, None, False)
568
569 @mock.patch.object(Client, "list_sfc_port_pair_groups")
570 def test_get_sf_list(self, list_sfc_port_pair_groups):
571 # what OpenStack is assumed to return to the VIM connector
572 list_sfc_port_pair_groups.return_value = {
573 "port_pair_groups": [
574 {
575 "port_pairs": [
576 "08fbdbb0-82d6-11e7-ad95-9bb52fbec2f2",
577 "0d63799c-82d6-11e7-8deb-a746bb3ae9f5",
578 ],
579 "description": "",
580 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
581 "port_pair_group_parameters": {},
582 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
583 "id": "f4a0bde8-82d5-11e7-90e1-a72b762fa27f",
584 "name": "osm_sf",
585 }
586 ]
587 }
588
589 # call the VIM connector
590 filter_dict = {"name": "osm_sf", "description": ""}
591 result = self.vimconn.get_sf_list(filter_dict.copy())
592
593 # assert that VIM connector called OpenStack with the expected filter
594 list_sfc_port_pair_groups.assert_called_with(**filter_dict)
595 # assert that the VIM connector successfully
596 # translated and returned the OpenStack result
597 self.assertEqual(
598 result,
599 [
600 {
601 "sfis": [
602 "08fbdbb0-82d6-11e7-ad95-9bb52fbec2f2",
603 "0d63799c-82d6-11e7-8deb-a746bb3ae9f5",
604 ],
605 "description": "",
606 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
607 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
608 "id": "f4a0bde8-82d5-11e7-90e1-a72b762fa27f",
609 "name": "osm_sf",
610 }
611 ],
612 )
613
614 def _test_get_sfp_list(self, list_sfc_port_chains, correlation, sfc_encap):
615 # what OpenStack is assumed to return to the VIM connector
616 list_sfc_port_chains.return_value = {
617 "port_chains": [
618 {
619 "port_pair_groups": [
620 "7d8e3bf8-82d6-11e7-a032-8ff028839d25",
621 "7dc9013e-82d6-11e7-a5a6-a3a8d78a5518",
622 ],
623 "flow_classifiers": [
624 "1333c2f4-82d7-11e7-a5df-9327f33d104e",
625 "1387ab44-82d7-11e7-9bb0-476337183905",
626 ],
627 "description": "",
628 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
629 "chain_parameters": {"correlation": correlation},
630 "chain_id": 40,
631 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
632 "id": "821bc9be-82d7-11e7-8ce3-23a08a27ab47",
633 "name": "osm_sfp",
634 }
635 ]
636 }
637
638 # call the VIM connector
639 filter_dict = {"name": "osm_sfp", "description": ""}
640 result = self.vimconn.get_sfp_list(filter_dict.copy())
641
642 # assert that VIM connector called OpenStack with the expected filter
643 list_sfc_port_chains.assert_called_with(**filter_dict)
644 # assert that the VIM connector successfully
645 # translated and returned the OpenStack result
646 self.assertEqual(
647 result,
648 [
649 {
650 "service_functions": [
651 "7d8e3bf8-82d6-11e7-a032-8ff028839d25",
652 "7dc9013e-82d6-11e7-a5a6-a3a8d78a5518",
653 ],
654 "classifications": [
655 "1333c2f4-82d7-11e7-a5df-9327f33d104e",
656 "1387ab44-82d7-11e7-9bb0-476337183905",
657 ],
658 "description": "",
659 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
660 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
661 "sfc_encap": sfc_encap,
662 "spi": 40,
663 "id": "821bc9be-82d7-11e7-8ce3-23a08a27ab47",
664 "name": "osm_sfp",
665 }
666 ],
667 )
668
669 @mock.patch.object(Client, "list_sfc_port_chains")
670 def test_get_sfp_list_with_sfc_encap(self, list_sfc_port_chains):
671 self._test_get_sfp_list(list_sfc_port_chains, "nsh", True)
672
673 @mock.patch.object(Client, "list_sfc_port_chains")
674 def test_get_sfp_list_without_sfc_encap(self, list_sfc_port_chains):
675 self._test_get_sfp_list(list_sfc_port_chains, None, False)
676
677 @mock.patch.object(Client, "list_sfc_flow_classifiers")
678 def test_get_classification(self, list_sfc_flow_classifiers):
679 # what OpenStack is assumed to return to the VIM connector
680 list_sfc_flow_classifiers.return_value = {
681 "flow_classifiers": [
682 {
683 "source_port_range_min": 2000,
684 "destination_ip_prefix": "192.168.3.0/24",
685 "protocol": "udp",
686 "description": "",
687 "ethertype": "IPv4",
688 "l7_parameters": {},
689 "source_port_range_max": 2000,
690 "destination_port_range_min": 3000,
691 "source_ip_prefix": "192.168.2.0/24",
692 "logical_destination_port": None,
693 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
694 "destination_port_range_max": None,
695 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
696 "logical_source_port": "aaab0ab0-1452-4636-bb3b-11dca833fa2b",
697 "id": "22198366-d4e8-4d6b-b4d2-637d5d6cbb7d",
698 "name": "fc1",
699 }
700 ]
701 }
702
703 # call the VIM connector
704 result = self.vimconn.get_classification("22198366-d4e8-4d6b-b4d2-637d5d6cbb7d")
705
706 # assert that VIM connector called OpenStack with the expected filter
707 list_sfc_flow_classifiers.assert_called_with(
708 id="22198366-d4e8-4d6b-b4d2-637d5d6cbb7d"
709 )
710 # assert that VIM connector successfully returned the OpenStack result
711 self.assertEqual(
712 result,
713 {
714 "id": "22198366-d4e8-4d6b-b4d2-637d5d6cbb7d",
715 "name": "fc1",
716 "description": "",
717 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
718 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
719 "ctype": "legacy_flow_classifier",
720 "definition": {
721 "source_port_range_min": 2000,
722 "destination_ip_prefix": "192.168.3.0/24",
723 "protocol": "udp",
724 "ethertype": "IPv4",
725 "l7_parameters": {},
726 "source_port_range_max": 2000,
727 "destination_port_range_min": 3000,
728 "source_ip_prefix": "192.168.2.0/24",
729 "logical_destination_port": None,
730 "destination_port_range_max": None,
731 "logical_source_port": "aaab0ab0-1452-4636-bb3b-11dca833fa2b",
732 },
733 },
734 )
735
736 @mock.patch.object(Client, "list_sfc_flow_classifiers")
737 def test_get_classification_many_results(self, list_sfc_flow_classifiers):
738 # what OpenStack is assumed to return to the VIM connector
739 list_sfc_flow_classifiers.return_value = {
740 "flow_classifiers": [
741 {
742 "source_port_range_min": 2000,
743 "destination_ip_prefix": "192.168.3.0/24",
744 "protocol": "udp",
745 "description": "",
746 "ethertype": "IPv4",
747 "l7_parameters": {},
748 "source_port_range_max": 2000,
749 "destination_port_range_min": 3000,
750 "source_ip_prefix": "192.168.2.0/24",
751 "logical_destination_port": None,
752 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
753 "destination_port_range_max": None,
754 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
755 "logical_source_port": "aaab0ab0-1452-4636-bb3b-11dca833fa2b",
756 "id": "22198366-d4e8-4d6b-b4d2-637d5d6cbb7d",
757 "name": "fc1",
758 },
759 {
760 "source_port_range_min": 1000,
761 "destination_ip_prefix": "192.168.3.0/24",
762 "protocol": "udp",
763 "description": "",
764 "ethertype": "IPv4",
765 "l7_parameters": {},
766 "source_port_range_max": 1000,
767 "destination_port_range_min": 3000,
768 "source_ip_prefix": "192.168.2.0/24",
769 "logical_destination_port": None,
770 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
771 "destination_port_range_max": None,
772 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
773 "logical_source_port": "aaab0ab0-1452-4636-bb3b-11dca833fa2b",
774 "id": "3196bafc-82dd-11e7-a205-9bf6c14b0721",
775 "name": "fc2",
776 },
777 ]
778 }
779
780 # call the VIM connector
781 self.assertRaises(
782 vimconn.VimConnConflictException,
783 self.vimconn.get_classification,
784 "3196bafc-82dd-11e7-a205-9bf6c14b0721",
785 )
786
787 # assert the VIM connector called OpenStack with the expected filter
788 list_sfc_flow_classifiers.assert_called_with(
789 id="3196bafc-82dd-11e7-a205-9bf6c14b0721"
790 )
791
792 @mock.patch.object(Client, "list_sfc_flow_classifiers")
793 def test_get_classification_no_results(self, list_sfc_flow_classifiers):
794 # what OpenStack is assumed to return to the VIM connector
795 list_sfc_flow_classifiers.return_value = {"flow_classifiers": []}
796
797 # call the VIM connector
798 self.assertRaises(
799 vimconn.VimConnNotFoundException,
800 self.vimconn.get_classification,
801 "3196bafc-82dd-11e7-a205-9bf6c14b0721",
802 )
803
804 # assert the VIM connector called OpenStack with the expected filter
805 list_sfc_flow_classifiers.assert_called_with(
806 id="3196bafc-82dd-11e7-a205-9bf6c14b0721"
807 )
808
809 @mock.patch.object(Client, "list_sfc_port_pairs")
810 def test_get_sfi(self, list_sfc_port_pairs):
811 # what OpenStack is assumed to return to the VIM connector
812 list_sfc_port_pairs.return_value = {
813 "port_pairs": [
814 {
815 "ingress": "5311c75d-d718-4369-bbda-cdcc6da60fcc",
816 "description": "",
817 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
818 "egress": "5311c75d-d718-4369-bbda-cdcc6da60fcc",
819 "service_function_parameters": {"correlation": "nsh"},
820 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
821 "id": "c121ebdd-7f2d-4213-b933-3325298a6966",
822 "name": "osm_sfi1",
823 },
824 ]
825 }
826
827 # call the VIM connector
828 result = self.vimconn.get_sfi("c121ebdd-7f2d-4213-b933-3325298a6966")
829
830 # assert the VIM connector called OpenStack with the expected filter
831 list_sfc_port_pairs.assert_called_with(
832 id="c121ebdd-7f2d-4213-b933-3325298a6966"
833 )
834 # assert the VIM connector successfully returned the OpenStack result
835 self.assertEqual(
836 result,
837 {
838 "ingress_ports": ["5311c75d-d718-4369-bbda-cdcc6da60fcc"],
839 "egress_ports": ["5311c75d-d718-4369-bbda-cdcc6da60fcc"],
840 "sfc_encap": True,
841 "description": "",
842 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
843 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
844 "id": "c121ebdd-7f2d-4213-b933-3325298a6966",
845 "name": "osm_sfi1",
846 },
847 )
848
849 @mock.patch.object(Client, "list_sfc_port_pairs")
850 def test_get_sfi_many_results(self, list_sfc_port_pairs):
851 # what OpenStack is assumed to return to the VIM connector
852 list_sfc_port_pairs.return_value = {
853 "port_pairs": [
854 {
855 "ingress": "5311c75d-d718-4369-bbda-cdcc6da60fcc",
856 "description": "",
857 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
858 "egress": "5311c75d-d718-4369-bbda-cdcc6da60fcc",
859 "service_function_parameters": {"correlation": "nsh"},
860 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
861 "id": "c121ebdd-7f2d-4213-b933-3325298a6966",
862 "name": "osm_sfi1",
863 },
864 {
865 "ingress": "5311c75d-d718-4369-bbda-cdcc6da60fcc",
866 "description": "",
867 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
868 "egress": "5311c75d-d718-4369-bbda-cdcc6da60fcc",
869 "service_function_parameters": {"correlation": "nsh"},
870 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
871 "id": "c0436d92-82db-11e7-8f9c-5fa535f1261f",
872 "name": "osm_sfi2",
873 },
874 ]
875 }
876
877 # call the VIM connector
878 self.assertRaises(
879 vimconn.VimConnConflictException,
880 self.vimconn.get_sfi,
881 "c0436d92-82db-11e7-8f9c-5fa535f1261f",
882 )
883
884 # assert that VIM connector called OpenStack with the expected filter
885 list_sfc_port_pairs.assert_called_with(
886 id="c0436d92-82db-11e7-8f9c-5fa535f1261f"
887 )
888
889 @mock.patch.object(Client, "list_sfc_port_pairs")
890 def test_get_sfi_no_results(self, list_sfc_port_pairs):
891 # what OpenStack is assumed to return to the VIM connector
892 list_sfc_port_pairs.return_value = {"port_pairs": []}
893
894 # call the VIM connector
895 self.assertRaises(
896 vimconn.VimConnNotFoundException,
897 self.vimconn.get_sfi,
898 "b22892fc-82d9-11e7-ae85-0fea6a3b3757",
899 )
900
901 # assert that VIM connector called OpenStack with the expected filter
902 list_sfc_port_pairs.assert_called_with(
903 id="b22892fc-82d9-11e7-ae85-0fea6a3b3757"
904 )
905
906 @mock.patch.object(Client, "list_sfc_port_pair_groups")
907 def test_get_sf(self, list_sfc_port_pair_groups):
908 # what OpenStack is assumed to return to the VIM connector
909 list_sfc_port_pair_groups.return_value = {
910 "port_pair_groups": [
911 {
912 "port_pairs": ["08fbdbb0-82d6-11e7-ad95-9bb52fbec2f2"],
913 "description": "",
914 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
915 "port_pair_group_parameters": {},
916 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
917 "id": "aabba8a6-82d9-11e7-a18a-d3c7719b742d",
918 "name": "osm_sf1",
919 }
920 ]
921 }
922
923 # call the VIM connector
924 result = self.vimconn.get_sf("b22892fc-82d9-11e7-ae85-0fea6a3b3757")
925
926 # assert that VIM connector called OpenStack with the expected filter
927 list_sfc_port_pair_groups.assert_called_with(
928 id="b22892fc-82d9-11e7-ae85-0fea6a3b3757"
929 )
930 # assert that VIM connector successfully returned the OpenStack result
931 self.assertEqual(
932 result,
933 {
934 "description": "",
935 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
936 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
937 "sfis": ["08fbdbb0-82d6-11e7-ad95-9bb52fbec2f2"],
938 "id": "aabba8a6-82d9-11e7-a18a-d3c7719b742d",
939 "name": "osm_sf1",
940 },
941 )
942
943 @mock.patch.object(Client, "list_sfc_port_pair_groups")
944 def test_get_sf_many_results(self, list_sfc_port_pair_groups):
945 # what OpenStack is assumed to return to the VIM connector
946 list_sfc_port_pair_groups.return_value = {
947 "port_pair_groups": [
948 {
949 "port_pairs": ["08fbdbb0-82d6-11e7-ad95-9bb52fbec2f2"],
950 "description": "",
951 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
952 "port_pair_group_parameters": {},
953 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
954 "id": "aabba8a6-82d9-11e7-a18a-d3c7719b742d",
955 "name": "osm_sf1",
956 },
957 {
958 "port_pairs": ["0d63799c-82d6-11e7-8deb-a746bb3ae9f5"],
959 "description": "",
960 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
961 "port_pair_group_parameters": {},
962 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
963 "id": "b22892fc-82d9-11e7-ae85-0fea6a3b3757",
964 "name": "osm_sf2",
965 },
966 ]
967 }
968
969 # call the VIM connector
970 self.assertRaises(
971 vimconn.VimConnConflictException,
972 self.vimconn.get_sf,
973 "b22892fc-82d9-11e7-ae85-0fea6a3b3757",
974 )
975
976 # assert that VIM connector called OpenStack with the expected filter
977 list_sfc_port_pair_groups.assert_called_with(
978 id="b22892fc-82d9-11e7-ae85-0fea6a3b3757"
979 )
980
981 @mock.patch.object(Client, "list_sfc_port_pair_groups")
982 def test_get_sf_no_results(self, list_sfc_port_pair_groups):
983 # what OpenStack is assumed to return to the VIM connector
984 list_sfc_port_pair_groups.return_value = {"port_pair_groups": []}
985
986 # call the VIM connector
987 self.assertRaises(
988 vimconn.VimConnNotFoundException,
989 self.vimconn.get_sf,
990 "b22892fc-82d9-11e7-ae85-0fea6a3b3757",
991 )
992
993 # assert that VIM connector called OpenStack with the expected filter
994 list_sfc_port_pair_groups.assert_called_with(
995 id="b22892fc-82d9-11e7-ae85-0fea6a3b3757"
996 )
997
998 @mock.patch.object(Client, "list_sfc_port_chains")
999 def test_get_sfp(self, list_sfc_port_chains):
1000 # what OpenStack is assumed to return to the VIM connector
1001 list_sfc_port_chains.return_value = {
1002 "port_chains": [
1003 {
1004 "port_pair_groups": ["7d8e3bf8-82d6-11e7-a032-8ff028839d25"],
1005 "flow_classifiers": ["1333c2f4-82d7-11e7-a5df-9327f33d104e"],
1006 "description": "",
1007 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
1008 "chain_parameters": {"correlation": "nsh"},
1009 "chain_id": 40,
1010 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
1011 "id": "821bc9be-82d7-11e7-8ce3-23a08a27ab47",
1012 "name": "osm_sfp1",
1013 }
1014 ]
1015 }
1016
1017 # call the VIM connector
1018 result = self.vimconn.get_sfp("821bc9be-82d7-11e7-8ce3-23a08a27ab47")
1019
1020 # assert that VIM connector called OpenStack with the expected filter
1021 list_sfc_port_chains.assert_called_with(
1022 id="821bc9be-82d7-11e7-8ce3-23a08a27ab47"
1023 )
1024 # assert that VIM connector successfully returned the OpenStack result
1025 self.assertEqual(
1026 result,
1027 {
1028 "service_functions": ["7d8e3bf8-82d6-11e7-a032-8ff028839d25"],
1029 "classifications": ["1333c2f4-82d7-11e7-a5df-9327f33d104e"],
1030 "description": "",
1031 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
1032 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
1033 "sfc_encap": True,
1034 "spi": 40,
1035 "id": "821bc9be-82d7-11e7-8ce3-23a08a27ab47",
1036 "name": "osm_sfp1",
1037 },
1038 )
1039
1040 @mock.patch.object(Client, "list_sfc_port_chains")
1041 def test_get_sfp_many_results(self, list_sfc_port_chains):
1042 # what OpenStack is assumed to return to the VIM connector
1043 list_sfc_port_chains.return_value = {
1044 "port_chains": [
1045 {
1046 "port_pair_groups": ["7d8e3bf8-82d6-11e7-a032-8ff028839d25"],
1047 "flow_classifiers": ["1333c2f4-82d7-11e7-a5df-9327f33d104e"],
1048 "description": "",
1049 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
1050 "chain_parameters": {"correlation": "nsh"},
1051 "chain_id": 40,
1052 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
1053 "id": "821bc9be-82d7-11e7-8ce3-23a08a27ab47",
1054 "name": "osm_sfp1",
1055 },
1056 {
1057 "port_pair_groups": ["7d8e3bf8-82d6-11e7-a032-8ff028839d25"],
1058 "flow_classifiers": ["1333c2f4-82d7-11e7-a5df-9327f33d104e"],
1059 "description": "",
1060 "tenant_id": "8f3019ef06374fa880a0144ad4bc1d7b",
1061 "chain_parameters": {"correlation": "nsh"},
1062 "chain_id": 50,
1063 "project_id": "8f3019ef06374fa880a0144ad4bc1d7b",
1064 "id": "5d002f38-82de-11e7-a770-f303f11ce66a",
1065 "name": "osm_sfp2",
1066 },
1067 ]
1068 }
1069
1070 # call the VIM connector
1071 self.assertRaises(
1072 vimconn.VimConnConflictException,
1073 self.vimconn.get_sfp,
1074 "5d002f38-82de-11e7-a770-f303f11ce66a",
1075 )
1076
1077 # assert that VIM connector called OpenStack with the expected filter
1078 list_sfc_port_chains.assert_called_with(
1079 id="5d002f38-82de-11e7-a770-f303f11ce66a"
1080 )
1081
1082 @mock.patch.object(Client, "list_sfc_port_chains")
1083 def test_get_sfp_no_results(self, list_sfc_port_chains):
1084 # what OpenStack is assumed to return to the VIM connector
1085 list_sfc_port_chains.return_value = {"port_chains": []}
1086
1087 # call the VIM connector
1088 self.assertRaises(
1089 vimconn.VimConnNotFoundException,
1090 self.vimconn.get_sfp,
1091 "5d002f38-82de-11e7-a770-f303f11ce66a",
1092 )
1093
1094 # assert that VIM connector called OpenStack with the expected filter
1095 list_sfc_port_chains.assert_called_with(
1096 id="5d002f38-82de-11e7-a770-f303f11ce66a"
1097 )
1098
1099 @mock.patch.object(Client, "delete_sfc_flow_classifier")
1100 def test_delete_classification(self, delete_sfc_flow_classifier):
1101 result = self.vimconn.delete_classification(
1102 "638f957c-82df-11e7-b7c8-132706021464"
1103 )
1104 delete_sfc_flow_classifier.assert_called_with(
1105 "638f957c-82df-11e7-b7c8-132706021464"
1106 )
1107 self.assertEqual(result, "638f957c-82df-11e7-b7c8-132706021464")
1108
1109 @mock.patch.object(Client, "delete_sfc_port_pair")
1110 def test_delete_sfi(self, delete_sfc_port_pair):
1111 result = self.vimconn.delete_sfi("638f957c-82df-11e7-b7c8-132706021464")
1112 delete_sfc_port_pair.assert_called_with("638f957c-82df-11e7-b7c8-132706021464")
1113 self.assertEqual(result, "638f957c-82df-11e7-b7c8-132706021464")
1114
1115 @mock.patch.object(Client, "delete_sfc_port_pair_group")
1116 def test_delete_sf(self, delete_sfc_port_pair_group):
1117 result = self.vimconn.delete_sf("638f957c-82df-11e7-b7c8-132706021464")
1118 delete_sfc_port_pair_group.assert_called_with(
1119 "638f957c-82df-11e7-b7c8-132706021464"
1120 )
1121 self.assertEqual(result, "638f957c-82df-11e7-b7c8-132706021464")
1122
1123 @mock.patch.object(Client, "delete_sfc_port_chain")
1124 def test_delete_sfp(self, delete_sfc_port_chain):
1125 result = self.vimconn.delete_sfp("638f957c-82df-11e7-b7c8-132706021464")
1126 delete_sfc_port_chain.assert_called_with("638f957c-82df-11e7-b7c8-132706021464")
1127 self.assertEqual(result, "638f957c-82df-11e7-b7c8-132706021464")
1128
1129
1130 def check_if_assert_not_called(mocks: list):
1131 for mocking in mocks:
1132 mocking.assert_not_called()
1133
1134
1135 class Status:
1136 def __init__(self, s):
1137 self.status = s
1138
1139 def __str__(self):
1140 return self.status
1141
1142
1143 class CopyingMock(MagicMock):
1144 def __call__(self, *args, **kwargs):
1145 args = deepcopy(args)
1146 kwargs = deepcopy(kwargs)
1147 return super(CopyingMock, self).__call__(*args, **kwargs)
1148
1149
1150 class TestNewVmInstance(unittest.TestCase):
1151 @patch("logging.getLogger", autospec=True)
1152 def setUp(self, mock_logger):
1153 # Instantiate dummy VIM connector so we can test it
1154 # It throws exception because of dummy parameters,
1155 # We are disabling the logging of exception not to print them to console.
1156 mock_logger = logging.getLogger()
1157 mock_logger.disabled = True
1158 self.vimconn = vimconnector(
1159 "123",
1160 "openstackvim",
1161 "456",
1162 "789",
1163 "http://dummy.url",
1164 None,
1165 "user",
1166 "pass",
1167 )
1168 self.vimconn.neutron = CopyingMock()
1169 self.vimconn.nova = CopyingMock()
1170 self.vimconn.cinder = CopyingMock()
1171 self.server = MagicMock(object, autospec=True)
1172 self.server.tenant_id = "408b73-r9cc-5a6a-a270-82cc4811bd4a"
1173 self.server.id = "908b73-e9cc-5a6a-t270-82cc4811bd4a"
1174 self.vimconn.config["security_groups"] = "default"
1175 self.vimconn.config["keypair"] = "my_keypair"
1176 self.vimconn.security_groups_id = "12345"
1177 self.vimconn.nova.api_version.get_string.return_value = "2.32"
1178 self.vimconn.logger = CopyingMock()
1179
1180 @patch.object(vimconnector, "_get_ids_from_name")
1181 def test_prepare_port_dict_security_security_groups_exists_in_config(
1182 self, mock_get_ids
1183 ):
1184 """In VIM config security_groups exists, net port_security is True
1185 no_port_security_extension does not exist.
1186 """
1187 self.vimconn.config = {"security_groups": "example_security_group"}
1188 net = {"port_security": True}
1189 port_dict = {}
1190 result_dict = {"security_groups": "12345"}
1191
1192 self.vimconn._prepare_port_dict_security_groups(net, port_dict)
1193 self.assertDictEqual(result_dict, port_dict)
1194 mock_get_ids.assert_not_called()
1195
1196 @patch.object(vimconnector, "_get_ids_from_name")
1197 def test_prepare_port_dict_security_security_groups_exists_in_config_no_security_groups_id(
1198 self, mock_get_ids
1199 ):
1200 """In VIM config Security_groups exists, net port_security is True, vim security_groups_id does not exist,
1201 no_port_security_extension does not exist.
1202 """
1203 self.vimconn.config = {"security_groups": "example_security_group"}
1204 self.vimconn.security_groups_id = None
1205 net = {"port_security": True}
1206 port_dict = {}
1207 result_dict = {"security_groups": None}
1208
1209 self.vimconn._prepare_port_dict_security_groups(net, port_dict)
1210 self.assertDictEqual(result_dict, port_dict)
1211 mock_get_ids.assert_called()
1212
1213 @patch.object(vimconnector, "_get_ids_from_name")
1214 def test_prepare_port_dict_security_security_groups_exists_security_extension_true_in_config(
1215 self, mock_get_ids
1216 ):
1217 """In VIM config security_groups exists, net port_security is True, in VIM security_groups_id exists,
1218 no_port_security_extension set to True.
1219 """
1220 self.vimconn.config = {
1221 "security_groups": "example_security_group",
1222 "no_port_security_extension": True,
1223 }
1224 net = {"port_security": True}
1225 port_dict = {}
1226 result_dict = {}
1227
1228 self.vimconn._prepare_port_dict_security_groups(net, port_dict)
1229 self.assertDictEqual(result_dict, port_dict)
1230 mock_get_ids.assert_not_called()
1231
1232 @patch.object(vimconnector, "_get_ids_from_name")
1233 def test_prepare_port_dict_security_no_security_groups_in_config(
1234 self, mock_get_ids
1235 ):
1236 """In VIM config security_group does not exist, net port_security True, in VIM security_groups_id exists,
1237 no_port_security_extension does not exist."""
1238 self.vimconn.config = {}
1239 net = {"port_security": True}
1240 port_dict = {}
1241 result_dict = {}
1242
1243 self.vimconn._prepare_port_dict_security_groups(net, port_dict)
1244 self.assertDictEqual(result_dict, port_dict)
1245 mock_get_ids.assert_not_called()
1246
1247 @patch.object(vimconnector, "_get_ids_from_name")
1248 def test_prepare_port_dict_security_no_security_groups_security_extension_true_in_config(
1249 self, mock_get_ids
1250 ):
1251 """Security_group does not exist, net port_security is True, in VIM security_groups_id exists,
1252 no_port_security_extension set to True."""
1253 self.vimconn.config = {"no_port_security_extension": True}
1254 net = {"port_security": True}
1255 port_dict = {}
1256 result_dict = {}
1257
1258 self.vimconn._prepare_port_dict_security_groups(net, port_dict)
1259 self.assertDictEqual(result_dict, port_dict)
1260 mock_get_ids.assert_not_called()
1261
1262 @patch.object(vimconnector, "_get_ids_from_name")
1263 def test_prepare_port_dict_security_security_groups_exists_net_port_security_false(
1264 self, mock_get_ids
1265 ):
1266 """In VIM config security_group exists, net port_security False, security_groups_id exists,
1267 no_port_security_extension does not exist."""
1268 self.vimconn.config = {"security_groups": "example_security_group"}
1269 net = {"port_security": False}
1270 port_dict = {}
1271 result_dict = {}
1272
1273 self.vimconn._prepare_port_dict_security_groups(net, port_dict)
1274 self.assertDictEqual(result_dict, port_dict)
1275 mock_get_ids.assert_not_called()
1276
1277 @patch.object(vimconnector, "_get_ids_from_name")
1278 def test_prepare_port_dict_security_net_port_security_false_port_security_extension_true(
1279 self, mock_get_ids
1280 ):
1281 """In VIM config security_group exists, net port_security False, security_groups_id exists,
1282 no_port_security_extension set to True."""
1283 self.vimconn.config = {
1284 "security_groups": "example_security_group",
1285 "no_port_security_extension": True,
1286 }
1287 net = {"port_security": False}
1288 port_dict = {}
1289 result_dict = {}
1290
1291 self.vimconn._prepare_port_dict_security_groups(net, port_dict)
1292 self.assertDictEqual(result_dict, port_dict)
1293 mock_get_ids.assert_not_called()
1294
1295 def test_prepare_port_dict_binding_net_type_virtual(self):
1296 """net type is virtual."""
1297 net = {"type": "virtual"}
1298 port_dict = {}
1299 result_dict = {}
1300 self.vimconn._prepare_port_dict_binding(net, port_dict)
1301 self.assertDictEqual(result_dict, port_dict)
1302
1303 def test_prepare_port_dict_binding_net_type_vf(self):
1304 """net type is VF, vim_type is not VIO."""
1305 net = {"type": "VF"}
1306 self.vimconn.vim_type = None
1307 port_dict = {}
1308 result_dict = {"binding:vnic_type": "direct"}
1309 self.vimconn._prepare_port_dict_binding(net, port_dict)
1310 self.assertDictEqual(port_dict, result_dict)
1311
1312 def test_prepare_port_dict_binding_net_type_sriov_vim_type_vio(self):
1313 """net type is SR-IOV, vim_type is VIO."""
1314 net = {"type": "SR-IOV"}
1315 self.vimconn.vim_type = "VIO"
1316 port_dict = {}
1317 result_dict = {
1318 "binding:vnic_type": "direct",
1319 "port_security_enabled": False,
1320 "provider_security_groups": [],
1321 "security_groups": [],
1322 }
1323 self.vimconn._prepare_port_dict_binding(net, port_dict)
1324 self.assertDictEqual(port_dict, result_dict)
1325
1326 def test_prepare_port_dict_binding_net_type_passthrough(self):
1327 """net type is pci-passthrough."""
1328 net = {"type": "PCI-PASSTHROUGH"}
1329 port_dict = {}
1330 result_dict = {
1331 "binding:vnic_type": "direct-physical",
1332 }
1333 self.vimconn._prepare_port_dict_binding(net, port_dict)
1334 self.assertDictEqual(port_dict, result_dict)
1335
1336 def test_prepare_port_dict_binding_no_net_type(self):
1337 """net type is missing."""
1338 net = {}
1339 port_dict = {}
1340 with self.assertRaises(VimConnException) as err:
1341 self.vimconn._prepare_port_dict_binding(net, port_dict)
1342 self.assertEqual(str(err.exception), "Type is missing in the network details.")
1343
1344 def test_set_fixed_ip(self):
1345 """new_port has fixed ip."""
1346 net = {}
1347 new_port = {
1348 "port": {
1349 "fixed_ips": [{"ip_address": "10.1.2.3"}, {"ip_address": "20.1.2.3"}]
1350 }
1351 }
1352 result = {"ip": "10.1.2.3"}
1353 self.vimconn._set_fixed_ip(new_port, net)
1354 self.assertDictEqual(net, result)
1355
1356 def test_set_fixed_ip_no_fixed_ip(self):
1357 """new_port does not have fixed ip."""
1358 net = {}
1359 new_port = {"port": {}}
1360 result = {"ip": None}
1361 self.vimconn._set_fixed_ip(new_port, net)
1362 self.assertDictEqual(net, result)
1363
1364 def test_set_fixed_ip_raise_exception(self):
1365 """new_port does not have port details."""
1366 net = {}
1367 new_port = {}
1368 with self.assertRaises(Exception) as err:
1369 self.vimconn._set_fixed_ip(new_port, net)
1370 self.assertEqual(type(err.exception), KeyError)
1371
1372 def test_prepare_port_dict_mac_ip_addr(self):
1373 """mac address and ip address exist."""
1374 net = {
1375 "mac_address": mac_address,
1376 "ip_address": "10.0.1.5",
1377 }
1378 port_dict = {}
1379 result_dict = {
1380 "mac_address": mac_address,
1381 "fixed_ips": [{"ip_address": "10.0.1.5"}],
1382 }
1383 self.vimconn._prepare_port_dict_mac_ip_addr(net, port_dict)
1384 self.assertDictEqual(port_dict, result_dict)
1385
1386 def test_prepare_port_dict_mac_ip_addr_no_mac_and_ip(self):
1387 """mac address and ip address does not exist."""
1388 net = {}
1389 port_dict = {}
1390 result_dict = {}
1391 self.vimconn._prepare_port_dict_mac_ip_addr(net, port_dict)
1392 self.assertDictEqual(port_dict, result_dict)
1393
1394 def test_create_new_port(self):
1395 """new port has id and mac address."""
1396 new_port = {
1397 "port": {
1398 "id": port_id,
1399 "mac_address": mac_address,
1400 },
1401 }
1402 self.vimconn.neutron.create_port.return_value = new_port
1403 net, port_dict, created_items = {}, {}, {}
1404 expected_result = new_port
1405 expected_net = {
1406 "mac_adress": mac_address,
1407 "vim_id": port_id,
1408 }
1409 expected_created_items = {f"port:{port_id}": True}
1410 result = self.vimconn._create_new_port(port_dict, created_items, net)
1411 self.assertDictEqual(result, expected_result)
1412 self.assertEqual(net, expected_net)
1413 self.assertEqual(created_items, expected_created_items)
1414 self.vimconn.neutron.create_port.assert_called_once_with({"port": port_dict})
1415
1416 def test_create_new_port_without_mac_or_id(self):
1417 """new port does not have mac address or ID."""
1418 new_port = {}
1419 self.vimconn.neutron.create_port.return_value = new_port
1420 net, port_dict, created_items = {}, {}, {}
1421 with self.assertRaises(KeyError):
1422 self.vimconn._create_new_port(port_dict, created_items, net)
1423 self.vimconn.neutron.create_port.assert_called_once_with({"port": port_dict})
1424
1425 def test_create_new_port_neutron_create_port_raises_exception(self):
1426 """Neutron create port raises exception."""
1427 self.vimconn.neutron.create_port.side_effect = VimConnException(
1428 "New port is not created."
1429 )
1430 net, port_dict, created_items = {}, {}, {}
1431 with self.assertRaises(VimConnException):
1432 self.vimconn._create_new_port(port_dict, created_items, net)
1433 self.vimconn.neutron.create_port.assert_called_once_with({"port": port_dict})
1434
1435 @patch.object(vimconnector, "_prepare_port_dict_security_groups")
1436 @patch.object(vimconnector, "_prepare_port_dict_binding")
1437 @patch.object(vimconnector, "_prepare_port_dict_mac_ip_addr")
1438 @patch.object(vimconnector, "_create_new_port")
1439 @patch.object(vimconnector, "_set_fixed_ip")
1440 def test_create_port(
1441 self,
1442 mock_set_fixed_ip,
1443 mock_create_new_port,
1444 mock_prepare_port_dict_mac_ip_addr,
1445 mock_prepare_port_dict_binding,
1446 mock_prepare_port_dict_security_groups,
1447 ):
1448 """Net has name, type, net-id."""
1449
1450 net = {
1451 "net_id": net_id,
1452 "name": "management",
1453 "type": "virtual",
1454 }
1455 created_items = {}
1456 new_port = {
1457 "port": {
1458 "id": net_id,
1459 "mac_address": mac_address,
1460 "name": "management",
1461 "fixed_ips": [{"ip_address": ip_addr1}],
1462 },
1463 }
1464 mock_create_new_port.return_value = new_port
1465 expected_port = {
1466 "port-id": net_id,
1467 "tag": "management",
1468 }
1469 port_dict = {
1470 "network_id": net_id,
1471 "name": "management",
1472 "admin_state_up": True,
1473 }
1474
1475 new_port_result, port_result = self.vimconn._create_port(
1476 net, name, created_items
1477 )
1478
1479 self.assertDictEqual(new_port_result, new_port)
1480 self.assertDictEqual(port_result, expected_port)
1481
1482 mock_prepare_port_dict_security_groups.assert_called_once_with(net, port_dict)
1483 mock_prepare_port_dict_binding.assert_called_once_with(net, port_dict)
1484 mock_prepare_port_dict_mac_ip_addr.assert_called_once_with(net, port_dict)
1485 mock_create_new_port.assert_called_once_with(port_dict, created_items, net)
1486 mock_set_fixed_ip.assert_called_once_with(new_port, net)
1487
1488 @patch.object(vimconnector, "_prepare_port_dict_security_groups")
1489 @patch.object(vimconnector, "_prepare_port_dict_binding")
1490 @patch.object(vimconnector, "_prepare_port_dict_mac_ip_addr")
1491 @patch.object(vimconnector, "_create_new_port")
1492 @patch.object(vimconnector, "_set_fixed_ip")
1493 def test_create_port_no_port_name(
1494 self,
1495 mock_set_fixed_ip,
1496 mock_create_new_port,
1497 mock_prepare_port_dict_mac_ip_addr,
1498 mock_prepare_port_dict_binding,
1499 mock_prepare_port_dict_security_groups,
1500 ):
1501 """Net has no name."""
1502 net = {
1503 "net_id": net_id,
1504 "type": "virtual",
1505 }
1506 created_items = {}
1507 new_port = {
1508 "port": {
1509 "id": net_id,
1510 "mac_address": mac_address,
1511 "name": name,
1512 "fixed_ips": [{"ip_address": ip_addr1}],
1513 },
1514 }
1515 mock_create_new_port.return_value = new_port
1516 expected_port = {
1517 "port-id": net_id,
1518 "tag": name,
1519 }
1520 port_dict = {
1521 "network_id": net_id,
1522 "admin_state_up": True,
1523 "name": name,
1524 }
1525
1526 new_port_result, port_result = self.vimconn._create_port(
1527 net, name, created_items
1528 )
1529
1530 self.assertDictEqual(new_port_result, new_port)
1531 self.assertDictEqual(port_result, expected_port)
1532
1533 mock_prepare_port_dict_security_groups.assert_called_once_with(net, port_dict)
1534 mock_prepare_port_dict_binding.assert_called_once_with(net, port_dict)
1535 mock_prepare_port_dict_mac_ip_addr.assert_called_once_with(net, port_dict)
1536 mock_create_new_port.assert_called_once_with(port_dict, created_items, net)
1537 mock_set_fixed_ip.assert_called_once_with(new_port, net)
1538
1539 @patch.object(vimconnector, "_prepare_port_dict_security_groups")
1540 @patch.object(vimconnector, "_prepare_port_dict_binding")
1541 @patch.object(vimconnector, "_prepare_port_dict_mac_ip_addr")
1542 @patch.object(vimconnector, "_create_new_port")
1543 @patch.object(vimconnector, "_set_fixed_ip")
1544 def test_create_port_nova_api_version_smaller_than_232(
1545 self,
1546 mock_set_fixed_ip,
1547 mock_create_new_port,
1548 mock_prepare_port_dict_mac_ip_addr,
1549 mock_prepare_port_dict_binding,
1550 mock_prepare_port_dict_security_groups,
1551 ):
1552 """Nova api version is smaller than 2.32."""
1553 self.vimconn.nova.api_version.get_string.return_value = "2.30"
1554 net = {
1555 "net_id": net_id,
1556 "type": "virtual",
1557 }
1558 created_items = {}
1559 new_port = {
1560 "port": {
1561 "id": net_id,
1562 "mac_address": mac_address,
1563 "name": name,
1564 "fixed_ips": [{"ip_address": ip_addr1}],
1565 },
1566 }
1567 mock_create_new_port.return_value = new_port
1568 expected_port = {
1569 "port-id": net_id,
1570 }
1571 port_dict = {
1572 "network_id": net_id,
1573 "admin_state_up": True,
1574 "name": name,
1575 }
1576
1577 new_port_result, port_result = self.vimconn._create_port(
1578 net, name, created_items
1579 )
1580
1581 self.assertDictEqual(new_port_result, new_port)
1582 self.assertDictEqual(port_result, expected_port)
1583
1584 mock_prepare_port_dict_security_groups.assert_called_once_with(net, port_dict)
1585 mock_prepare_port_dict_binding.assert_called_once_with(net, port_dict)
1586 mock_prepare_port_dict_mac_ip_addr.assert_called_once_with(net, port_dict)
1587 mock_create_new_port.assert_called_once_with(port_dict, created_items, net)
1588 mock_set_fixed_ip.assert_called_once_with(new_port, net)
1589
1590 @patch.object(vimconnector, "_prepare_port_dict_security_groups")
1591 @patch.object(vimconnector, "_prepare_port_dict_binding")
1592 @patch.object(vimconnector, "_prepare_port_dict_mac_ip_addr")
1593 @patch.object(vimconnector, "_create_new_port")
1594 @patch.object(vimconnector, "_set_fixed_ip")
1595 def test_create_port_create_new_port_raise_exception(
1596 self,
1597 mock_set_fixed_ip,
1598 mock_create_new_port,
1599 mock_prepare_port_dict_mac_ip_addr,
1600 mock_prepare_port_dict_binding,
1601 mock_prepare_port_dict_security_groups,
1602 ):
1603 """_create_new_port method raises exception."""
1604 net = {
1605 "net_id": net_id,
1606 "type": "virtual",
1607 }
1608 created_items = {}
1609 mock_create_new_port.side_effect = Exception
1610 port_dict = {
1611 "network_id": net_id,
1612 "admin_state_up": True,
1613 "name": name,
1614 }
1615
1616 with self.assertRaises(Exception):
1617 self.vimconn._create_port(net, name, created_items)
1618
1619 mock_prepare_port_dict_security_groups.assert_called_once_with(net, port_dict)
1620 mock_prepare_port_dict_binding.assert_called_once_with(net, port_dict)
1621 mock_prepare_port_dict_mac_ip_addr.assert_called_once_with(net, port_dict)
1622 mock_create_new_port.assert_called_once_with(port_dict, created_items, net)
1623 mock_set_fixed_ip.assert_not_called()
1624
1625 @patch.object(vimconnector, "_prepare_port_dict_security_groups")
1626 @patch.object(vimconnector, "_prepare_port_dict_binding")
1627 @patch.object(vimconnector, "_prepare_port_dict_mac_ip_addr")
1628 @patch.object(vimconnector, "_create_new_port")
1629 @patch.object(vimconnector, "_set_fixed_ip")
1630 def test_create_port_create_sec_groups_raises_exception(
1631 self,
1632 mock_set_fixed_ip,
1633 mock_create_new_port,
1634 mock_prepare_port_dict_mac_ip_addr,
1635 mock_prepare_port_dict_binding,
1636 mock_prepare_port_dict_security_groups,
1637 ):
1638 """_prepare_port_dict_security_groups method raises exception."""
1639 net = {
1640 "net_id": net_id,
1641 "type": "virtual",
1642 }
1643 created_items = {}
1644 mock_prepare_port_dict_security_groups.side_effect = Exception
1645 port_dict = {
1646 "network_id": net_id,
1647 "admin_state_up": True,
1648 "name": name,
1649 }
1650
1651 with self.assertRaises(Exception):
1652 self.vimconn._create_port(net, name, created_items)
1653
1654 mock_prepare_port_dict_security_groups.assert_called_once_with(net, port_dict)
1655
1656 mock_prepare_port_dict_binding.assert_not_called()
1657 mock_prepare_port_dict_mac_ip_addr.assert_not_called()
1658 mock_create_new_port.assert_not_called()
1659 mock_set_fixed_ip.assert_not_called()
1660
1661 @patch.object(vimconnector, "_prepare_port_dict_security_groups")
1662 @patch.object(vimconnector, "_prepare_port_dict_binding")
1663 @patch.object(vimconnector, "_prepare_port_dict_mac_ip_addr")
1664 @patch.object(vimconnector, "_create_new_port")
1665 @patch.object(vimconnector, "_set_fixed_ip")
1666 def test_create_port_create_port_dict_binding_raise_exception(
1667 self,
1668 mock_set_fixed_ip,
1669 mock_create_new_port,
1670 mock_prepare_port_dict_mac_ip_addr,
1671 mock_prepare_port_dict_binding,
1672 mock_prepare_port_dict_security_groups,
1673 ):
1674 """_prepare_port_dict_binding method raises exception."""
1675
1676 net = {
1677 "net_id": net_id,
1678 "type": "virtual",
1679 }
1680 created_items = {}
1681 mock_prepare_port_dict_binding.side_effect = Exception
1682 port_dict = {
1683 "network_id": net_id,
1684 "admin_state_up": True,
1685 "name": name,
1686 }
1687
1688 with self.assertRaises(Exception):
1689 self.vimconn._create_port(net, name, created_items)
1690
1691 mock_prepare_port_dict_security_groups.assert_called_once_with(net, port_dict)
1692
1693 mock_prepare_port_dict_binding.assert_called_once_with(net, port_dict)
1694
1695 mock_prepare_port_dict_mac_ip_addr.assert_not_called()
1696 mock_create_new_port.assert_not_called()
1697 mock_set_fixed_ip.assert_not_called()
1698
1699 @patch.object(vimconnector, "_prepare_port_dict_security_groups")
1700 @patch.object(vimconnector, "_prepare_port_dict_binding")
1701 @patch.object(vimconnector, "_prepare_port_dict_mac_ip_addr")
1702 @patch.object(vimconnector, "_create_new_port")
1703 @patch.object(vimconnector, "_set_fixed_ip")
1704 def test_create_port_create_port_mac_ip_addr_raise_exception(
1705 self,
1706 mock_set_fixed_ip,
1707 mock_create_new_port,
1708 mock_prepare_port_dict_mac_ip_addr,
1709 mock_prepare_port_dict_binding,
1710 mock_prepare_port_dict_security_groups,
1711 ):
1712 """prepare_port_dict_mac_ip_addr method raises exception."""
1713 net = {
1714 "net_id": net_id,
1715 "type": "virtual",
1716 }
1717 created_items = {}
1718 mock_prepare_port_dict_mac_ip_addr.side_effect = Exception
1719 port_dict = {
1720 "network_id": net_id,
1721 "admin_state_up": True,
1722 "name": name,
1723 }
1724
1725 with self.assertRaises(Exception):
1726 self.vimconn._create_port(net, name, created_items)
1727
1728 mock_prepare_port_dict_security_groups.assert_called_once_with(net, port_dict)
1729 mock_prepare_port_dict_binding.assert_called_once_with(net, port_dict)
1730 mock_prepare_port_dict_mac_ip_addr.assert_called_once_with(net, port_dict)
1731
1732 mock_create_new_port.assert_not_called()
1733 mock_set_fixed_ip.assert_not_called()
1734
1735 @patch.object(vimconnector, "_prepare_port_dict_security_groups")
1736 @patch.object(vimconnector, "_prepare_port_dict_binding")
1737 @patch.object(vimconnector, "_prepare_port_dict_mac_ip_addr")
1738 @patch.object(vimconnector, "_create_new_port")
1739 @patch.object(vimconnector, "_set_fixed_ip")
1740 def test_create_port_create_port_set_fixed_ip_raise_exception(
1741 self,
1742 mock_set_fixed_ip,
1743 mock_create_new_port,
1744 mock_prepare_port_dict_mac_ip_addr,
1745 mock_prepare_port_dict_binding,
1746 mock_prepare_port_dict_security_groups,
1747 ):
1748 """_set_fixed_ip method raises exception."""
1749 net = {
1750 "net_id": net_id,
1751 "type": "virtual",
1752 }
1753 created_items = {}
1754 mock_set_fixed_ip.side_effect = VimConnException(
1755 "Port detail is missing in new_port."
1756 )
1757 port_dict = {
1758 "network_id": net_id,
1759 "admin_state_up": True,
1760 "name": name,
1761 }
1762 new_port = {
1763 "port": {
1764 "id": net_id,
1765 "mac_address": mac_address,
1766 "name": name,
1767 "fixed_ips": [{"ip_address": ip_addr1}],
1768 },
1769 }
1770 mock_create_new_port.return_value = new_port
1771
1772 with self.assertRaises(VimConnException):
1773 self.vimconn._create_port(net, name, created_items)
1774
1775 mock_prepare_port_dict_security_groups.assert_called_once_with(net, port_dict)
1776 mock_prepare_port_dict_binding.assert_called_once_with(net, port_dict)
1777 mock_prepare_port_dict_mac_ip_addr.assert_called_once_with(net, port_dict)
1778 mock_create_new_port.assert_called_once_with(port_dict, created_items, net)
1779 mock_set_fixed_ip.assert_called_once_with(new_port, net)
1780
1781 @patch.object(vimconnector, "_reload_connection")
1782 @patch.object(vimconnector, "_create_port")
1783 def test_prepare_network_for_vm_instance_no_net_id(
1784 self, mock_create_port, mock_reload_connection
1785 ):
1786 """Nets do not have net_id"""
1787 mock_reload_connection.side_effect = None
1788 created_items = {}
1789 net_list = [
1790 {
1791 "use": "mgmt",
1792 "port_security": False,
1793 "exit_on_floating_ip_error": False,
1794 "port_security_disable_strategy": "full",
1795 },
1796 {
1797 "port_security": True,
1798 "exit_on_floating_ip_error": False,
1799 "floating_ip": True,
1800 },
1801 ]
1802 net_list_vim = []
1803 external_network, no_secured_ports = [], []
1804 expected_external_network, expected_no_secured_ports = [], []
1805 expected_net_list_vim = []
1806
1807 self.vimconn._prepare_network_for_vminstance(
1808 name,
1809 net_list,
1810 created_items,
1811 net_list_vim,
1812 external_network,
1813 no_secured_ports,
1814 )
1815 self.assertEqual(expected_net_list_vim, net_list_vim)
1816 self.assertEqual(external_network, expected_external_network)
1817 self.assertEqual(expected_no_secured_ports, no_secured_ports)
1818
1819 mock_create_port.assert_not_called()
1820
1821 @patch.object(vimconnector, "_reload_connection")
1822 @patch.object(vimconnector, "_create_port")
1823 def test_prepare_network_for_vm_instance_empty_net_list(
1824 self, mock_create_port, mock_reload_connection
1825 ):
1826 """Net list is empty."""
1827 mock_reload_connection.side_effect = None
1828 created_items = {}
1829 net_list_vim = []
1830 external_network, no_secured_ports = [], []
1831 expected_external_network, expected_no_secured_ports = [], []
1832 expected_net_list_vim = []
1833
1834 self.vimconn._prepare_network_for_vminstance(
1835 name,
1836 net_list,
1837 created_items,
1838 net_list_vim,
1839 external_network,
1840 no_secured_ports,
1841 )
1842 self.assertEqual(expected_net_list_vim, net_list_vim)
1843 self.assertEqual(external_network, expected_external_network)
1844 self.assertEqual(expected_no_secured_ports, no_secured_ports)
1845
1846 mock_create_port.assert_not_called()
1847
1848 @patch.object(vimconnector, "_reload_connection")
1849 @patch.object(vimconnector, "_create_port")
1850 def test_prepare_network_for_vm_instance_use_floating_ip_false_mgmt_net(
1851 self, mock_create_port, mock_reload_connection
1852 ):
1853 """Nets have net-id, floating_ip False, mgmt network."""
1854 mock_reload_connection.side_effect = None
1855 created_items = {}
1856 net_list = [
1857 {
1858 "net_id": net2_id,
1859 "floating_ip": False,
1860 "use": "mgmt",
1861 }
1862 ]
1863 net_list_vim = []
1864 mock_create_port.side_effect = [
1865 (
1866 {
1867 "port": {
1868 "id": port2_id,
1869 "mac_address": mac_address,
1870 "name": name,
1871 },
1872 },
1873 {"port-dict": port2_id},
1874 ),
1875 ]
1876 external_network, no_secured_ports = [], []
1877 expected_external_network, expected_no_secured_ports = [], []
1878 expected_net_list_vim = [{"port-dict": port2_id}]
1879 self.vimconn._prepare_network_for_vminstance(
1880 name,
1881 net_list,
1882 created_items,
1883 net_list_vim,
1884 external_network,
1885 no_secured_ports,
1886 )
1887 self.assertEqual(expected_net_list_vim, net_list_vim)
1888 self.assertEqual(external_network, expected_external_network)
1889 self.assertEqual(expected_no_secured_ports, no_secured_ports)
1890
1891 mock_create_port.assert_called_once_with(
1892 {
1893 "net_id": net2_id,
1894 "floating_ip": False,
1895 "use": "mgmt",
1896 },
1897 name,
1898 created_items,
1899 )
1900
1901 @patch.object(vimconnector, "_reload_connection")
1902 def test_prepare_network_for_vm_instance_mgmt_net_net_port_security_and_floating_ip_true(
1903 self, mock_reload_connection
1904 ):
1905 """Nets have net-id, use_floating_ip False in VIM config, mgmt network, net floating_ip is True."""
1906 self.vimconn.config["use_floating_ip"] = False
1907 mock_create_port = CopyingMock()
1908 mock_reload_connection.side_effect = None
1909 created_items = {}
1910 net_list = [
1911 {
1912 "net_id": net2_id,
1913 "floating_ip": True,
1914 "use": "mgmt",
1915 }
1916 ]
1917 net_list_vim = []
1918 mock_create_port.side_effect = [
1919 (
1920 {
1921 "port": {
1922 "id": port2_id,
1923 "mac_address": mac_address,
1924 "name": name,
1925 },
1926 },
1927 {"port-dict": port2_id},
1928 ),
1929 ]
1930 external_network, no_secured_ports = [], []
1931 expected_external_network = [
1932 {
1933 "net_id": net2_id,
1934 "floating_ip": True,
1935 "use": "mgmt",
1936 "exit_on_floating_ip_error": True,
1937 },
1938 ]
1939 expected_no_secured_ports = []
1940 expected_net_list_vim = [{"port-dict": port2_id}]
1941 with patch.object(vimconnector, "_create_port", mock_create_port):
1942 self.vimconn._prepare_network_for_vminstance(
1943 name,
1944 net_list,
1945 created_items,
1946 net_list_vim,
1947 external_network,
1948 no_secured_ports,
1949 )
1950 self.assertEqual(expected_net_list_vim, net_list_vim)
1951 self.assertEqual(external_network, expected_external_network)
1952 self.assertEqual(expected_no_secured_ports, no_secured_ports)
1953
1954 mock_create_port.assert_called_once_with(
1955 {
1956 "net_id": net2_id,
1957 "floating_ip": True,
1958 "use": "mgmt",
1959 },
1960 name,
1961 created_items,
1962 )
1963
1964 @patch.object(vimconnector, "_reload_connection")
1965 def test_prepare_network_for_vm_instance_use_floating_ip_true_mgmt_net_port_security_false(
1966 self, mock_reload_connection
1967 ):
1968 """Nets have net-id, use_floating_ip is True in VIM config, mgmt network, net port security is False."""
1969 mock_create_port = CopyingMock()
1970 self.vimconn.config["use_floating_ip"] = True
1971 self.vimconn.config["no_port_security_extension"] = False
1972 mock_reload_connection.side_effect = None
1973 created_items = {}
1974
1975 net_list = [
1976 {
1977 "net_id": net2_id,
1978 "use": "mgmt",
1979 "port_security": False,
1980 "exit_on_floating_ip_error": False,
1981 "port_security_disable_strategy": "full",
1982 }
1983 ]
1984 net_list_vim = []
1985 mock_create_port.side_effect = [
1986 (
1987 {
1988 "port": {
1989 "id": port2_id,
1990 "mac_address": mac_address,
1991 "name": name,
1992 },
1993 },
1994 {"port-dict": port2_id},
1995 ),
1996 ]
1997 external_network, no_secured_ports = [], []
1998 expected_external_network = [
1999 {
2000 "net_id": net2_id,
2001 "use": "mgmt",
2002 "port_security": False,
2003 "exit_on_floating_ip_error": False,
2004 "port_security_disable_strategy": "full",
2005 "floating_ip": True,
2006 },
2007 ]
2008 expected_no_secured_ports = [(port2_id, "full")]
2009 expected_net_list_vim = [{"port-dict": port2_id}]
2010 with patch.object(vimconnector, "_create_port", mock_create_port):
2011 self.vimconn._prepare_network_for_vminstance(
2012 name,
2013 net_list,
2014 created_items,
2015 net_list_vim,
2016 external_network,
2017 no_secured_ports,
2018 )
2019
2020 mock_create_port.assert_called_once_with(
2021 {
2022 "net_id": net2_id,
2023 "use": "mgmt",
2024 "port_security": False,
2025 "exit_on_floating_ip_error": False,
2026 "port_security_disable_strategy": "full",
2027 },
2028 name,
2029 created_items,
2030 )
2031 self.assertEqual(expected_net_list_vim, net_list_vim)
2032 self.assertEqual(external_network, expected_external_network)
2033 self.assertEqual(expected_no_secured_ports, no_secured_ports)
2034
2035 @patch.object(vimconnector, "_reload_connection")
2036 def test_prepare_network_for_vm_instance_use_fip_true_non_mgmt_net_port_security_false(
2037 self, mock_reload_connection
2038 ):
2039 """Nets have net-id, use_floating_ip True in VIM config, non-mgmt network, port security is False."""
2040 mock_create_port = CopyingMock()
2041 self.vimconn.config["use_floating_ip"] = True
2042 self.vimconn.config["no_port_security_extension"] = False
2043 mock_reload_connection.side_effect = None
2044 created_items = {}
2045
2046 net_list = [
2047 {
2048 "net_id": net2_id,
2049 "use": "other",
2050 "port_security": False,
2051 "port_security_disable_strategy": "full",
2052 }
2053 ]
2054 net_list_vim = []
2055 mock_create_port.side_effect = [
2056 (
2057 {
2058 "port": {
2059 "id": port2_id,
2060 "mac_address": mac_address,
2061 "name": name,
2062 },
2063 },
2064 {"port-dict": port2_id},
2065 ),
2066 ]
2067 external_network, no_secured_ports = [], []
2068 expected_external_network = []
2069 expected_no_secured_ports = [(port2_id, "full")]
2070 expected_net_list_vim = [{"port-dict": port2_id}]
2071 with patch.object(vimconnector, "_create_port", mock_create_port):
2072 self.vimconn._prepare_network_for_vminstance(
2073 name,
2074 net_list,
2075 created_items,
2076 net_list_vim,
2077 external_network,
2078 no_secured_ports,
2079 )
2080
2081 mock_create_port.assert_called_once_with(
2082 {
2083 "net_id": net2_id,
2084 "use": "other",
2085 "port_security": False,
2086 "port_security_disable_strategy": "full",
2087 },
2088 name,
2089 created_items,
2090 )
2091 self.assertEqual(expected_net_list_vim, net_list_vim)
2092 self.assertEqual(external_network, expected_external_network)
2093 self.assertEqual(expected_no_secured_ports, no_secured_ports)
2094
2095 @patch.object(vimconnector, "_reload_connection")
2096 def test_prepare_network_for_vm_instance_use_fip_true_non_mgmt_net_port_security_true(
2097 self, mock_reload_connection
2098 ):
2099 """Nets have net-id, use_floating_ip is True in VIM config, non-mgmt network, net port security is True."""
2100 mock_create_port = CopyingMock()
2101 self.vimconn.config["use_floating_ip"] = True
2102 self.vimconn.config["no_port_security_extension"] = True
2103 mock_reload_connection.side_effect = None
2104 created_items = {}
2105
2106 net_list = [
2107 {
2108 "net_id": net2_id,
2109 "use": "other",
2110 "port_security": True,
2111 "port_security_disable_strategy": "full",
2112 }
2113 ]
2114 net_list_vim = []
2115 mock_create_port.side_effect = [
2116 (
2117 {
2118 "port": {
2119 "id": port2_id,
2120 "mac_address": mac_address,
2121 "name": name,
2122 },
2123 },
2124 {"port-dict": port2_id},
2125 ),
2126 ]
2127 external_network, no_secured_ports = [], []
2128 expected_external_network = []
2129 expected_no_secured_ports = []
2130 expected_net_list_vim = [{"port-dict": port2_id}]
2131 with patch.object(vimconnector, "_create_port", mock_create_port):
2132 self.vimconn._prepare_network_for_vminstance(
2133 name,
2134 net_list,
2135 created_items,
2136 net_list_vim,
2137 external_network,
2138 no_secured_ports,
2139 )
2140
2141 mock_create_port.assert_called_once_with(
2142 {
2143 "net_id": net2_id,
2144 "use": "other",
2145 "port_security": True,
2146 "port_security_disable_strategy": "full",
2147 },
2148 name,
2149 created_items,
2150 )
2151 self.assertEqual(expected_net_list_vim, net_list_vim)
2152 self.assertEqual(external_network, expected_external_network)
2153 self.assertEqual(expected_no_secured_ports, no_secured_ports)
2154
2155 @patch.object(vimconnector, "_reload_connection")
2156 def test_prepare_network_for_vm_instance_create_port_raise_exception(
2157 self, mock_reload_connection
2158 ):
2159 """_create_port method raise exception."""
2160 mock_create_port = CopyingMock()
2161 self.vimconn.config["use_floating_ip"] = True
2162 self.vimconn.config["no_port_security_extension"] = True
2163 mock_reload_connection.side_effect = None
2164 created_items = {}
2165
2166 net_list = [
2167 {
2168 "net_id": net2_id,
2169 "use": "other",
2170 "port_security": True,
2171 "port_security_disable_strategy": "full",
2172 }
2173 ]
2174 net_list_vim = []
2175 mock_create_port.side_effect = KeyError
2176 external_network, no_secured_ports = [], []
2177 expected_external_network = []
2178 expected_no_secured_ports = []
2179 expected_net_list_vim = []
2180 with patch.object(vimconnector, "_create_port", mock_create_port):
2181 with self.assertRaises(Exception) as err:
2182 self.vimconn._prepare_network_for_vminstance(
2183 name,
2184 net_list,
2185 created_items,
2186 net_list_vim,
2187 external_network,
2188 no_secured_ports,
2189 )
2190
2191 self.assertEqual(type(err.exception), KeyError)
2192
2193 mock_create_port.assert_called_once_with(
2194 {
2195 "net_id": net2_id,
2196 "use": "other",
2197 "port_security": True,
2198 "port_security_disable_strategy": "full",
2199 },
2200 name,
2201 created_items,
2202 )
2203 self.assertEqual(expected_net_list_vim, net_list_vim)
2204 self.assertEqual(external_network, expected_external_network)
2205 self.assertEqual(expected_no_secured_ports, no_secured_ports)
2206
2207 @patch.object(vimconnector, "_reload_connection")
2208 def test_prepare_network_for_vm_instance_reload_connection_raise_exception(
2209 self, mock_reload_connection
2210 ):
2211 """_reload_connection method raises exception."""
2212 mock_create_port = CopyingMock()
2213 mock_reload_connection.side_effect = VimConnConnectionException(
2214 "Connection failed."
2215 )
2216 self.vimconn.config["use_floating_ip"] = True
2217 self.vimconn.config["no_port_security_extension"] = True
2218 created_items = {}
2219
2220 net_list = [
2221 {
2222 "net_id": net2_id,
2223 "use": "other",
2224 "port_security": True,
2225 "port_security_disable_strategy": "full",
2226 }
2227 ]
2228 net_list_vim = []
2229 mock_create_port.side_effect = None
2230 external_network, no_secured_ports = [], []
2231 expected_external_network = []
2232 expected_no_secured_ports = []
2233 expected_net_list_vim = []
2234 with patch.object(vimconnector, "_create_port", mock_create_port):
2235 with self.assertRaises(Exception) as err:
2236 self.vimconn._prepare_network_for_vminstance(
2237 name,
2238 net_list,
2239 created_items,
2240 net_list_vim,
2241 external_network,
2242 no_secured_ports,
2243 )
2244
2245 self.assertEqual(type(err.exception), VimConnConnectionException)
2246 self.assertEqual(str(err.exception), "Connection failed.")
2247 mock_reload_connection.assert_called_once()
2248 mock_create_port.assert_not_called()
2249 self.assertEqual(expected_net_list_vim, net_list_vim)
2250 self.assertEqual(external_network, expected_external_network)
2251 self.assertEqual(expected_no_secured_ports, no_secured_ports)
2252
2253 def test_prepare_persistent_root_volumes_vim_using_volume_id(self):
2254 """Existing persistent root volume with vim_volume_id."""
2255 vm_av_zone = ["nova"]
2256 base_disk_index = ord("a")
2257 disk = {"vim_volume_id": volume_id}
2258 block_device_mapping = {}
2259 existing_vim_volumes = []
2260 created_items = {}
2261 expected_boot_vol_id = None
2262 expected_block_device_mapping = {"vda": volume_id}
2263 expected_existing_vim_volumes = [{"id": volume_id}]
2264 boot_volume_id = self.vimconn._prepare_persistent_root_volumes(
2265 name,
2266 vm_av_zone,
2267 disk,
2268 base_disk_index,
2269 block_device_mapping,
2270 existing_vim_volumes,
2271 created_items,
2272 )
2273 self.assertEqual(boot_volume_id, expected_boot_vol_id)
2274 self.assertDictEqual(block_device_mapping, expected_block_device_mapping)
2275 self.assertEqual(existing_vim_volumes, expected_existing_vim_volumes)
2276 self.vimconn.cinder.volumes.create.assert_not_called()
2277
2278 def test_prepare_persistent_non_root_volumes_vim_using_volume_id(self):
2279 """Existing persistent non root volume with vim_volume_id."""
2280 vm_av_zone = ["nova"]
2281 base_disk_index = ord("b")
2282 disk = {"vim_volume_id": volume_id}
2283 block_device_mapping = {}
2284 existing_vim_volumes = []
2285 created_items = {}
2286 expected_block_device_mapping = {"vdb": volume_id}
2287 expected_existing_vim_volumes = [{"id": volume_id}]
2288 self.vimconn._prepare_non_root_persistent_volumes(
2289 name,
2290 disk,
2291 vm_av_zone,
2292 block_device_mapping,
2293 base_disk_index,
2294 existing_vim_volumes,
2295 created_items,
2296 )
2297 self.assertDictEqual(block_device_mapping, expected_block_device_mapping)
2298 self.assertEqual(existing_vim_volumes, expected_existing_vim_volumes)
2299 self.vimconn.cinder.volumes.create.assert_not_called()
2300
2301 def test_prepare_persistent_root_volumes_using_vim_id(self):
2302 """Existing persistent root volume with vim_id."""
2303 vm_av_zone = ["nova"]
2304 base_disk_index = ord("a")
2305 disk = {"vim_id": volume_id}
2306 block_device_mapping = {}
2307 existing_vim_volumes = []
2308 created_items = {}
2309 expected_boot_vol_id = None
2310 expected_block_device_mapping = {"vda": volume_id}
2311 expected_existing_vim_volumes = [{"id": volume_id}]
2312 boot_volume_id = self.vimconn._prepare_persistent_root_volumes(
2313 name,
2314 vm_av_zone,
2315 disk,
2316 base_disk_index,
2317 block_device_mapping,
2318 existing_vim_volumes,
2319 created_items,
2320 )
2321 self.assertEqual(boot_volume_id, expected_boot_vol_id)
2322 self.assertDictEqual(block_device_mapping, expected_block_device_mapping)
2323 self.assertEqual(existing_vim_volumes, expected_existing_vim_volumes)
2324 self.vimconn.cinder.volumes.create.assert_not_called()
2325
2326 def test_prepare_persistent_non_root_volumes_using_vim_id(self):
2327 """Existing persistent root volume with vim_id."""
2328 vm_av_zone = ["nova"]
2329 base_disk_index = ord("b")
2330 disk = {"vim_id": volume_id}
2331 block_device_mapping = {}
2332 existing_vim_volumes = []
2333 created_items = {}
2334
2335 expected_block_device_mapping = {"vdb": volume_id}
2336 expected_existing_vim_volumes = [{"id": volume_id}]
2337 self.vimconn._prepare_non_root_persistent_volumes(
2338 name,
2339 disk,
2340 vm_av_zone,
2341 block_device_mapping,
2342 base_disk_index,
2343 existing_vim_volumes,
2344 created_items,
2345 )
2346
2347 self.assertDictEqual(block_device_mapping, expected_block_device_mapping)
2348 self.assertEqual(existing_vim_volumes, expected_existing_vim_volumes)
2349 self.vimconn.cinder.volumes.create.assert_not_called()
2350
2351 def test_prepare_persistent_root_volumes_create(self):
2352 """Create persistent root volume."""
2353 self.vimconn.cinder.volumes.create.return_value.id = volume_id2
2354 vm_av_zone = ["nova"]
2355 base_disk_index = ord("a")
2356 disk = {"size": 10, "image_id": image_id}
2357 block_device_mapping = {}
2358 existing_vim_volumes = []
2359 created_items = {}
2360 expected_boot_vol_id = volume_id2
2361 expected_block_device_mapping = {"vda": volume_id2}
2362 expected_existing_vim_volumes = []
2363 boot_volume_id = self.vimconn._prepare_persistent_root_volumes(
2364 name,
2365 vm_av_zone,
2366 disk,
2367 base_disk_index,
2368 block_device_mapping,
2369 existing_vim_volumes,
2370 created_items,
2371 )
2372 self.assertEqual(boot_volume_id, expected_boot_vol_id)
2373 self.assertDictEqual(block_device_mapping, expected_block_device_mapping)
2374 self.assertEqual(existing_vim_volumes, expected_existing_vim_volumes)
2375 self.vimconn.cinder.volumes.create.assert_called_once_with(
2376 size=10,
2377 name="basicvmvda",
2378 imageRef=image_id,
2379 availability_zone=["nova"],
2380 )
2381 self.assertEqual(created_items, {f"volume:{volume_id2}": True})
2382
2383 def test_prepare_persistent_non_root_volumes_create(self):
2384 """Create persistent non-root volume."""
2385 self.vimconn.cinder = CopyingMock()
2386 self.vimconn.cinder.volumes.create.return_value.id = volume_id2
2387 vm_av_zone = ["nova"]
2388 base_disk_index = ord("a")
2389 disk = {"size": 10}
2390 block_device_mapping = {}
2391 existing_vim_volumes = []
2392 created_items = {}
2393 expected_block_device_mapping = {"vda": volume_id2}
2394 expected_existing_vim_volumes = []
2395 self.vimconn._prepare_non_root_persistent_volumes(
2396 name,
2397 disk,
2398 vm_av_zone,
2399 block_device_mapping,
2400 base_disk_index,
2401 existing_vim_volumes,
2402 created_items,
2403 )
2404
2405 self.assertDictEqual(block_device_mapping, expected_block_device_mapping)
2406 self.assertEqual(existing_vim_volumes, expected_existing_vim_volumes)
2407 self.vimconn.cinder.volumes.create.assert_called_once_with(
2408 size=10, name="basicvmvda", availability_zone=["nova"]
2409 )
2410 self.assertEqual(created_items, {f"volume:{volume_id2}": True})
2411
2412 def test_prepare_persistent_root_volumes_create_raise_exception(self):
2413 """Create persistent root volume raise exception."""
2414 self.vimconn.cinder.volumes.create.side_effect = Exception
2415 vm_av_zone = ["nova"]
2416 base_disk_index = ord("a")
2417 disk = {"size": 10, "image_id": image_id}
2418 block_device_mapping = {}
2419 existing_vim_volumes = []
2420 created_items = {}
2421
2422 with self.assertRaises(Exception):
2423 result = self.vimconn._prepare_persistent_root_volumes(
2424 name,
2425 vm_av_zone,
2426 disk,
2427 base_disk_index,
2428 block_device_mapping,
2429 existing_vim_volumes,
2430 created_items,
2431 )
2432
2433 self.assertEqual(result, None)
2434
2435 self.vimconn.cinder.volumes.create.assert_called_once_with(
2436 size=10,
2437 name="basicvmvda",
2438 imageRef=image_id,
2439 availability_zone=["nova"],
2440 )
2441 self.assertEqual(existing_vim_volumes, [])
2442 self.assertEqual(block_device_mapping, {})
2443 self.assertEqual(created_items, {})
2444
2445 def test_prepare_persistent_non_root_volumes_create_raise_exception(self):
2446 """Create persistent non-root volume raise exception."""
2447 self.vimconn.cinder.volumes.create.side_effect = Exception
2448 vm_av_zone = ["nova"]
2449 base_disk_index = ord("b")
2450 disk = {"size": 10}
2451 block_device_mapping = {}
2452 existing_vim_volumes = []
2453 created_items = {}
2454
2455 with self.assertRaises(Exception):
2456 self.vimconn._prepare_non_root_persistent_volumes(
2457 name,
2458 disk,
2459 vm_av_zone,
2460 block_device_mapping,
2461 base_disk_index,
2462 existing_vim_volumes,
2463 created_items,
2464 )
2465
2466 self.vimconn.cinder.volumes.create.assert_called_once_with(
2467 size=10, name="basicvmvdb", availability_zone=["nova"]
2468 )
2469 self.assertEqual(existing_vim_volumes, [])
2470 self.assertEqual(block_device_mapping, {})
2471 self.assertEqual(created_items, {})
2472
2473 @patch("time.sleep")
2474 def test_wait_for_created_volumes_availability_volume_status_available(
2475 self, mock_sleep
2476 ):
2477 """Created volume status is available."""
2478 elapsed_time = 5
2479 created_items = {f"volume:{volume_id2}": True}
2480 self.vimconn.cinder.volumes.get.return_value.status = "available"
2481
2482 result = self.vimconn._wait_for_created_volumes_availability(
2483 elapsed_time, created_items
2484 )
2485 self.assertEqual(result, elapsed_time)
2486 self.vimconn.cinder.volumes.get.assert_called_with(volume_id2)
2487 mock_sleep.assert_not_called()
2488
2489 @patch("time.sleep")
2490 def test_wait_for_existing_volumes_availability_volume_status_available(
2491 self, mock_sleep
2492 ):
2493 """Existing volume status is available."""
2494 elapsed_time = 5
2495 existing_vim_volumes = [{"id": volume_id2}]
2496 self.vimconn.cinder.volumes.get.return_value.status = "available"
2497
2498 result = self.vimconn._wait_for_existing_volumes_availability(
2499 elapsed_time, existing_vim_volumes
2500 )
2501 self.assertEqual(result, elapsed_time)
2502 self.vimconn.cinder.volumes.get.assert_called_with(volume_id2)
2503 mock_sleep.assert_not_called()
2504
2505 @patch("time.sleep")
2506 def test_wait_for_created_volumes_availability_status_processing_multiple_volumes(
2507 self, mock_sleep
2508 ):
2509 """Created volume status is processing."""
2510 elapsed_time = 5
2511 created_items = {
2512 f"volume:{volume_id2}": True,
2513 f"volume:{volume_id3}": True,
2514 }
2515 self.vimconn.cinder.volumes.get.side_effect = [
2516 Status("processing"),
2517 Status("available"),
2518 Status("available"),
2519 ]
2520
2521 result = self.vimconn._wait_for_created_volumes_availability(
2522 elapsed_time, created_items
2523 )
2524 self.assertEqual(result, 10)
2525 _call_mock_get_volumes = self.vimconn.cinder.volumes.get.call_args_list
2526 self.assertEqual(_call_mock_get_volumes[0][0], (volume_id2,))
2527 self.assertEqual(_call_mock_get_volumes[1][0], (volume_id2,))
2528 self.assertEqual(_call_mock_get_volumes[2][0], (volume_id3,))
2529 mock_sleep.assert_called_with(5)
2530 self.assertEqual(1, mock_sleep.call_count)
2531
2532 @patch("time.sleep")
2533 def test_wait_for_existing_volumes_availability_status_processing_multiple_volumes(
2534 self, mock_sleep
2535 ):
2536 """Existing volume status is processing."""
2537 elapsed_time = 5
2538 existing_vim_volumes = [
2539 {"id": volume_id2},
2540 {"id": "44e0e83-b9uu-4akk-t234-p9cc4811bd4a"},
2541 ]
2542 self.vimconn.cinder.volumes.get.side_effect = [
2543 Status("processing"),
2544 Status("available"),
2545 Status("available"),
2546 ]
2547
2548 result = self.vimconn._wait_for_existing_volumes_availability(
2549 elapsed_time, existing_vim_volumes
2550 )
2551 self.assertEqual(result, 10)
2552 _call_mock_get_volumes = self.vimconn.cinder.volumes.get.call_args_list
2553 self.assertEqual(_call_mock_get_volumes[0][0], (volume_id2,))
2554 self.assertEqual(_call_mock_get_volumes[1][0], (volume_id2,))
2555 self.assertEqual(
2556 _call_mock_get_volumes[2][0], ("44e0e83-b9uu-4akk-t234-p9cc4811bd4a",)
2557 )
2558 mock_sleep.assert_called_with(5)
2559 self.assertEqual(1, mock_sleep.call_count)
2560
2561 @patch("time.sleep")
2562 def test_wait_for_created_volumes_availability_volume_status_processing_timeout(
2563 self, mock_sleep
2564 ):
2565 """Created volume status is processing, elapsed time greater than timeout (1800)."""
2566 elapsed_time = 1805
2567 created_items = {f"volume:{volume_id2}": True}
2568 self.vimconn.cinder.volumes.get.side_effect = [
2569 Status("processing"),
2570 Status("processing"),
2571 ]
2572 with patch("time.sleep", mock_sleep):
2573 result = self.vimconn._wait_for_created_volumes_availability(
2574 elapsed_time, created_items
2575 )
2576 self.assertEqual(result, 1805)
2577 self.vimconn.cinder.volumes.get.assert_not_called()
2578 mock_sleep.assert_not_called()
2579
2580 @patch("time.sleep")
2581 def test_wait_for_existing_volumes_availability_volume_status_processing_timeout(
2582 self, mock_sleep
2583 ):
2584 """Exsiting volume status is processing, elapsed time greater than timeout (1800)."""
2585 elapsed_time = 1805
2586 existing_vim_volumes = [{"id": volume_id2}]
2587 self.vimconn.cinder.volumes.get.side_effect = [
2588 Status("processing"),
2589 Status("processing"),
2590 ]
2591
2592 result = self.vimconn._wait_for_existing_volumes_availability(
2593 elapsed_time, existing_vim_volumes
2594 )
2595 self.assertEqual(result, 1805)
2596 self.vimconn.cinder.volumes.get.assert_not_called()
2597 mock_sleep.assert_not_called()
2598
2599 @patch("time.sleep")
2600 def test_wait_for_created_volumes_availability_cinder_raise_exception(
2601 self, mock_sleep
2602 ):
2603 """Cinder get volumes raises exception for created volumes."""
2604 elapsed_time = 1000
2605 created_items = {f"volume:{volume_id2}": True}
2606 self.vimconn.cinder.volumes.get.side_effect = Exception
2607 with self.assertRaises(Exception):
2608 result = self.vimconn._wait_for_created_volumes_availability(
2609 elapsed_time, created_items
2610 )
2611 self.assertEqual(result, 1000)
2612 self.vimconn.cinder.volumes.get.assert_called_with(volume_id2)
2613 mock_sleep.assert_not_called()
2614
2615 @patch("time.sleep")
2616 def test_wait_for_existing_volumes_availability_cinder_raise_exception(
2617 self, mock_sleep
2618 ):
2619 """Cinder get volumes raises exception for existing volumes."""
2620 elapsed_time = 1000
2621 existing_vim_volumes = [{"id": volume_id2}]
2622 self.vimconn.cinder.volumes.get.side_effect = Exception
2623 with self.assertRaises(Exception):
2624 result = self.vimconn._wait_for_existing_volumes_availability(
2625 elapsed_time, existing_vim_volumes
2626 )
2627 self.assertEqual(result, 1000)
2628 self.vimconn.cinder.volumes.get.assert_called_with(volume_id2)
2629 mock_sleep.assert_not_called()
2630
2631 @patch("time.sleep")
2632 def test_wait_for_created_volumes_availability_no_volume_in_created_items(
2633 self, mock_sleep
2634 ):
2635 """Created_items dict does not have volume-id."""
2636 elapsed_time = 10
2637 created_items = {}
2638
2639 self.vimconn.cinder.volumes.get.side_effect = [None]
2640
2641 result = self.vimconn._wait_for_created_volumes_availability(
2642 elapsed_time, created_items
2643 )
2644 self.assertEqual(result, 10)
2645 self.vimconn.cinder.volumes.get.assert_not_called()
2646 mock_sleep.assert_not_called()
2647
2648 @patch("time.sleep")
2649 def test_wait_for_existing_volumes_availability_no_volume_in_existing_vim_volumes(
2650 self, mock_sleep
2651 ):
2652 """Existing_vim_volumes list does not have volume."""
2653 elapsed_time = 10
2654 existing_vim_volumes = []
2655
2656 self.vimconn.cinder.volumes.get.side_effect = [None]
2657
2658 result = self.vimconn._wait_for_existing_volumes_availability(
2659 elapsed_time, existing_vim_volumes
2660 )
2661 self.assertEqual(result, 10)
2662 self.vimconn.cinder.volumes.get.assert_not_called()
2663 mock_sleep.assert_not_called()
2664
2665 @patch.object(vimconnector, "_prepare_persistent_root_volumes")
2666 @patch.object(vimconnector, "_prepare_non_root_persistent_volumes")
2667 @patch.object(vimconnector, "_wait_for_created_volumes_availability")
2668 @patch.object(vimconnector, "_wait_for_existing_volumes_availability")
2669 def test_prepare_disk_for_vm_instance(
2670 self,
2671 mock_existing_vol_availability,
2672 mock_created_vol_availability,
2673 mock_non_root_volumes,
2674 mock_root_volumes,
2675 ):
2676 """Prepare disks for VM instance successfully."""
2677 existing_vim_volumes = []
2678 created_items = {}
2679 block_device_mapping = {}
2680 vm_av_zone = ["nova"]
2681
2682 mock_root_volumes.return_value = root_vol_id
2683 mock_created_vol_availability.return_value = 10
2684 mock_existing_vol_availability.return_value = 15
2685 self.vimconn.cinder = CopyingMock()
2686
2687 self.vimconn._prepare_disk_for_vminstance(
2688 name,
2689 existing_vim_volumes,
2690 created_items,
2691 vm_av_zone,
2692 block_device_mapping,
2693 disk_list2,
2694 )
2695 self.vimconn.cinder.volumes.set_bootable.assert_called_once_with(
2696 root_vol_id, True
2697 )
2698 mock_created_vol_availability.assert_called_once_with(0, created_items)
2699 mock_existing_vol_availability.assert_called_once_with(10, existing_vim_volumes)
2700 self.assertEqual(mock_root_volumes.call_count, 1)
2701 self.assertEqual(mock_non_root_volumes.call_count, 1)
2702 mock_root_volumes.assert_called_once_with(
2703 name="basicvm",
2704 vm_av_zone=["nova"],
2705 disk={"size": 10, "image_id": image_id},
2706 base_disk_index=97,
2707 block_device_mapping={},
2708 existing_vim_volumes=[],
2709 created_items={},
2710 )
2711 mock_non_root_volumes.assert_called_once_with(
2712 name="basicvm",
2713 disk={"size": 20},
2714 vm_av_zone=["nova"],
2715 base_disk_index=98,
2716 block_device_mapping={},
2717 existing_vim_volumes=[],
2718 created_items={},
2719 )
2720
2721 @patch.object(vimconnector, "_prepare_persistent_root_volumes")
2722 @patch.object(vimconnector, "_prepare_non_root_persistent_volumes")
2723 @patch.object(vimconnector, "_wait_for_created_volumes_availability")
2724 @patch.object(vimconnector, "_wait_for_existing_volumes_availability")
2725 def test_prepare_disk_for_vm_instance_timeout_exceeded(
2726 self,
2727 mock_existing_vol_availability,
2728 mock_created_vol_availability,
2729 mock_non_root_volumes,
2730 mock_root_volumes,
2731 ):
2732 """Timeout exceeded while waiting for disks."""
2733 existing_vim_volumes = []
2734 created_items = {}
2735 vm_av_zone = ["nova"]
2736 block_device_mapping = {}
2737
2738 mock_root_volumes.return_value = root_vol_id
2739 mock_created_vol_availability.return_value = 1700
2740 mock_existing_vol_availability.return_value = 1900
2741
2742 with self.assertRaises(VimConnException) as err:
2743 self.vimconn._prepare_disk_for_vminstance(
2744 name,
2745 existing_vim_volumes,
2746 created_items,
2747 vm_av_zone,
2748 block_device_mapping,
2749 disk_list2,
2750 )
2751 self.assertEqual(
2752 str(err.exception), "Timeout creating volumes for instance basicvm"
2753 )
2754 self.vimconn.cinder.volumes.set_bootable.assert_not_called()
2755 mock_created_vol_availability.assert_called_once_with(0, created_items)
2756 mock_existing_vol_availability.assert_called_once_with(
2757 1700, existing_vim_volumes
2758 )
2759 self.assertEqual(mock_root_volumes.call_count, 1)
2760 self.assertEqual(mock_non_root_volumes.call_count, 1)
2761 mock_root_volumes.assert_called_once_with(
2762 name="basicvm",
2763 vm_av_zone=["nova"],
2764 disk={"size": 10, "image_id": image_id},
2765 base_disk_index=97,
2766 block_device_mapping={},
2767 existing_vim_volumes=[],
2768 created_items={},
2769 )
2770 mock_non_root_volumes.assert_called_once_with(
2771 name="basicvm",
2772 disk={"size": 20},
2773 vm_av_zone=["nova"],
2774 base_disk_index=98,
2775 block_device_mapping={},
2776 existing_vim_volumes=[],
2777 created_items={},
2778 )
2779
2780 @patch.object(vimconnector, "_prepare_persistent_root_volumes")
2781 @patch.object(vimconnector, "_prepare_non_root_persistent_volumes")
2782 @patch.object(vimconnector, "_wait_for_created_volumes_availability")
2783 @patch.object(vimconnector, "_wait_for_existing_volumes_availability")
2784 def test_prepare_disk_for_vm_instance_empty_disk_list(
2785 self,
2786 mock_existing_vol_availability,
2787 mock_created_vol_availability,
2788 mock_non_root_volumes,
2789 mock_root_volumes,
2790 ):
2791 """Disk list is empty."""
2792 existing_vim_volumes = []
2793 created_items = {}
2794 block_device_mapping = {}
2795 vm_av_zone = ["nova"]
2796 mock_created_vol_availability.return_value = 2
2797 mock_existing_vol_availability.return_value = 3
2798
2799 self.vimconn._prepare_disk_for_vminstance(
2800 name,
2801 existing_vim_volumes,
2802 created_items,
2803 vm_av_zone,
2804 block_device_mapping,
2805 disk_list,
2806 )
2807 self.vimconn.cinder.volumes.set_bootable.assert_not_called()
2808 mock_created_vol_availability.assert_called_once_with(0, created_items)
2809 mock_existing_vol_availability.assert_called_once_with(2, existing_vim_volumes)
2810 mock_root_volumes.assert_not_called()
2811 mock_non_root_volumes.assert_not_called()
2812
2813 @patch.object(vimconnector, "_prepare_persistent_root_volumes")
2814 @patch.object(vimconnector, "_prepare_non_root_persistent_volumes")
2815 @patch.object(vimconnector, "_wait_for_created_volumes_availability")
2816 @patch.object(vimconnector, "_wait_for_existing_volumes_availability")
2817 def test_prepare_disk_for_vm_instance_persistent_root_volume_error(
2818 self,
2819 mock_existing_vol_availability,
2820 mock_created_vol_availability,
2821 mock_non_root_volumes,
2822 mock_root_volumes,
2823 ):
2824 """Persistent root volumes preparation raises error."""
2825 existing_vim_volumes = []
2826 created_items = {}
2827 vm_av_zone = ["nova"]
2828 block_device_mapping = {}
2829
2830 mock_root_volumes.side_effect = Exception()
2831 mock_created_vol_availability.return_value = 10
2832 mock_existing_vol_availability.return_value = 15
2833
2834 with self.assertRaises(Exception):
2835 self.vimconn._prepare_disk_for_vminstance(
2836 name,
2837 existing_vim_volumes,
2838 created_items,
2839 vm_av_zone,
2840 block_device_mapping,
2841 disk_list2,
2842 )
2843 self.vimconn.cinder.volumes.set_bootable.assert_not_called()
2844 mock_created_vol_availability.assert_not_called()
2845 mock_existing_vol_availability.assert_not_called()
2846 mock_root_volumes.assert_called_once_with(
2847 name="basicvm",
2848 vm_av_zone=["nova"],
2849 disk={"size": 10, "image_id": image_id},
2850 base_disk_index=97,
2851 block_device_mapping={},
2852 existing_vim_volumes=[],
2853 created_items={},
2854 )
2855 mock_non_root_volumes.assert_not_called()
2856
2857 @patch.object(vimconnector, "_prepare_persistent_root_volumes")
2858 @patch.object(vimconnector, "_prepare_non_root_persistent_volumes")
2859 @patch.object(vimconnector, "_wait_for_created_volumes_availability")
2860 @patch.object(vimconnector, "_wait_for_existing_volumes_availability")
2861 def test_prepare_disk_for_vm_instance_non_root_volume_error(
2862 self,
2863 mock_existing_vol_availability,
2864 mock_created_vol_availability,
2865 mock_non_root_volumes,
2866 mock_root_volumes,
2867 ):
2868 """Non-root volumes preparation raises error."""
2869 existing_vim_volumes = []
2870 created_items = {}
2871 vm_av_zone = ["nova"]
2872 block_device_mapping = {}
2873
2874 mock_root_volumes.return_value = root_vol_id
2875 mock_non_root_volumes.side_effect = Exception
2876
2877 with self.assertRaises(Exception):
2878 self.vimconn._prepare_disk_for_vminstance(
2879 name,
2880 existing_vim_volumes,
2881 created_items,
2882 vm_av_zone,
2883 block_device_mapping,
2884 disk_list2,
2885 )
2886 self.vimconn.cinder.volumes.set_bootable.assert_not_called()
2887 mock_created_vol_availability.assert_not_called()
2888 mock_existing_vol_availability.assert_not_called()
2889 self.assertEqual(mock_root_volumes.call_count, 1)
2890 self.assertEqual(mock_non_root_volumes.call_count, 1)
2891 mock_root_volumes.assert_called_once_with(
2892 name="basicvm",
2893 vm_av_zone=["nova"],
2894 disk={"size": 10, "image_id": image_id},
2895 base_disk_index=97,
2896 block_device_mapping={},
2897 existing_vim_volumes=[],
2898 created_items={},
2899 )
2900 mock_non_root_volumes.assert_called_once_with(
2901 name="basicvm",
2902 disk={"size": 20},
2903 vm_av_zone=["nova"],
2904 base_disk_index=98,
2905 block_device_mapping={},
2906 existing_vim_volumes=[],
2907 created_items={},
2908 )
2909
2910 def test_find_external_network_for_floating_ip_no_external_network(self):
2911 """External network could not be found."""
2912 self.vimconn.neutron.list_networks.return_value = {
2913 "networks": [
2914 {"id": "408b73-r9cc-5a6a-a270-82cc4811bd4a", "router:external": False}
2915 ]
2916 }
2917 with self.assertRaises(VimConnException) as err:
2918 self.vimconn._find_the_external_network_for_floating_ip()
2919 self.assertEqual(
2920 str(err.exception),
2921 "Cannot create floating_ip automatically since no external network is present",
2922 )
2923
2924 def test_find_external_network_for_floating_one_external_network(self):
2925 """One external network has been found."""
2926 self.vimconn.neutron.list_networks.return_value = {
2927 "networks": [
2928 {"id": "408b73-r9cc-5a6a-a270-82cc4811bd4a", "router:external": True}
2929 ]
2930 }
2931 expected_result = "408b73-r9cc-5a6a-a270-82cc4811bd4a"
2932 result = self.vimconn._find_the_external_network_for_floating_ip()
2933 self.assertEqual(result, expected_result)
2934
2935 def test_find_external_network_for_floating_neutron_raises_exception(self):
2936 """Neutron list networks raises exception."""
2937 self.vimconn.neutron.list_networks.side_effect = Exception
2938 with self.assertRaises(Exception):
2939 self.vimconn._find_the_external_network_for_floating_ip()
2940
2941 def test_find_external_network_for_floating_several_external_network(self):
2942 """Several exernal networks has been found."""
2943 self.vimconn.neutron.list_networks.return_value = {
2944 "networks": [
2945 {"id": "408b73-r9cc-5a6a-a270-82cc4811bd4a", "router:external": True},
2946 {"id": "608b73-y9cc-5a6a-a270-12cc4811bd4a", "router:external": True},
2947 ]
2948 }
2949 with self.assertRaises(VimConnException) as err:
2950 self.vimconn._find_the_external_network_for_floating_ip()
2951 self.assertEqual(
2952 str(err.exception),
2953 "Cannot create floating_ip automatically since multiple external networks are present",
2954 )
2955
2956 def test_neutron_create_float_ip(self):
2957 """Floating ip creation is successful."""
2958 param = {"net_id": "408b73-r9cc-5a6a-a270-p2cc4811bd9a"}
2959 created_items = {}
2960 self.vimconn.neutron.create_floatingip.return_value = {
2961 "floatingip": {"id": "308b73-t9cc-1a6a-a270-12cc4811bd4a"}
2962 }
2963 expected_created_items = {
2964 "floating_ip:308b73-t9cc-1a6a-a270-12cc4811bd4a": True
2965 }
2966 self.vimconn._neutron_create_float_ip(param, created_items)
2967 self.assertEqual(created_items, expected_created_items)
2968
2969 def test_neutron_create_float_ip_exception_occurred(self):
2970 """Floating ip could not be created."""
2971 param = {
2972 "floatingip": {
2973 "floating_network_id": "408b73-r9cc-5a6a-a270-p2cc4811bd9a",
2974 "tenant_id": "308b73-19cc-8a6a-a270-02cc4811bd9a",
2975 }
2976 }
2977 created_items = {}
2978 self.vimconn.neutron = CopyingMock()
2979 self.vimconn.neutron.create_floatingip.side_effect = Exception(
2980 "Neutron floating ip create exception occurred."
2981 )
2982 with self.assertRaises(VimConnException) as err:
2983 self.vimconn._neutron_create_float_ip(param, created_items)
2984 self.assertEqual(created_items, {})
2985 self.assertEqual(
2986 str(err.exception),
2987 "Exception: Cannot create new floating_ip Neutron floating ip create exception occurred.",
2988 )
2989
2990 @patch.object(vimconnector, "_neutron_create_float_ip")
2991 @patch.object(vimconnector, "_find_the_external_network_for_floating_ip")
2992 def test_create_floating_ip_pool_id_available(
2993 self, mock_find_ext_network, mock_create_float_ip
2994 ):
2995 """Floating ip creation, ip pool is available."""
2996 floating_network = {"floating_ip": "308b73-t9cc-1a6a-a270-12cc4811bd4a"}
2997 created_items = {}
2998 expected_param = {
2999 "floatingip": {
3000 "floating_network_id": "308b73-t9cc-1a6a-a270-12cc4811bd4a",
3001 "tenant_id": "408b73-r9cc-5a6a-a270-82cc4811bd4a",
3002 }
3003 }
3004 self.vimconn._create_floating_ip(floating_network, self.server, created_items)
3005 mock_find_ext_network.assert_not_called()
3006 mock_create_float_ip.assert_called_once_with(expected_param, {})
3007
3008 @patch.object(vimconnector, "_neutron_create_float_ip")
3009 @patch.object(vimconnector, "_find_the_external_network_for_floating_ip")
3010 def test_create_floating_ip_finding_pool_id(
3011 self, mock_find_ext_network, mock_create_float_ip
3012 ):
3013 """Floating ip creation, pool id need to be found."""
3014 floating_network = {"floating_ip": True}
3015 created_items = {}
3016 mock_find_ext_network.return_value = "308b73-t9cc-1a6a-a270-12cc4811bd4a"
3017 expected_param = {
3018 "floatingip": {
3019 "floating_network_id": "308b73-t9cc-1a6a-a270-12cc4811bd4a",
3020 "tenant_id": "408b73-r9cc-5a6a-a270-82cc4811bd4a",
3021 }
3022 }
3023 self.vimconn._create_floating_ip(floating_network, self.server, created_items)
3024 mock_find_ext_network.assert_called_once()
3025 mock_create_float_ip.assert_called_once_with(expected_param, {})
3026
3027 @patch.object(vimconnector, "_neutron_create_float_ip")
3028 @patch.object(vimconnector, "_find_the_external_network_for_floating_ip")
3029 def test_create_floating_ip_neutron_create_floating_ip_exception(
3030 self, mock_find_ext_network, mock_create_float_ip
3031 ):
3032 """Neutron creat floating ip raises error."""
3033 floating_network = {"floating_ip": True}
3034 created_items = {}
3035 mock_create_float_ip.side_effect = VimConnException(
3036 "Can not create floating ip."
3037 )
3038 mock_find_ext_network.return_value = "308b73-t9cc-1a6a-a270-12cc4811bd4a"
3039 expected_param = {
3040 "floatingip": {
3041 "floating_network_id": "308b73-t9cc-1a6a-a270-12cc4811bd4a",
3042 "tenant_id": "408b73-r9cc-5a6a-a270-82cc4811bd4a",
3043 }
3044 }
3045
3046 with self.assertRaises(VimConnException) as err:
3047 self.vimconn._create_floating_ip(
3048 floating_network, self.server, created_items
3049 )
3050 self.assertEqual(str(err.exception), "Can not create floating ip.")
3051 mock_find_ext_network.assert_called_once()
3052 mock_create_float_ip.assert_called_once_with(expected_param, {})
3053
3054 @patch.object(vimconnector, "_neutron_create_float_ip")
3055 @patch.object(vimconnector, "_find_the_external_network_for_floating_ip")
3056 def test_create_floating_ip_can_not_find_pool_id(
3057 self, mock_find_ext_network, mock_create_float_ip
3058 ):
3059 """Floating ip creation, pool id could not be found."""
3060 floating_network = {"floating_ip": True}
3061 created_items = {}
3062 mock_find_ext_network.side_effect = VimConnException(
3063 "Cannot create floating_ip automatically since no external network is present"
3064 )
3065 with self.assertRaises(VimConnException) as err:
3066 self.vimconn._create_floating_ip(
3067 floating_network, self.server, created_items
3068 )
3069 self.assertEqual(
3070 str(err.exception),
3071 "Cannot create floating_ip automatically since no external network is present",
3072 )
3073 mock_find_ext_network.assert_called_once()
3074 mock_create_float_ip.assert_not_called()
3075
3076 def test_find_floating_ip_get_free_floating_ip(self):
3077 """Get free floating ips successfully."""
3078 floating_ips = [
3079 {
3080 "tenant_id": "408b73-r9cc-5a6a-a270-82cc4811bd4a",
3081 "floating_network_id": "308b73-t9cc-1a6a-a270-12cc4811bd4a",
3082 "id": "508b73-o9cc-5a6a-a270-72cc4811bd8",
3083 }
3084 ]
3085 floating_network = {"floating_ip": "308b73-t9cc-1a6a-a270-12cc4811bd4a"}
3086 expected_result = "508b73-o9cc-5a6a-a270-72cc4811bd8"
3087
3088 result = self.vimconn._find_floating_ip(
3089 self.server, floating_ips, floating_network
3090 )
3091 self.assertEqual(result, expected_result)
3092
3093 def test_find_floating_ip_different_floating_network_id(self):
3094 """Floating network id is different with floating_ip of floating network."""
3095 floating_ips = [
3096 {
3097 "floating_network_id": "308b73-t9cc-1a6a-a270-12cc4811bd4a",
3098 "id": "508b73-o9cc-5a6a-a270-72cc4811bd8",
3099 }
3100 ]
3101 floating_network = {"floating_ip": "508b73-t9cc-1a6a-a270-12cc4811bd4a"}
3102
3103 result = self.vimconn._find_floating_ip(
3104 self.server, floating_ips, floating_network
3105 )
3106 self.assertEqual(result, None)
3107
3108 def test_find_floating_ip_different_fip_tenant(self):
3109 """Items in floating_ips has port_id, tenant_is is not same with server tenant id."""
3110 floating_ips = [
3111 {
3112 "port_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3113 "floating_network_id": "308b73-t9cc-1a6a-a270-12cc4811bd4a",
3114 "id": "508b73-o9cc-5a6a-a270-72cc4811bd8",
3115 "tenant_id": self.server.id,
3116 }
3117 ]
3118 floating_network = {"floating_ip": "308b73-t9cc-1a6a-a270-12cc4811bd4a"}
3119 mock_create_floating_ip = CopyingMock()
3120 with patch.object(vimconnector, "_create_floating_ip", mock_create_floating_ip):
3121 result = self.vimconn._find_floating_ip(
3122 self.server, floating_ips, floating_network
3123 )
3124 self.assertEqual(result, None)
3125
3126 @patch("time.sleep")
3127 def test_assign_floating_ip(self, mock_sleep):
3128 """Assign floating ip successfully."""
3129 free_floating_ip = "508b73-o9cc-5a6a-a270-72cc4811bd8"
3130 floating_network = {"vim_id": floating_network_vim_id}
3131 fip = {
3132 "port_id": floating_network_vim_id,
3133 "floating_network_id": "p08b73-e9cc-5a6a-t270-82cc4811bd4a",
3134 "id": "508b73-o9cc-5a6a-a270-72cc4811bd8",
3135 "tenant_id": "k08b73-e9cc-5a6a-t270-82cc4811bd4a",
3136 }
3137 self.vimconn.neutron.update_floatingip.side_effect = None
3138 self.vimconn.neutron.show_floatingip.return_value = fip
3139 expected_result = fip
3140
3141 result = self.vimconn._assign_floating_ip(free_floating_ip, floating_network)
3142 self.assertEqual(result, expected_result)
3143 self.vimconn.neutron.update_floatingip.assert_called_once_with(
3144 free_floating_ip,
3145 {"floatingip": {"port_id": floating_network_vim_id}},
3146 )
3147 mock_sleep.assert_called_once_with(5)
3148 self.vimconn.neutron.show_floatingip.assert_called_once_with(free_floating_ip)
3149
3150 @patch("time.sleep")
3151 def test_assign_floating_ip_update_floating_ip_exception(self, mock_sleep):
3152 """Neutron update floating ip raises exception."""
3153 free_floating_ip = "508b73-o9cc-5a6a-a270-72cc4811bd8"
3154 floating_network = {"vim_id": floating_network_vim_id}
3155 self.vimconn.neutron = CopyingMock()
3156 self.vimconn.neutron.update_floatingip.side_effect = Exception(
3157 "Floating ip is not updated."
3158 )
3159
3160 with self.assertRaises(Exception) as err:
3161 result = self.vimconn._assign_floating_ip(
3162 free_floating_ip, floating_network
3163 )
3164 self.assertEqual(result, None)
3165 self.assertEqual(str(err.exception), "Floating ip is not updated.")
3166
3167 self.vimconn.neutron.update_floatingip.assert_called_once_with(
3168 free_floating_ip,
3169 {"floatingip": {"port_id": floating_network_vim_id}},
3170 )
3171 mock_sleep.assert_not_called()
3172 self.vimconn.neutron.show_floatingip.assert_not_called()
3173
3174 @patch("time.sleep")
3175 def test_assign_floating_ip_show_floating_ip_exception(self, mock_sleep):
3176 """Neutron show floating ip raises exception."""
3177 free_floating_ip = "508b73-o9cc-5a6a-a270-72cc4811bd8"
3178 floating_network = {"vim_id": floating_network_vim_id}
3179 self.vimconn.neutron.update_floatingip.side_effect = None
3180 self.vimconn.neutron.show_floatingip.side_effect = Exception(
3181 "Floating ip could not be shown."
3182 )
3183
3184 with self.assertRaises(Exception) as err:
3185 result = self.vimconn._assign_floating_ip(
3186 free_floating_ip, floating_network
3187 )
3188 self.assertEqual(result, None)
3189 self.assertEqual(str(err.exception), "Floating ip could not be shown.")
3190 self.vimconn.neutron.update_floatingip.assert_called_once_with(
3191 free_floating_ip,
3192 {"floatingip": {"port_id": floating_network_vim_id}},
3193 )
3194 mock_sleep.assert_called_once_with(5)
3195 self.vimconn.neutron.show_floatingip.assert_called_once_with(free_floating_ip)
3196
3197 @patch("random.shuffle")
3198 @patch.object(vimconnector, "_find_floating_ip")
3199 def test_get_free_floating_ip(self, mock_find_floating_ip, mock_shuffle):
3200 """Get free floating ip successfully."""
3201 floating_network = {"floating_ip": "308b73-t9cc-1a6a-a270-12cc4811bd4a"}
3202 floating_ips = [
3203 {
3204 "port_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3205 "floating_network_id": "308b73-t9cc-1a6a-a270-12cc4811bd4a",
3206 "id": "508b73-o9cc-5a6a-a270-72cc4811bd8",
3207 "tenant_id": "208b73-e9cc-5a6a-t270-82cc4811bd4a",
3208 },
3209 {
3210 "port_id": "508b73-r9cc-5a6a-5270-o2cc4811bd4a",
3211 "floating_network_id": "308b73-t9cc-1a6a-a270-12cc4811bd4a",
3212 "id": "208b73-o9cc-5a6a-a270-52cc4811bd8",
3213 "tenant_id": "208b73-e9cc-5a6a-t270-82cc4811bd4a",
3214 },
3215 ]
3216 self.vimconn.neutron.list_floatingips.return_value = {
3217 "floatingips": floating_ips
3218 }
3219 mock_find_floating_ip.return_value = "508b73-o9cc-5a6a-a270-72cc4811bd8"
3220 expected_result = "508b73-o9cc-5a6a-a270-72cc4811bd8"
3221
3222 result = self.vimconn._get_free_floating_ip(self.server, floating_network)
3223 self.assertEqual(result, expected_result)
3224 mock_shuffle.assert_called_once_with(floating_ips)
3225 mock_find_floating_ip.assert_called_once_with(
3226 self.server, floating_ips, floating_network
3227 )
3228
3229 @patch("random.shuffle")
3230 @patch.object(vimconnector, "_find_floating_ip")
3231 def test_get_free_floating_ip_list_floating_ip_exception(
3232 self, mock_find_floating_ip, mock_shuffle
3233 ):
3234 """Neutron list floating IPs raises exception."""
3235 floating_network = {"floating_ip": "308b73-t9cc-1a6a-a270-12cc4811bd4a"}
3236 self.vimconn.neutron = CopyingMock()
3237 self.vimconn.neutron.list_floatingips.side_effect = Exception(
3238 "Floating ips could not be listed."
3239 )
3240 with self.assertRaises(Exception) as err:
3241 result = self.vimconn._get_free_floating_ip(self.server, floating_network)
3242 self.assertEqual(result, None)
3243 self.assertEqual(str(err.exception), "Floating ips could not be listed.")
3244 mock_shuffle.assert_not_called()
3245 mock_find_floating_ip.assert_not_called()
3246
3247 @patch("random.shuffle")
3248 @patch.object(vimconnector, "_find_floating_ip")
3249 def test_get_free_floating_ip_find_floating_ip_exception(
3250 self, mock_find_floating_ip, mock_shuffle
3251 ):
3252 """_find_floating_ip method raises exception."""
3253 floating_network = {"floating_ip": "308b73-t9cc-1a6a-a270-12cc4811bd4a"}
3254 floating_ips = [
3255 {
3256 "port_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3257 "floating_network_id": "308b73-t9cc-1a6a-a270-12cc4811bd4a",
3258 "id": "508b73-o9cc-5a6a-a270-72cc4811bd8",
3259 "tenant_id": "208b73-e9cc-5a6a-t270-82cc4811bd4a",
3260 },
3261 {
3262 "port_id": "508b73-r9cc-5a6a-5270-o2cc4811bd4a",
3263 "floating_network_id": "308b73-t9cc-1a6a-a270-12cc4811bd4a",
3264 "id": "208b73-o9cc-5a6a-a270-52cc4811bd8",
3265 "tenant_id": "208b73-e9cc-5a6a-t270-82cc4811bd4a",
3266 },
3267 ]
3268 self.vimconn.neutron = CopyingMock()
3269 self.vimconn.neutron.list_floatingips.return_value = {
3270 "floatingips": floating_ips
3271 }
3272 mock_find_floating_ip.side_effect = Exception(
3273 "Free floating ip could not be found."
3274 )
3275
3276 with self.assertRaises(Exception) as err:
3277 result = self.vimconn._get_free_floating_ip(self.server, floating_network)
3278 self.assertEqual(result, None)
3279 self.assertEqual(str(err.exception), "Free floating ip could not be found.")
3280 mock_shuffle.assert_called_once_with(floating_ips)
3281 mock_find_floating_ip.assert_called_once_with(
3282 self.server, floating_ips, floating_network
3283 )
3284
3285 @patch.object(vimconnector, "_create_floating_ip")
3286 @patch.object(vimconnector, "_get_free_floating_ip")
3287 @patch.object(vimconnector, "_assign_floating_ip")
3288 def test_prepare_external_network_for_vm_instance(
3289 self,
3290 mock_assign_floating_ip,
3291 mock_get_free_floating_ip,
3292 mock_create_floating_ip,
3293 ):
3294 """Prepare external network successfully."""
3295 external_network = [
3296 {
3297 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3298 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3299 },
3300 ]
3301 created_items = {}
3302 vm_start_time = time_return_value
3303 mock_get_free_floating_ip.side_effect = ["y08b73-o9cc-1a6a-a270-12cc4811bd4u"]
3304 mock_assign_floating_ip.return_value = {
3305 "floatingip": {"port_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a"}
3306 }
3307 self.vimconn.neutron = CopyingMock()
3308 self.vimconn.nova = CopyingMock()
3309 self.vimconn.neutron.show_floatingip.return_value = {
3310 "floatingip": {"port_id": ""}
3311 }
3312
3313 self.vimconn._prepare_external_network_for_vminstance(
3314 external_network, self.server, created_items, vm_start_time
3315 )
3316
3317 self.assertEqual(mock_get_free_floating_ip.call_count, 1)
3318 mock_get_free_floating_ip.assert_called_once_with(
3319 self.server,
3320 {
3321 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3322 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3323 },
3324 )
3325 self.vimconn.neutron.show_floatingip.assert_called_once_with(
3326 "y08b73-o9cc-1a6a-a270-12cc4811bd4u"
3327 )
3328 self.vimconn.nova.servers.get.assert_not_called()
3329 mock_create_floating_ip.assert_not_called()
3330 mock_assign_floating_ip.assert_called_once_with(
3331 "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3332 {
3333 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3334 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3335 },
3336 )
3337
3338 @patch("time.time")
3339 @patch("time.sleep")
3340 @patch.object(vimconnector, "_create_floating_ip")
3341 @patch.object(vimconnector, "_get_free_floating_ip")
3342 @patch.object(vimconnector, "_assign_floating_ip")
3343 def test_prepare_external_network_for_vm_instance_no_free_floating_ip(
3344 self,
3345 mock_assign_floating_ip,
3346 mock_get_free_floating_ip,
3347 mock_create_floating_ip,
3348 mock_sleep,
3349 mock_time,
3350 ):
3351 """There is not any free floating ip."""
3352 floating_network = {
3353 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3354 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3355 }
3356 external_network = [floating_network]
3357
3358 created_items = {}
3359 vm_start_time = time_return_value
3360 mock_get_free_floating_ip.return_value = None
3361 mock_assign_floating_ip.return_value = {}
3362 self.vimconn.nova.servers.get.return_value.status = "ERROR"
3363 self.vimconn.neutron.show_floatingip.return_value = {}
3364
3365 with self.assertRaises(KeyError):
3366 self.vimconn._prepare_external_network_for_vminstance(
3367 external_network, self.server, created_items, vm_start_time
3368 )
3369
3370 self.assertEqual(mock_get_free_floating_ip.call_count, 4)
3371 mock_get_free_floating_ip.assert_called_with(
3372 self.server,
3373 {
3374 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3375 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3376 },
3377 )
3378 self.vimconn.neutron.show_floatingip.assert_called_with(None)
3379 mock_sleep.assert_not_called()
3380 mock_time.assert_not_called()
3381 self.assertEqual(self.vimconn.nova.servers.get.call_count, 4)
3382 mock_create_floating_ip.assert_called_with(
3383 floating_network, self.server, created_items
3384 )
3385 self.assertEqual(mock_create_floating_ip.call_count, 4)
3386 mock_assign_floating_ip.assert_not_called()
3387 self.vimconn.nova.servers.get.assert_called_with(self.server.id)
3388
3389 @patch("time.time")
3390 @patch("time.sleep")
3391 @patch.object(vimconnector, "_create_floating_ip")
3392 @patch.object(vimconnector, "_get_free_floating_ip")
3393 @patch.object(vimconnector, "_assign_floating_ip")
3394 def test_prepare_external_network_for_vm_instance_no_free_fip_can_not_create_fip_exit_on_error_false(
3395 self,
3396 mock_assign_floating_ip,
3397 mock_get_free_floating_ip,
3398 mock_create_floating_ip,
3399 mock_sleep,
3400 mock_time,
3401 ):
3402 """There is not any free floating ip, create_floating ip method raise exception
3403 exit_on_floating_ip_error set to False."""
3404 floating_network = {
3405 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3406 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3407 "exit_on_floating_ip_error": False,
3408 }
3409 external_network = [floating_network]
3410
3411 created_items = {}
3412 vm_start_time = time_return_value
3413 mock_get_free_floating_ip.return_value = None
3414 mock_assign_floating_ip.return_value = {}
3415 mock_create_floating_ip.side_effect = VimConnException(
3416 "Can not create floating ip."
3417 )
3418 self.vimconn.nova.servers.get.return_value.status = "ERROR"
3419 self.vimconn.neutron.show_floatingip.return_value = {}
3420
3421 self.vimconn._prepare_external_network_for_vminstance(
3422 external_network, self.server, created_items, vm_start_time
3423 )
3424 self.assertEqual(mock_get_free_floating_ip.call_count, 1)
3425 mock_get_free_floating_ip.assert_called_with(
3426 self.server,
3427 {
3428 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3429 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3430 "exit_on_floating_ip_error": False,
3431 },
3432 )
3433 self.vimconn.neutron.show_floatingip.assert_not_called()
3434 mock_sleep.assert_not_called()
3435 mock_time.assert_not_called()
3436 self.vimconn.nova.servers.get.assert_not_called()
3437 mock_create_floating_ip.assert_called_with(
3438 floating_network, self.server, created_items
3439 )
3440 self.assertEqual(mock_create_floating_ip.call_count, 1)
3441 mock_assign_floating_ip.assert_not_called()
3442
3443 @patch("time.time")
3444 @patch("time.sleep")
3445 @patch.object(vimconnector, "_create_floating_ip")
3446 @patch.object(vimconnector, "_get_free_floating_ip")
3447 @patch.object(vimconnector, "_assign_floating_ip")
3448 def test_prepare_external_network_for_vm_instance_no_free_fip_can_not_create_fip_exit_on_error_true(
3449 self,
3450 mock_assign_floating_ip,
3451 mock_get_free_floating_ip,
3452 mock_create_floating_ip,
3453 mock_sleep,
3454 mock_time,
3455 ):
3456 """There is not any free floating ip, create_floating ip method raise exception
3457 exit_on_floating_ip_error set to False."""
3458 floating_network = {
3459 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3460 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3461 "exit_on_floating_ip_error": True,
3462 }
3463 external_network = [floating_network]
3464
3465 created_items = {}
3466 vm_start_time = time_return_value
3467 mock_get_free_floating_ip.return_value = None
3468 mock_assign_floating_ip.return_value = {}
3469 mock_create_floating_ip.side_effect = VimConnException(
3470 "Can not create floating ip."
3471 )
3472 self.vimconn.nova.servers.get.return_value.status = "ERROR"
3473 self.vimconn.neutron.show_floatingip.return_value = {}
3474 with self.assertRaises(VimConnException):
3475 self.vimconn._prepare_external_network_for_vminstance(
3476 external_network, self.server, created_items, vm_start_time
3477 )
3478 self.assertEqual(mock_get_free_floating_ip.call_count, 1)
3479 mock_get_free_floating_ip.assert_called_with(
3480 self.server,
3481 {
3482 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3483 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3484 "exit_on_floating_ip_error": True,
3485 },
3486 )
3487 self.vimconn.neutron.show_floatingip.assert_not_called()
3488 mock_sleep.assert_not_called()
3489 mock_time.assert_not_called()
3490 self.vimconn.nova.servers.get.assert_not_called()
3491 mock_create_floating_ip.assert_called_with(
3492 floating_network, self.server, created_items
3493 )
3494 self.assertEqual(mock_create_floating_ip.call_count, 1)
3495 mock_assign_floating_ip.assert_not_called()
3496
3497 @patch.object(vimconnector, "_create_floating_ip")
3498 @patch.object(vimconnector, "_get_free_floating_ip")
3499 @patch.object(vimconnector, "_assign_floating_ip")
3500 def test_prepare_external_network_for_vm_instance_fip_has_port_id(
3501 self,
3502 mock_assign_floating_ip,
3503 mock_get_free_floating_ip,
3504 mock_create_floating_ip,
3505 ):
3506 """Neutron show floating ip return the fip with port_id and floating network vim_id
3507 is different from port_id."""
3508 floating_network = {
3509 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3510 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3511 }
3512 external_network = [floating_network]
3513 created_items = {}
3514 vm_start_time = 150
3515 mock_get_free_floating_ip.side_effect = [
3516 "t08b73-o9cc-1a6a-a270-12cc4811bd4u",
3517 "r08b73-o9cc-1a6a-a270-12cc4811bd4u",
3518 "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3519 ]
3520 mock_assign_floating_ip.side_effect = [
3521 {"floatingip": {"port_id": "k08b73-r9cc-5a6a-a270-82cc4811bd4a"}},
3522 {"floatingip": {"port_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a"}},
3523 ]
3524 self.vimconn.neutron = CopyingMock()
3525 self.vimconn.nova = CopyingMock()
3526 self.vimconn.neutron.show_floatingip.side_effect = [
3527 {"floatingip": {"port_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a"}},
3528 {"floatingip": {"port_id": ""}},
3529 {"floatingip": {"port_id": ""}},
3530 ]
3531 self.vimconn._prepare_external_network_for_vminstance(
3532 external_network, self.server, created_items, vm_start_time
3533 )
3534 self.assertEqual(mock_get_free_floating_ip.call_count, 3)
3535 _call_mock_get_free_floating_ip = mock_get_free_floating_ip.call_args_list
3536 self.assertEqual(
3537 _call_mock_get_free_floating_ip[0][0],
3538 (
3539 self.server,
3540 floating_network,
3541 ),
3542 )
3543 self.assertEqual(
3544 _call_mock_get_free_floating_ip[1][0],
3545 (
3546 self.server,
3547 floating_network,
3548 ),
3549 )
3550 self.assertEqual(
3551 _call_mock_get_free_floating_ip[2][0],
3552 (
3553 self.server,
3554 floating_network,
3555 ),
3556 )
3557 self.assertEqual(self.vimconn.neutron.show_floatingip.call_count, 3)
3558 self.vimconn.nova.servers.get.assert_not_called()
3559 mock_create_floating_ip.assert_not_called()
3560 self.assertEqual(mock_assign_floating_ip.call_count, 2)
3561 _call_mock_assign_floating_ip = mock_assign_floating_ip.call_args_list
3562 self.assertEqual(
3563 _call_mock_assign_floating_ip[0][0],
3564 ("r08b73-o9cc-1a6a-a270-12cc4811bd4u", floating_network),
3565 )
3566 self.assertEqual(
3567 _call_mock_assign_floating_ip[1][0],
3568 ("y08b73-o9cc-1a6a-a270-12cc4811bd4u", floating_network),
3569 )
3570
3571 @patch("time.time")
3572 @patch("time.sleep")
3573 @patch.object(vimconnector, "_create_floating_ip")
3574 @patch.object(vimconnector, "_get_free_floating_ip")
3575 @patch.object(vimconnector, "_assign_floating_ip")
3576 def test_prepare_external_network_for_vm_instance_neutron_show_fip_exception_vm_status_in_error(
3577 self,
3578 mock_assign_floating_ip,
3579 mock_get_free_floating_ip,
3580 mock_create_floating_ip,
3581 mock_sleep,
3582 mock_time,
3583 ):
3584 """Neutron show floating ip gives exception, exit_on_floating_ip_error set to True,
3585 VM status is in error."""
3586 floating_network = {
3587 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3588 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3589 "exit_on_floating_ip_error": True,
3590 }
3591 external_network = [floating_network]
3592 created_items = {}
3593 vm_start_time = time_return_value
3594
3595 mock_time.side_effect = [156570150, 156570800, 156571200]
3596
3597 self.vimconn.nova.servers.get.return_value.status = "ERROR"
3598 self.vimconn.neutron.show_floatingip.side_effect = [
3599 Exception("Floating ip could not be shown.")
3600 ] * 4
3601 with self.assertRaises(Exception) as err:
3602 self.vimconn._prepare_external_network_for_vminstance(
3603 external_network, self.server, created_items, vm_start_time
3604 )
3605 self.assertEqual(
3606 str(err.exception),
3607 "Cannot create floating_ip: Exception Floating ip could not be shown.",
3608 )
3609
3610 self.assertEqual(mock_get_free_floating_ip.call_count, 4)
3611 _call_mock_get_free_floating_ip = mock_get_free_floating_ip.call_args_list
3612 self.assertEqual(
3613 _call_mock_get_free_floating_ip[0][0],
3614 (
3615 self.server,
3616 floating_network,
3617 ),
3618 )
3619 self.assertEqual(
3620 _call_mock_get_free_floating_ip[1][0],
3621 (
3622 self.server,
3623 floating_network,
3624 ),
3625 )
3626 self.assertEqual(
3627 _call_mock_get_free_floating_ip[2][0],
3628 (
3629 self.server,
3630 floating_network,
3631 ),
3632 )
3633 self.assertEqual(
3634 _call_mock_get_free_floating_ip[3][0],
3635 (
3636 self.server,
3637 floating_network,
3638 ),
3639 )
3640
3641 self.assertEqual(self.vimconn.neutron.show_floatingip.call_count, 4)
3642 self.vimconn.nova.servers.get.assert_called_with(self.server.id)
3643 mock_create_floating_ip.assert_not_called()
3644 mock_assign_floating_ip.assert_not_called()
3645 mock_time.assert_not_called()
3646 mock_sleep.assert_not_called()
3647
3648 @patch("time.time")
3649 @patch("time.sleep")
3650 @patch.object(vimconnector, "_create_floating_ip")
3651 @patch.object(vimconnector, "_get_free_floating_ip")
3652 @patch.object(vimconnector, "_assign_floating_ip")
3653 def test_prepare_external_network_for_vm_instance_neutron_show_fip_exception_vm_status_in_active(
3654 self,
3655 mock_assign_floating_ip,
3656 mock_get_free_floating_ip,
3657 mock_create_floating_ip,
3658 mock_sleep,
3659 mock_time,
3660 ):
3661 """Neutron show floating ip gives exception, exit_on_floating_ip_error is set to False,
3662 VM status is in active."""
3663 floating_network = {
3664 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3665 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3666 "exit_on_floating_ip_error": False,
3667 }
3668 external_network = [floating_network]
3669 created_items = {}
3670 vm_start_time = time_return_value
3671
3672 mock_time.side_effect = [156570150, 156570800, 156571200]
3673
3674 self.vimconn.nova.servers.get.return_value.status = "ACTIVE"
3675 self.vimconn.neutron.show_floatingip.side_effect = [
3676 Exception("Floating ip could not be shown.")
3677 ] * 4
3678
3679 self.vimconn._prepare_external_network_for_vminstance(
3680 external_network, self.server, created_items, vm_start_time
3681 )
3682 # self.assertEqual(str(err.exception), "Cannot create floating_ip")
3683
3684 self.assertEqual(mock_get_free_floating_ip.call_count, 4)
3685 _call_mock_get_free_floating_ip = mock_get_free_floating_ip.call_args_list
3686 self.assertEqual(
3687 _call_mock_get_free_floating_ip[0][0],
3688 (
3689 self.server,
3690 floating_network,
3691 ),
3692 )
3693 self.assertEqual(
3694 _call_mock_get_free_floating_ip[1][0],
3695 (
3696 self.server,
3697 floating_network,
3698 ),
3699 )
3700 self.assertEqual(
3701 _call_mock_get_free_floating_ip[2][0],
3702 (
3703 self.server,
3704 floating_network,
3705 ),
3706 )
3707 self.assertEqual(
3708 _call_mock_get_free_floating_ip[3][0],
3709 (
3710 self.server,
3711 floating_network,
3712 ),
3713 )
3714
3715 self.assertEqual(self.vimconn.neutron.show_floatingip.call_count, 4)
3716 self.vimconn.nova.servers.get.assert_called_with(self.server.id)
3717 mock_create_floating_ip.assert_not_called()
3718 mock_assign_floating_ip.assert_not_called()
3719 mock_time.assert_not_called()
3720 mock_sleep.assert_not_called()
3721
3722 @patch("time.time")
3723 @patch("time.sleep")
3724 @patch.object(vimconnector, "_create_floating_ip")
3725 @patch.object(vimconnector, "_get_free_floating_ip")
3726 @patch.object(vimconnector, "_assign_floating_ip")
3727 def test_prepare_external_network_for_vm_instance_neutron_show_fip_exception_exit_on_error(
3728 self,
3729 mock_assign_floating_ip,
3730 mock_get_free_floating_ip,
3731 mock_create_floating_ip,
3732 mock_sleep,
3733 mock_time,
3734 ):
3735 """Neutron show floating ip gives exception, but exit_on_floating_ip_error is set to True.
3736 VM status is not ACTIVE or ERROR, server timeout happened."""
3737 floating_network = {
3738 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3739 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3740 "exit_on_floating_ip_error": True,
3741 }
3742 external_network = [floating_network]
3743 created_items = {}
3744 vm_start_time = time_return_value
3745 mock_get_free_floating_ip.side_effect = None
3746 mock_time.side_effect = [156571790, 156571795, 156571800, 156571805]
3747 self.vimconn.nova.servers.get.return_value.status = "OTHER"
3748 self.vimconn.neutron.show_floatingip.side_effect = [
3749 Exception("Floating ip could not be shown.")
3750 ] * 5
3751
3752 with self.assertRaises(VimConnException) as err:
3753 self.vimconn._prepare_external_network_for_vminstance(
3754 external_network, self.server, created_items, vm_start_time
3755 )
3756 self.assertEqual(
3757 str(err.exception),
3758 "Cannot create floating_ip: Exception Floating ip could not be shown.",
3759 )
3760
3761 self.assertEqual(mock_get_free_floating_ip.call_count, 3)
3762 _call_mock_get_free_floating_ip = mock_get_free_floating_ip.call_args_list
3763 self.assertEqual(
3764 _call_mock_get_free_floating_ip[0][0],
3765 (
3766 self.server,
3767 floating_network,
3768 ),
3769 )
3770 self.assertEqual(
3771 _call_mock_get_free_floating_ip[1][0],
3772 (
3773 self.server,
3774 floating_network,
3775 ),
3776 )
3777 self.assertEqual(
3778 _call_mock_get_free_floating_ip[2][0],
3779 (
3780 self.server,
3781 floating_network,
3782 ),
3783 )
3784
3785 self.assertEqual(self.vimconn.neutron.show_floatingip.call_count, 3)
3786 self.vimconn.nova.servers.get.assert_called_with(self.server.id)
3787 mock_create_floating_ip.assert_not_called()
3788 mock_assign_floating_ip.assert_not_called()
3789 self.assertEqual(mock_time.call_count, 3)
3790 self.assertEqual(mock_sleep.call_count, 2)
3791
3792 @patch("time.time")
3793 @patch("time.sleep")
3794 @patch.object(vimconnector, "_create_floating_ip")
3795 @patch.object(vimconnector, "_get_free_floating_ip")
3796 @patch.object(vimconnector, "_assign_floating_ip")
3797 def test_prepare_external_network_for_vm_instance_assign_floating_ip_exception_exit_on_error(
3798 self,
3799 mock_assign_floating_ip,
3800 mock_get_free_floating_ip,
3801 mock_create_floating_ip,
3802 mock_sleep,
3803 mock_time,
3804 ):
3805 """Assign floating ip method gives exception, exit_on_floating_ip_error is set to True.
3806 VM status is in ERROR."""
3807 floating_network = {
3808 "floating_ip": "y08b73-o9cc-1a6a-a270-12cc4811bd4u",
3809 "vim_id": "608b73-r9cc-5a6a-a270-82cc4811bd4a",
3810 "exit_on_floating_ip_error": True,
3811 }
3812 external_network = [floating_network]
3813 created_items = {}
3814 vm_start_time = time_return_value
3815
3816 mock_get_free_floating_ip.side_effect = [
3817 "y08b73-o9cc-1a6a-a270-12cc4811bd4u"
3818 ] * 4
3819
3820 mock_time.side_effect = [156571790, 156571795, 156571800, 156571805]
3821
3822 mock_assign_floating_ip.side_effect = [
3823 Exception("Floating ip could not be assigned.")
3824 ] * 4
3825
3826 self.vimconn.nova.servers.get.return_value.status = "ERROR"
3827 self.vimconn.neutron.show_floatingip.side_effect = [
3828 {"floatingip": {"port_id": ""}}
3829 ] * 4
3830
3831 with self.assertRaises(VimConnException) as err:
3832 self.vimconn._prepare_external_network_for_vminstance(
3833 external_network, self.server, created_items, vm_start_time
3834 )
3835 self.assertEqual(
3836 str(err.exception),
3837 "Cannot create floating_ip: Exception Floating ip could not be assigned.",
3838 )
3839
3840 self.assertEqual(mock_get_free_floating_ip.call_count, 4)
3841 _call_mock_get_free_floating_ip = mock_get_free_floating_ip.call_args_list
3842 self.assertEqual(
3843 _call_mock_get_free_floating_ip[0][0],
3844 (
3845 self.server,
3846 floating_network,
3847 ),
3848 )
3849 self.assertEqual(
3850 _call_mock_get_free_floating_ip[1][0],
3851 (
3852 self.server,
3853 floating_network,
3854 ),
3855 )
3856 self.assertEqual(
3857 _call_mock_get_free_floating_ip[2][0],
3858 (
3859 self.server,
3860 floating_network,
3861 ),
3862 )
3863
3864 self.assertEqual(self.vimconn.neutron.show_floatingip.call_count, 4)
3865 self.vimconn.neutron.show_floatingip.assert_called_with(
3866 "y08b73-o9cc-1a6a-a270-12cc4811bd4u"
3867 )
3868 self.assertEqual(self.vimconn.nova.servers.get.call_count, 4)
3869 self.vimconn.nova.servers.get.assert_called_with(self.server.id)
3870 mock_time.assert_not_called()
3871 mock_sleep.assert_not_called()
3872 mock_create_floating_ip.assert_not_called()
3873
3874 @patch("time.time")
3875 @patch("time.sleep")
3876 @patch.object(vimconnector, "_create_floating_ip")
3877 @patch.object(vimconnector, "_get_free_floating_ip")
3878 @patch.object(vimconnector, "_assign_floating_ip")
3879 def test_prepare_external_network_for_vm_instance_empty_external_network_list(
3880 self,
3881 mock_assign_floating_ip,
3882 mock_get_free_floating_ip,
3883 mock_create_floating_ip,
3884 mock_sleep,
3885 mock_time,
3886 ):
3887 """External network list is empty."""
3888 external_network = []
3889 created_items = {}
3890 vm_start_time = time_return_value
3891
3892 self.vimconn._prepare_external_network_for_vminstance(
3893 external_network, self.server, created_items, vm_start_time
3894 )
3895 mock_create_floating_ip.assert_not_called()
3896 mock_time.assert_not_called()
3897 mock_sleep.assert_not_called()
3898 mock_assign_floating_ip.assert_not_called()
3899 mock_get_free_floating_ip.assert_not_called()
3900 self.vimconn.neutron.show.show_floatingip.assert_not_called()
3901 self.vimconn.nova.servers.get.assert_not_called()
3902
3903 @patch.object(vimconnector, "_vimconnector__wait_for_vm")
3904 def test_update_port_security_for_vm_instance(self, mock_wait_for_vm):
3905 """no_secured_ports has port and the port has allow-address-pairs."""
3906 no_secured_ports = [(port2_id, "allow-address-pairs")]
3907
3908 self.vimconn._update_port_security_for_vminstance(no_secured_ports, self.server)
3909
3910 mock_wait_for_vm.assert_called_once_with(self.server.id, "ACTIVE")
3911
3912 self.vimconn.neutron.update_port.assert_called_once_with(
3913 port2_id,
3914 {"port": {"allowed_address_pairs": [{"ip_address": "0.0.0.0/0"}]}},
3915 )
3916
3917 @patch.object(vimconnector, "_vimconnector__wait_for_vm")
3918 def test_update_port_security_for_vm_instance_no_allowed_address_pairs(
3919 self, mock_wait_for_vm
3920 ):
3921 """no_secured_ports has port and the port does not have allow-address-pairs."""
3922 no_secured_ports = [(port2_id, "something")]
3923
3924 self.vimconn._update_port_security_for_vminstance(no_secured_ports, self.server)
3925
3926 mock_wait_for_vm.assert_called_once_with(self.server.id, "ACTIVE")
3927
3928 self.vimconn.neutron.update_port.assert_called_once_with(
3929 port2_id,
3930 {"port": {"port_security_enabled": False, "security_groups": None}},
3931 )
3932
3933 @patch.object(vimconnector, "_vimconnector__wait_for_vm")
3934 def test_update_port_security_for_vm_instance_wait_for_vm_raise_exception(
3935 self, mock_wait_for_vm
3936 ):
3937 """__wait_for_vm raises timeout exception."""
3938 no_secured_ports = [(port2_id, "something")]
3939
3940 mock_wait_for_vm.side_effect = VimConnException("Timeout waiting for instance.")
3941
3942 with self.assertRaises(VimConnException) as err:
3943 self.vimconn._update_port_security_for_vminstance(
3944 no_secured_ports, self.server
3945 )
3946 self.assertEqual(str(err.exception), "Timeout waiting for instance.")
3947
3948 mock_wait_for_vm.assert_called_once_with(self.server.id, "ACTIVE")
3949
3950 self.vimconn.neutron.update_port.assert_not_called()
3951
3952 @patch.object(vimconnector, "_vimconnector__wait_for_vm")
3953 def test_update_port_security_for_vm_instance_neutron_update_port_raise_exception(
3954 self, mock_wait_for_vm
3955 ):
3956 """neutron_update_port method raises exception."""
3957 no_secured_ports = [(port2_id, "something")]
3958
3959 self.vimconn.neutron.update_port.side_effect = Exception(
3960 "Port security could not be updated."
3961 )
3962
3963 with self.assertRaises(VimConnException) as err:
3964 self.vimconn._update_port_security_for_vminstance(
3965 no_secured_ports, self.server
3966 )
3967 self.assertEqual(
3968 str(err.exception),
3969 "It was not possible to disable port security for port 17472685-f67f-49fd-8722-eabb7692fc22",
3970 )
3971 mock_wait_for_vm.assert_called_once_with(self.server.id, "ACTIVE")
3972
3973 self.vimconn.neutron.update_port.assert_called_once_with(
3974 port2_id,
3975 {"port": {"port_security_enabled": False, "security_groups": None}},
3976 )
3977
3978 @patch.object(vimconnector, "_vimconnector__wait_for_vm")
3979 def test_update_port_security_for_vm_instance_empty_port_list(
3980 self, mock_wait_for_vm
3981 ):
3982 """no_secured_ports list does not have any ports."""
3983 no_secured_ports = []
3984
3985 self.vimconn._update_port_security_for_vminstance(no_secured_ports, self.server)
3986
3987 mock_wait_for_vm.assert_not_called()
3988
3989 self.vimconn.neutron.update_port.assert_not_called()
3990
3991 @patch("time.time")
3992 @patch.object(vimconnector, "_reload_connection")
3993 @patch.object(vimconnector, "_prepare_network_for_vminstance")
3994 @patch.object(vimconnector, "_create_user_data")
3995 @patch.object(vimconnector, "_get_vm_availability_zone")
3996 @patch.object(vimconnector, "_prepare_disk_for_vminstance")
3997 @patch.object(vimconnector, "_update_port_security_for_vminstance")
3998 @patch.object(vimconnector, "_prepare_external_network_for_vminstance")
3999 @patch.object(vimconnector, "delete_vminstance")
4000 @patch.object(vimconnector, "_format_exception")
4001 def test_new_vm_instance(
4002 self,
4003 mock_format_exception,
4004 mock_delete_vm_instance,
4005 mock_prepare_external_network,
4006 mock_update_port_security,
4007 mock_prepare_disk_for_vm_instance,
4008 mock_get_vm_availability_zone,
4009 mock_create_user_data,
4010 mock_prepare_network_for_vm_instance,
4011 mock_reload_connection,
4012 mock_time,
4013 ):
4014 """New VM instance creation is successful."""
4015
4016 mock_create_user_data.return_value = True, "userdata"
4017
4018 mock_get_vm_availability_zone.return_value = "nova"
4019
4020 self.vimconn.nova.servers.create.return_value = self.server
4021
4022 mock_time.return_value = time_return_value
4023
4024 expected_result = self.server.id, {}
4025
4026 result = self.vimconn.new_vminstance(
4027 name,
4028 description,
4029 start,
4030 image_id,
4031 flavor_id,
4032 affinity_group_list,
4033 net_list,
4034 cloud_config,
4035 disk_list2,
4036 availability_zone_index,
4037 availability_zone_list,
4038 )
4039 self.assertEqual(result, expected_result)
4040
4041 mock_reload_connection.assert_called_once()
4042 mock_prepare_network_for_vm_instance.assert_called_once_with(
4043 name=name,
4044 net_list=net_list,
4045 created_items={},
4046 net_list_vim=[],
4047 external_network=[],
4048 no_secured_ports=[],
4049 )
4050 mock_create_user_data.assert_called_once_with(cloud_config)
4051 mock_get_vm_availability_zone.assert_called_once_with(
4052 availability_zone_index, availability_zone_list
4053 )
4054 mock_prepare_disk_for_vm_instance.assert_called_once_with(
4055 name=name,
4056 existing_vim_volumes=[],
4057 created_items={},
4058 vm_av_zone="nova",
4059 block_device_mapping={},
4060 disk_list=disk_list2,
4061 )
4062 self.vimconn.nova.servers.create.assert_called_once_with(
4063 name=name,
4064 image=image_id,
4065 flavor=flavor_id,
4066 nics=[],
4067 security_groups="default",
4068 availability_zone="nova",
4069 key_name="my_keypair",
4070 userdata="userdata",
4071 config_drive=True,
4072 block_device_mapping={},
4073 scheduler_hints={},
4074 )
4075 mock_time.assert_called_once()
4076 mock_update_port_security.assert_called_once_with([], self.server)
4077 mock_prepare_external_network.assert_called_once_with(
4078 external_network=[],
4079 server=self.server,
4080 created_items={},
4081 vm_start_time=time_return_value,
4082 )
4083 mock_delete_vm_instance.assert_not_called()
4084 mock_format_exception.assert_not_called()
4085
4086 @patch("time.time")
4087 @patch.object(vimconnector, "_reload_connection")
4088 @patch.object(vimconnector, "_prepare_network_for_vminstance")
4089 @patch.object(vimconnector, "_create_user_data")
4090 @patch.object(vimconnector, "_get_vm_availability_zone")
4091 @patch.object(vimconnector, "_prepare_disk_for_vminstance")
4092 @patch.object(vimconnector, "_update_port_security_for_vminstance")
4093 @patch.object(vimconnector, "_prepare_external_network_for_vminstance")
4094 @patch.object(vimconnector, "delete_vminstance")
4095 @patch.object(vimconnector, "_format_exception")
4096 def test_new_vm_instance_create_user_data_fails(
4097 self,
4098 mock_format_exception,
4099 mock_delete_vm_instance,
4100 mock_prepare_external_network,
4101 mock_update_port_security,
4102 mock_prepare_disk_for_vm_instance,
4103 mock_get_vm_availability_zone,
4104 mock_create_user_data,
4105 mock_prepare_network_for_vm_instance,
4106 mock_reload_connection,
4107 mock_time,
4108 ):
4109 """New VM instance creation failed because of user data creation failure."""
4110
4111 mock_create_user_data.side_effect = Exception(
4112 "User data could not be retrieved."
4113 )
4114
4115 mock_get_vm_availability_zone.return_value = "nova"
4116
4117 self.vimconn.nova.servers.create.return_value = self.server
4118
4119 mock_time.return_value = time_return_value
4120
4121 self.vimconn.new_vminstance(
4122 name,
4123 description,
4124 start,
4125 image_id,
4126 flavor_id,
4127 affinity_group_list,
4128 net_list,
4129 cloud_config,
4130 disk_list,
4131 availability_zone_index,
4132 availability_zone_list,
4133 )
4134
4135 mock_reload_connection.assert_called_once()
4136 mock_prepare_network_for_vm_instance.assert_called_once_with(
4137 name=name,
4138 net_list=net_list,
4139 created_items={},
4140 net_list_vim=[],
4141 external_network=[],
4142 no_secured_ports=[],
4143 )
4144 mock_create_user_data.assert_called_once_with(cloud_config)
4145 mock_get_vm_availability_zone.assert_not_called()
4146 mock_prepare_disk_for_vm_instance.assert_not_called()
4147 self.vimconn.nova.servers.create.assert_not_called()
4148 mock_time.assert_not_called()
4149 mock_update_port_security.assert_not_called()
4150 mock_prepare_external_network.assert_not_called()
4151 mock_delete_vm_instance.assert_called_once_with(None, {})
4152 mock_format_exception.assert_called_once()
4153 arg = mock_format_exception.call_args[0][0]
4154 self.assertEqual(str(arg), "User data could not be retrieved.")
4155
4156 @patch("time.time")
4157 @patch.object(vimconnector, "_reload_connection")
4158 @patch.object(vimconnector, "_prepare_network_for_vminstance")
4159 @patch.object(vimconnector, "_create_user_data")
4160 @patch.object(vimconnector, "_get_vm_availability_zone")
4161 @patch.object(vimconnector, "_prepare_disk_for_vminstance")
4162 @patch.object(vimconnector, "_update_port_security_for_vminstance")
4163 @patch.object(vimconnector, "_prepare_external_network_for_vminstance")
4164 @patch.object(vimconnector, "delete_vminstance")
4165 @patch.object(vimconnector, "_format_exception")
4166 def test_new_vm_instance_external_network_exception(
4167 self,
4168 mock_format_exception,
4169 mock_delete_vm_instance,
4170 mock_prepare_external_network,
4171 mock_update_port_security,
4172 mock_prepare_disk_for_vm_instance,
4173 mock_get_vm_availability_zone,
4174 mock_create_user_data,
4175 mock_prepare_network_for_vm_instance,
4176 mock_reload_connection,
4177 mock_time,
4178 ):
4179 """New VM instance creation, external network connection has failed as floating
4180 ip could not be created."""
4181
4182 mock_create_user_data.return_value = True, "userdata"
4183
4184 mock_get_vm_availability_zone.return_value = "nova"
4185
4186 self.vimconn.nova.servers.create.return_value = self.server
4187
4188 mock_time.return_value = time_return_value
4189
4190 mock_prepare_external_network.side_effect = VimConnException(
4191 "Can not create floating ip."
4192 )
4193
4194 self.vimconn.new_vminstance(
4195 name,
4196 description,
4197 start,
4198 image_id,
4199 flavor_id,
4200 affinity_group_list,
4201 net_list,
4202 cloud_config,
4203 disk_list2,
4204 availability_zone_index,
4205 availability_zone_list,
4206 )
4207
4208 mock_reload_connection.assert_called_once()
4209 mock_prepare_network_for_vm_instance.assert_called_once_with(
4210 name=name,
4211 net_list=net_list,
4212 created_items={},
4213 net_list_vim=[],
4214 external_network=[],
4215 no_secured_ports=[],
4216 )
4217 mock_create_user_data.assert_called_once_with(cloud_config)
4218 mock_get_vm_availability_zone.assert_called_once_with(
4219 availability_zone_index, availability_zone_list
4220 )
4221 mock_prepare_disk_for_vm_instance.assert_called_once_with(
4222 name=name,
4223 existing_vim_volumes=[],
4224 created_items={},
4225 vm_av_zone="nova",
4226 block_device_mapping={},
4227 disk_list=disk_list2,
4228 )
4229 self.vimconn.nova.servers.create.assert_called_once_with(
4230 name=name,
4231 image=image_id,
4232 flavor=flavor_id,
4233 nics=[],
4234 security_groups="default",
4235 availability_zone="nova",
4236 key_name="my_keypair",
4237 userdata="userdata",
4238 config_drive=True,
4239 block_device_mapping={},
4240 scheduler_hints={},
4241 )
4242 mock_time.assert_called_once()
4243 mock_update_port_security.assert_called_once_with([], self.server)
4244 mock_prepare_external_network.assert_called_once_with(
4245 external_network=[],
4246 server=self.server,
4247 created_items={},
4248 vm_start_time=time_return_value,
4249 )
4250 mock_delete_vm_instance.assert_called_once_with(self.server.id, {})
4251 mock_format_exception.assert_called_once()
4252 arg = mock_format_exception.call_args[0][0]
4253 self.assertEqual(str(arg), "Can not create floating ip.")
4254
4255 @patch("time.time")
4256 @patch.object(vimconnector, "_reload_connection")
4257 @patch.object(vimconnector, "_prepare_network_for_vminstance")
4258 @patch.object(vimconnector, "_create_user_data")
4259 @patch.object(vimconnector, "_get_vm_availability_zone")
4260 @patch.object(vimconnector, "_prepare_disk_for_vminstance")
4261 @patch.object(vimconnector, "_update_port_security_for_vminstance")
4262 @patch.object(vimconnector, "_prepare_external_network_for_vminstance")
4263 @patch.object(vimconnector, "delete_vminstance")
4264 @patch.object(vimconnector, "_format_exception")
4265 def test_new_vm_instance_with_affinity_group(
4266 self,
4267 mock_format_exception,
4268 mock_delete_vm_instance,
4269 mock_prepare_external_network,
4270 mock_update_port_security,
4271 mock_prepare_disk_for_vm_instance,
4272 mock_get_vm_availability_zone,
4273 mock_create_user_data,
4274 mock_prepare_network_for_vm_instance,
4275 mock_reload_connection,
4276 mock_time,
4277 ):
4278 """New VM creation with affinity group."""
4279 affinity_group_list = [
4280 {"affinity_group_id": "38b73-e9cc-5a6a-t270-82cc4811bd4a"}
4281 ]
4282 mock_create_user_data.return_value = True, "userdata"
4283 mock_get_vm_availability_zone.return_value = "nova"
4284 self.vimconn.nova.servers.create.return_value = self.server
4285 mock_time.return_value = time_return_value
4286 expected_result = self.server.id, {}
4287
4288 result = self.vimconn.new_vminstance(
4289 name,
4290 description,
4291 start,
4292 image_id,
4293 flavor_id,
4294 affinity_group_list,
4295 net_list,
4296 cloud_config,
4297 disk_list2,
4298 availability_zone_index,
4299 availability_zone_list,
4300 )
4301 self.assertEqual(result, expected_result)
4302
4303 mock_reload_connection.assert_called_once()
4304 mock_prepare_network_for_vm_instance.assert_called_once_with(
4305 name=name,
4306 net_list=net_list,
4307 created_items={},
4308 net_list_vim=[],
4309 external_network=[],
4310 no_secured_ports=[],
4311 )
4312 mock_create_user_data.assert_called_once_with(cloud_config)
4313 mock_get_vm_availability_zone.assert_called_once_with(
4314 availability_zone_index, availability_zone_list
4315 )
4316 mock_prepare_disk_for_vm_instance.assert_called_once_with(
4317 name=name,
4318 existing_vim_volumes=[],
4319 created_items={},
4320 vm_av_zone="nova",
4321 block_device_mapping={},
4322 disk_list=disk_list2,
4323 )
4324 self.vimconn.nova.servers.create.assert_called_once_with(
4325 name=name,
4326 image=image_id,
4327 flavor=flavor_id,
4328 nics=[],
4329 security_groups="default",
4330 availability_zone="nova",
4331 key_name="my_keypair",
4332 userdata="userdata",
4333 config_drive=True,
4334 block_device_mapping={},
4335 scheduler_hints={"group": "38b73-e9cc-5a6a-t270-82cc4811bd4a"},
4336 )
4337 mock_time.assert_called_once()
4338 mock_update_port_security.assert_called_once_with([], self.server)
4339 mock_prepare_external_network.assert_called_once_with(
4340 external_network=[],
4341 server=self.server,
4342 created_items={},
4343 vm_start_time=time_return_value,
4344 )
4345 mock_delete_vm_instance.assert_not_called()
4346 mock_format_exception.assert_not_called()
4347
4348 @patch("time.time")
4349 @patch.object(vimconnector, "_reload_connection")
4350 @patch.object(vimconnector, "_prepare_network_for_vminstance")
4351 @patch.object(vimconnector, "_create_user_data")
4352 @patch.object(vimconnector, "_get_vm_availability_zone")
4353 @patch.object(vimconnector, "_prepare_disk_for_vminstance")
4354 @patch.object(vimconnector, "_update_port_security_for_vminstance")
4355 @patch.object(vimconnector, "_prepare_external_network_for_vminstance")
4356 @patch.object(vimconnector, "delete_vminstance")
4357 @patch.object(vimconnector, "_format_exception")
4358 def test_new_vm_instance_nova_server_create_failed(
4359 self,
4360 mock_format_exception,
4361 mock_delete_vm_instance,
4362 mock_prepare_external_network,
4363 mock_update_port_security,
4364 mock_prepare_disk_for_vm_instance,
4365 mock_get_vm_availability_zone,
4366 mock_create_user_data,
4367 mock_prepare_network_for_vm_instance,
4368 mock_reload_connection,
4369 mock_time,
4370 ):
4371 """New VM(server) creation failed."""
4372
4373 mock_create_user_data.return_value = True, "userdata"
4374
4375 mock_get_vm_availability_zone.return_value = "nova"
4376
4377 self.vimconn.nova.servers.create.side_effect = Exception(
4378 "Server could not be created."
4379 )
4380
4381 mock_time.return_value = time_return_value
4382
4383 self.vimconn.new_vminstance(
4384 name,
4385 description,
4386 start,
4387 image_id,
4388 flavor_id,
4389 affinity_group_list,
4390 net_list,
4391 cloud_config,
4392 disk_list2,
4393 availability_zone_index,
4394 availability_zone_list,
4395 )
4396
4397 mock_reload_connection.assert_called_once()
4398 mock_prepare_network_for_vm_instance.assert_called_once_with(
4399 name=name,
4400 net_list=net_list,
4401 created_items={},
4402 net_list_vim=[],
4403 external_network=[],
4404 no_secured_ports=[],
4405 )
4406 mock_create_user_data.assert_called_once_with(cloud_config)
4407 mock_get_vm_availability_zone.assert_called_once_with(
4408 availability_zone_index, availability_zone_list
4409 )
4410 mock_prepare_disk_for_vm_instance.assert_called_once_with(
4411 name=name,
4412 existing_vim_volumes=[],
4413 created_items={},
4414 vm_av_zone="nova",
4415 block_device_mapping={},
4416 disk_list=disk_list2,
4417 )
4418
4419 self.vimconn.nova.servers.create.assert_called_once_with(
4420 name=name,
4421 image=image_id,
4422 flavor=flavor_id,
4423 nics=[],
4424 security_groups="default",
4425 availability_zone="nova",
4426 key_name="my_keypair",
4427 userdata="userdata",
4428 config_drive=True,
4429 block_device_mapping={},
4430 scheduler_hints={},
4431 )
4432 mock_time.assert_not_called()
4433 mock_update_port_security.assert_not_called()
4434 mock_prepare_external_network.assert_not_called()
4435 mock_delete_vm_instance.assert_called_once_with(None, {})
4436 mock_format_exception.assert_called_once()
4437 arg = mock_format_exception.call_args[0][0]
4438 self.assertEqual(str(arg), "Server could not be created.")
4439
4440 @patch("time.time")
4441 @patch.object(vimconnector, "_reload_connection")
4442 @patch.object(vimconnector, "_prepare_network_for_vminstance")
4443 @patch.object(vimconnector, "_create_user_data")
4444 @patch.object(vimconnector, "_get_vm_availability_zone")
4445 @patch.object(vimconnector, "_prepare_disk_for_vminstance")
4446 @patch.object(vimconnector, "_update_port_security_for_vminstance")
4447 @patch.object(vimconnector, "_prepare_external_network_for_vminstance")
4448 @patch.object(vimconnector, "delete_vminstance")
4449 @patch.object(vimconnector, "_format_exception")
4450 def test_new_vm_instance_connection_exception(
4451 self,
4452 mock_format_exception,
4453 mock_delete_vm_instance,
4454 mock_prepare_external_network,
4455 mock_update_port_security,
4456 mock_prepare_disk_for_vm_instance,
4457 mock_get_vm_availability_zone,
4458 mock_create_user_data,
4459 mock_prepare_network_for_vm_instance,
4460 mock_reload_connection,
4461 mock_time,
4462 ):
4463 """Connection to Cloud API has failed."""
4464 mock_reload_connection.side_effect = Exception("Can not connect to Cloud APIs.")
4465 mock_create_user_data.return_value = True, "userdata"
4466 mock_get_vm_availability_zone.return_value = "nova"
4467 self.vimconn.nova.servers.create.return_value = self.server
4468 mock_time.return_value = time_return_value
4469
4470 self.vimconn.new_vminstance(
4471 name,
4472 description,
4473 start,
4474 image_id,
4475 flavor_id,
4476 affinity_group_list,
4477 net_list,
4478 cloud_config,
4479 disk_list,
4480 availability_zone_index,
4481 availability_zone_list,
4482 )
4483 mock_format_exception.assert_called_once()
4484 arg = mock_format_exception.call_args[0][0]
4485 self.assertEqual(str(arg), "Can not connect to Cloud APIs.")
4486 mock_reload_connection.assert_called_once()
4487 mock_prepare_network_for_vm_instance.assert_not_called()
4488 mock_create_user_data.assert_not_called()
4489 mock_get_vm_availability_zone.assert_not_called()
4490 mock_prepare_disk_for_vm_instance.assert_not_called()
4491 self.vimconn.nova.servers.create.assert_not_called()
4492 mock_time.assert_not_called()
4493 mock_update_port_security.assert_not_called()
4494 mock_prepare_external_network.assert_not_called()
4495 mock_delete_vm_instance.assert_called_once_with(None, {})
4496
4497 @patch.object(vimconnector, "_delete_ports_by_id_wth_neutron")
4498 def test_delete_vm_ports_attached_to_network_empty_created_items(
4499 self, mock_delete_ports_by_id_wth_neutron
4500 ):
4501 """Created_items is emtpty."""
4502 created_items = {}
4503 self.vimconn._delete_vm_ports_attached_to_network(created_items)
4504 self.vimconn.neutron.list_ports.assert_not_called()
4505 self.vimconn.neutron.delete_port.assert_not_called()
4506 mock_delete_ports_by_id_wth_neutron.assert_not_called()
4507
4508 @patch.object(vimconnector, "_delete_ports_by_id_wth_neutron")
4509 def test_delete_vm_ports_attached_to_network(
4510 self, mock_delete_ports_by_id_wth_neutron
4511 ):
4512 created_items = {
4513 "floating_ip:308b73-t9cc-1a6a-a270-12cc4811bd4a": True,
4514 f"volume:{volume_id2}": True,
4515 f"volume:{volume_id}": True,
4516 f"port:{port_id}": True,
4517 }
4518 self.vimconn._delete_vm_ports_attached_to_network(created_items)
4519 mock_delete_ports_by_id_wth_neutron.assert_called_once_with(f"{port_id}")
4520 self.vimconn.logger.error.assert_not_called()
4521
4522 @patch.object(vimconnector, "_delete_ports_by_id_wth_neutron")
4523 def test_delete_vm_ports_attached_to_network_wthout_port(
4524 self, mock_delete_ports_by_id_wth_neutron
4525 ):
4526 """Created_items does not have port."""
4527 created_items = {
4528 f"floating_ip:{floating_network_vim_id}": True,
4529 f"volume:{volume_id2}": True,
4530 f"volume:{volume_id}": True,
4531 }
4532 self.vimconn._delete_vm_ports_attached_to_network(created_items)
4533 mock_delete_ports_by_id_wth_neutron.assert_not_called()
4534 self.vimconn.logger.error.assert_not_called()
4535
4536 @patch.object(vimconnector, "_delete_ports_by_id_wth_neutron")
4537 def test_delete_vm_ports_attached_to_network_delete_port_raise_vimconnexception(
4538 self, mock_delete_ports_by_id_wth_neutron
4539 ):
4540 """_delete_ports_by_id_wth_neutron raises vimconnexception."""
4541 created_items = deepcopy(created_items_all_true)
4542 mock_delete_ports_by_id_wth_neutron.side_effect = VimConnException(
4543 "Can not delete port"
4544 )
4545 self.vimconn._delete_vm_ports_attached_to_network(created_items)
4546 mock_delete_ports_by_id_wth_neutron.assert_called_once_with(f"{port_id}")
4547 self.vimconn.logger.error.assert_called_once_with(
4548 "Error deleting port: VimConnException: Can not delete port"
4549 )
4550
4551 @patch.object(vimconnector, "_delete_ports_by_id_wth_neutron")
4552 def test_delete_vm_ports_attached_to_network_delete_port_raise_nvexception(
4553 self, mock_delete_ports_by_id_wth_neutron
4554 ):
4555 """_delete_ports_by_id_wth_neutron raises nvExceptions.ClientException."""
4556 created_items = deepcopy(created_items_all_true)
4557 mock_delete_ports_by_id_wth_neutron.side_effect = nvExceptions.ClientException(
4558 "Connection aborted."
4559 )
4560 self.vimconn._delete_vm_ports_attached_to_network(created_items)
4561 mock_delete_ports_by_id_wth_neutron.assert_called_once_with(f"{port_id}")
4562 self.vimconn.logger.error.assert_called_once_with(
4563 "Error deleting port: ClientException: Unknown Error (HTTP Connection aborted.)"
4564 )
4565
4566 @patch.object(vimconnector, "_delete_ports_by_id_wth_neutron")
4567 def test_delete_vm_ports_attached_to_network_delete_port_invalid_port_item(
4568 self, mock_delete_ports_by_id_wth_neutron
4569 ):
4570 """port item is invalid."""
4571 created_items = {
4572 f"floating_ip:{floating_network_vim_id}": True,
4573 f"volume:{volume_id2}": True,
4574 f"volume:{volume_id}": True,
4575 f"port:{port_id}:": True,
4576 }
4577 mock_delete_ports_by_id_wth_neutron.side_effect = VimConnException(
4578 "Port is not valid."
4579 )
4580 self.vimconn._delete_vm_ports_attached_to_network(created_items)
4581 mock_delete_ports_by_id_wth_neutron.assert_called_once_with(f"{port_id}:")
4582 self.vimconn.logger.error.assert_called_once_with(
4583 "Error deleting port: VimConnException: Port is not valid."
4584 )
4585
4586 @patch.object(vimconnector, "_delete_ports_by_id_wth_neutron")
4587 def test_delete_vm_ports_attached_to_network_delete_port_already_deleted(
4588 self, mock_delete_ports_by_id_wth_neutron
4589 ):
4590 """port is already deleted."""
4591 created_items = {
4592 f"floating_ip:{floating_network_vim_id}": True,
4593 f"volume:{volume_id2}": True,
4594 f"volume:{volume_id}": None,
4595 f"port:{port_id}": None,
4596 }
4597 self.vimconn._delete_vm_ports_attached_to_network(created_items)
4598 mock_delete_ports_by_id_wth_neutron.assert_not_called()
4599 self.vimconn.logger.error.assert_not_called()
4600
4601 def test_delete_floating_ip_by_id(self):
4602 created_items = {
4603 f"floating_ip:{floating_network_vim_id}": True,
4604 f"port:{port_id}": True,
4605 }
4606 expected_created_items = {
4607 f"floating_ip:{floating_network_vim_id}": None,
4608 f"port:{port_id}": True,
4609 }
4610 k_id = floating_network_vim_id
4611 k = f"floating_ip:{floating_network_vim_id}"
4612 self.vimconn._delete_floating_ip_by_id(k, k_id, created_items)
4613 self.vimconn.neutron.delete_floatingip.assert_called_once_with(k_id)
4614 self.assertEqual(created_items, expected_created_items)
4615
4616 def test_delete_floating_ip_by_id_floating_ip_already_deleted(self):
4617 """floating ip is already deleted."""
4618 created_items = {
4619 f"floating_ip:{floating_network_vim_id}": None,
4620 f"port:{port_id}": True,
4621 }
4622 k_id = floating_network_vim_id
4623 k = f"floating_ip:{floating_network_vim_id}"
4624 self.vimconn._delete_floating_ip_by_id(k, k_id, created_items)
4625 self.vimconn.neutron.delete_floatingip.assert_called_once_with(k_id)
4626 self.assertEqual(
4627 created_items,
4628 {
4629 f"floating_ip:{floating_network_vim_id}": None,
4630 f"port:{port_id}": True,
4631 },
4632 )
4633
4634 def test_delete_floating_ip_by_id_floating_ip_raises_nvexception(self):
4635 """netron delete floating ip raises nvExceptions.ClientException."""
4636 created_items = {
4637 f"floating_ip:{floating_network_vim_id}": True,
4638 f"port:{port_id}": True,
4639 }
4640 k_id = floating_network_vim_id
4641 k = f"floating_ip:{floating_network_vim_id}"
4642 self.vimconn.neutron.delete_floatingip.side_effect = (
4643 nvExceptions.ClientException("Client exception occurred.")
4644 )
4645 self.vimconn._delete_floating_ip_by_id(k, k_id, created_items)
4646 self.vimconn.neutron.delete_floatingip.assert_called_once_with(k_id)
4647 self.assertEqual(
4648 created_items,
4649 {
4650 f"floating_ip:{floating_network_vim_id}": True,
4651 f"port:{port_id}": True,
4652 },
4653 )
4654 self.vimconn.logger.error.assert_called_once_with(
4655 "Error deleting floating ip: ClientException: Unknown Error (HTTP Client exception occurred.)"
4656 )
4657
4658 def test_delete_floating_ip_by_id_floating_ip_raises_vimconnexception(self):
4659 """netron delete floating ip raises VimConnNotFoundException."""
4660 created_items = {
4661 f"floating_ip:{floating_network_vim_id}": True,
4662 f"port:{port_id}": True,
4663 }
4664 k_id = floating_network_vim_id
4665 k = f"floating_ip:{floating_network_vim_id}"
4666 self.vimconn.neutron.delete_floatingip.side_effect = VimConnNotFoundException(
4667 "Port id could not found."
4668 )
4669 self.vimconn._delete_floating_ip_by_id(k, k_id, created_items)
4670 self.vimconn.neutron.delete_floatingip.assert_called_once_with(k_id)
4671 self.assertEqual(
4672 created_items,
4673 {
4674 f"floating_ip:{floating_network_vim_id}": True,
4675 f"port:{port_id}": True,
4676 },
4677 )
4678 self.vimconn.logger.error.assert_called_once_with(
4679 "Error deleting floating ip: VimConnNotFoundException: Port id could not found."
4680 )
4681
4682 def test_delete_floating_ip_by_id_floating_ip_invalid_k_item(self):
4683 """invalid floating ip item."""
4684 created_items = {
4685 f"floating_ip:{floating_network_vim_id}": True,
4686 f"port:{port_id}": True,
4687 }
4688 expected_created_items = {
4689 f"floating_ip:{floating_network_vim_id}::": None,
4690 f"floating_ip:{floating_network_vim_id}": True,
4691 f"port:{port_id}": True,
4692 }
4693 k_id = floating_network_vim_id
4694 k = f"floating_ip:{floating_network_vim_id}::"
4695 self.vimconn._delete_floating_ip_by_id(k, k_id, created_items)
4696 self.vimconn.neutron.delete_floatingip.assert_called_once_with(k_id)
4697 self.assertEqual(created_items, expected_created_items)
4698
4699 def test_delete_volumes_by_id_with_cinder_volume_status_available(self):
4700 """volume status is available."""
4701 created_items = {
4702 f"floating_ip:{floating_network_vim_id}": True,
4703 f"volume:{volume_id2}": True,
4704 f"volume:{volume_id}": True,
4705 f"port:{port_id}": None,
4706 }
4707 expected_created_items = {
4708 f"floating_ip:{floating_network_vim_id}": True,
4709 f"volume:{volume_id2}": True,
4710 f"volume:{volume_id}": None,
4711 f"port:{port_id}": None,
4712 }
4713 volumes_to_hold = []
4714 k = f"volume:{volume_id}"
4715 k_id = volume_id
4716 self.vimconn.cinder.volumes.get.return_value.status = "available"
4717 result = self.vimconn._delete_volumes_by_id_wth_cinder(
4718 k, k_id, volumes_to_hold, created_items
4719 )
4720 self.assertEqual(result, None)
4721 self.vimconn.cinder.volumes.get.assert_called_once_with(k_id)
4722 self.vimconn.cinder.volumes.delete.assert_called_once_with(k_id)
4723 self.vimconn.logger.error.assert_not_called()
4724 self.assertEqual(created_items, expected_created_items)
4725
4726 def test_delete_volumes_by_id_with_cinder_volume_already_deleted(self):
4727 """volume is already deleted."""
4728 created_items = {
4729 f"floating_ip:{floating_network_vim_id}": True,
4730 f"volume:{volume_id2}": True,
4731 f"volume:{volume_id}": None,
4732 f"port:{port_id}": None,
4733 }
4734 expected_created_items = {
4735 f"floating_ip:{floating_network_vim_id}": True,
4736 f"volume:{volume_id2}": True,
4737 f"volume:{volume_id}": None,
4738 f"port:{port_id}": None,
4739 }
4740 volumes_to_hold = []
4741 k = f"volume:{volume_id}"
4742 k_id = volume_id
4743 self.vimconn.cinder.volumes.get.return_value.status = "available"
4744 result = self.vimconn._delete_volumes_by_id_wth_cinder(
4745 k, k_id, volumes_to_hold, created_items
4746 )
4747 self.assertEqual(result, None)
4748 self.vimconn.cinder.volumes.get.assert_called_once_with(k_id)
4749 self.vimconn.cinder.volumes.delete.assert_called_once_with(k_id)
4750 self.vimconn.logger.error.assert_not_called()
4751 self.assertEqual(created_items, expected_created_items)
4752
4753 def test_delete_volumes_by_id_with_cinder_get_volume_raise_exception(self):
4754 """cinder get volume raises exception."""
4755 created_items = {
4756 f"floating_ip:{floating_network_vim_id}": True,
4757 f"volume:{volume_id2}": True,
4758 f"volume:{volume_id}": True,
4759 f"port:{port_id}": None,
4760 }
4761 expected_created_items = {
4762 f"floating_ip:{floating_network_vim_id}": True,
4763 f"volume:{volume_id2}": True,
4764 f"volume:{volume_id}": True,
4765 f"port:{port_id}": None,
4766 }
4767 volumes_to_hold = []
4768 k = f"volume:{volume_id}"
4769 k_id = volume_id
4770 self.vimconn.cinder.volumes.get.side_effect = Exception(
4771 "Can not get volume status."
4772 )
4773 result = self.vimconn._delete_volumes_by_id_wth_cinder(
4774 k, k_id, volumes_to_hold, created_items
4775 )
4776 self.assertEqual(result, None)
4777 self.vimconn.cinder.volumes.get.assert_called_once_with(k_id)
4778 self.vimconn.cinder.volumes.delete.assert_not_called()
4779 self.vimconn.logger.error.assert_called_once_with(
4780 "Error deleting volume: Exception: Can not get volume status."
4781 )
4782 self.assertEqual(created_items, expected_created_items)
4783
4784 def test_delete_volumes_by_id_with_cinder_delete_volume_raise_exception(self):
4785 """cinder delete volume raises exception."""
4786 created_items = {
4787 f"floating_ip:{floating_network_vim_id}": True,
4788 f"volume:{volume_id2}": True,
4789 f"volume:{volume_id}": True,
4790 f"port:{port_id}": None,
4791 }
4792 expected_created_items = {
4793 f"floating_ip:{floating_network_vim_id}": True,
4794 f"volume:{volume_id2}": True,
4795 f"volume:{volume_id}": True,
4796 f"port:{port_id}": None,
4797 }
4798 volumes_to_hold = []
4799 k = f"volume:{volume_id}"
4800 k_id = volume_id
4801 self.vimconn.cinder.volumes.get.return_value.status = "available"
4802 self.vimconn.cinder.volumes.delete.side_effect = nvExceptions.ClientException(
4803 "Connection aborted."
4804 )
4805 result = self.vimconn._delete_volumes_by_id_wth_cinder(
4806 k, k_id, volumes_to_hold, created_items
4807 )
4808 self.assertEqual(result, None)
4809 self.vimconn.cinder.volumes.get.assert_called_once_with(k_id)
4810 self.vimconn.cinder.volumes.delete.assert_called_once_with(k_id)
4811 self.vimconn.logger.error.assert_called_once_with(
4812 "Error deleting volume: ClientException: Unknown Error (HTTP Connection aborted.)"
4813 )
4814 self.assertEqual(created_items, expected_created_items)
4815
4816 def test_delete_volumes_by_id_with_cinder_volume_to_be_hold(self):
4817 """volume_to_hold has item."""
4818 created_items = {
4819 f"floating_ip:{floating_network_vim_id}": True,
4820 f"volume:{volume_id2}": True,
4821 f"volume:{volume_id}": True,
4822 f"port:{port_id}": None,
4823 }
4824 expected_created_items = {
4825 f"floating_ip:{floating_network_vim_id}": True,
4826 f"volume:{volume_id2}": True,
4827 f"volume:{volume_id}": True,
4828 f"port:{port_id}": None,
4829 }
4830 volumes_to_hold = [volume_id]
4831 k = f"volume:{volume_id}"
4832 k_id = volume_id
4833 result = self.vimconn._delete_volumes_by_id_wth_cinder(
4834 k, k_id, volumes_to_hold, created_items
4835 )
4836 self.assertEqual(result, None)
4837 self.vimconn.cinder.volumes.get.assert_not_called()
4838 self.vimconn.cinder.volumes.delete.assert_not_called()
4839 self.vimconn.logger.error.assert_not_called()
4840 self.assertEqual(created_items, expected_created_items)
4841
4842 def test_delete_volumes_by_id_with_cinder_volume_status_not_available(self):
4843 """volume status is not available."""
4844 created_items = {
4845 f"floating_ip:{floating_network_vim_id}": True,
4846 f"volume:{volume_id2}": True,
4847 f"volume:{volume_id}": True,
4848 f"port:{port_id}": None,
4849 }
4850 expected_created_items = {
4851 f"floating_ip:{floating_network_vim_id}": True,
4852 f"volume:{volume_id2}": True,
4853 f"volume:{volume_id}": True,
4854 f"port:{port_id}": None,
4855 }
4856 volumes_to_hold = []
4857 k = f"volume:{volume_id}"
4858 k_id = volume_id
4859 self.vimconn.cinder.volumes.get.return_value.status = "unavailable"
4860 result = self.vimconn._delete_volumes_by_id_wth_cinder(
4861 k, k_id, volumes_to_hold, created_items
4862 )
4863 self.assertEqual(result, True)
4864 self.vimconn.cinder.volumes.get.assert_called_once_with(k_id)
4865 self.vimconn.cinder.volumes.delete.assert_not_called()
4866 self.vimconn.logger.error.assert_not_called()
4867 self.assertEqual(created_items, expected_created_items)
4868
4869 def test_delete_ports_by_id_by_neutron(self):
4870 """neutron delete ports."""
4871 k_id = port_id
4872 self.vimconn.neutron.list_ports.return_value = {
4873 "ports": [{"id": port_id}, {"id": port2_id}]
4874 }
4875
4876 self.vimconn._delete_ports_by_id_wth_neutron(k_id)
4877 self.vimconn.neutron.list_ports.assert_called_once()
4878 self.vimconn.neutron.delete_port.assert_called_once_with(k_id)
4879 self.vimconn.logger.error.assert_not_called()
4880
4881 def test_delete_ports_by_id_by_neutron_id_not_in_port_list(self):
4882 """port id not in the port list."""
4883 k_id = volume_id
4884 self.vimconn.neutron.list_ports.return_value = {
4885 "ports": [{"id": port_id}, {"id": port2_id}]
4886 }
4887
4888 self.vimconn._delete_ports_by_id_wth_neutron(k_id)
4889 self.vimconn.neutron.list_ports.assert_called_once()
4890 self.vimconn.neutron.delete_port.assert_not_called()
4891 self.vimconn.logger.error.assert_not_called()
4892
4893 def test_delete_ports_by_id_by_neutron_list_port_raise_exception(self):
4894 """neutron list port raises exception."""
4895 k_id = port_id
4896 self.vimconn.neutron.list_ports.side_effect = nvExceptions.ClientException(
4897 "Connection aborted."
4898 )
4899 self.vimconn._delete_ports_by_id_wth_neutron(k_id)
4900 self.vimconn.neutron.list_ports.assert_called_once()
4901 self.vimconn.neutron.delete_port.assert_not_called()
4902 self.vimconn.logger.error.assert_called_once_with(
4903 "Error deleting port: ClientException: Unknown Error (HTTP Connection aborted.)"
4904 )
4905
4906 def test_delete_ports_by_id_by_neutron_delete_port_raise_exception(self):
4907 """neutron delete port raises exception."""
4908 k_id = port_id
4909 self.vimconn.neutron.list_ports.return_value = {
4910 "ports": [{"id": port_id}, {"id": port2_id}]
4911 }
4912 self.vimconn.neutron.delete_port.side_effect = nvExceptions.ClientException(
4913 "Connection aborted."
4914 )
4915 self.vimconn._delete_ports_by_id_wth_neutron(k_id)
4916 self.vimconn.neutron.list_ports.assert_called_once()
4917 self.vimconn.neutron.delete_port.assert_called_once_with(k_id)
4918 self.vimconn.logger.error.assert_called_once_with(
4919 "Error deleting port: ClientException: Unknown Error (HTTP Connection aborted.)"
4920 )
4921
4922 def test_get_item_name_id(self):
4923 """Get name and id successfully."""
4924 k = f"some:{port_id}"
4925 result = self.vimconn._get_item_name_id(k)
4926 self.assertEqual(result, ("some", f"{port_id}"))
4927
4928 def test_get_item_name_id_wthout_semicolon(self):
4929 """Does not have seperator."""
4930 k = f"some{port_id}"
4931 result = self.vimconn._get_item_name_id(k)
4932 self.assertEqual(result, (f"some{port_id}", ""))
4933
4934 def test_get_item_name_id_empty_string(self):
4935 """Empty string."""
4936 k = ""
4937 result = self.vimconn._get_item_name_id(k)
4938 self.assertEqual(result, ("", ""))
4939
4940 def test_get_item_name_id_k_is_none(self):
4941 """item is None."""
4942 k = None
4943 with self.assertRaises(AttributeError):
4944 self.vimconn._get_item_name_id(k)
4945
4946 @patch.object(vimconnector, "_get_item_name_id")
4947 @patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
4948 @patch.object(vimconnector, "_delete_floating_ip_by_id")
4949 def test_delete_created_items(
4950 self,
4951 mock_delete_floating_ip_by_id,
4952 mock_delete_volumes_by_id_wth_cinder,
4953 mock_get_item_name_id,
4954 ):
4955 """Created items has floating ip and volume."""
4956 created_items = {
4957 f"floating_ip:{floating_network_vim_id}": True,
4958 f"volume:{volume_id}": True,
4959 f"port:{port_id}": None,
4960 }
4961 mock_get_item_name_id.side_effect = [
4962 ("floating_ip", f"{floating_network_vim_id}"),
4963 ("volume", f"{volume_id}"),
4964 ]
4965 mock_delete_volumes_by_id_wth_cinder.return_value = True
4966 volumes_to_hold = []
4967 keep_waiting = False
4968 result = self.vimconn._delete_created_items(
4969 created_items, volumes_to_hold, keep_waiting
4970 )
4971 self.assertEqual(result, True)
4972 self.assertEqual(mock_get_item_name_id.call_count, 2)
4973 mock_delete_volumes_by_id_wth_cinder.assert_called_once_with(
4974 f"volume:{volume_id}", f"{volume_id}", [], created_items
4975 )
4976 mock_delete_floating_ip_by_id.assert_called_once_with(
4977 f"floating_ip:{floating_network_vim_id}",
4978 f"{floating_network_vim_id}",
4979 created_items,
4980 )
4981 self.vimconn.logger.error.assert_not_called()
4982
4983 @patch.object(vimconnector, "_get_item_name_id")
4984 @patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
4985 @patch.object(vimconnector, "_delete_floating_ip_by_id")
4986 def test_delete_created_items_wth_volumes_to_hold(
4987 self,
4988 mock_delete_floating_ip_by_id,
4989 mock_delete_volumes_by_id_wth_cinder,
4990 mock_get_item_name_id,
4991 ):
4992 """Created items has floating ip and volume and volumes_to_hold has items."""
4993 created_items = {
4994 f"floating_ip:{floating_network_vim_id}": True,
4995 f"volume:{volume_id}": True,
4996 f"port:{port_id}": None,
4997 }
4998 mock_get_item_name_id.side_effect = [
4999 ("floating_ip", f"{floating_network_vim_id}"),
5000 ("volume", f"{volume_id}"),
5001 ]
5002 mock_delete_volumes_by_id_wth_cinder.return_value = True
5003 volumes_to_hold = [f"{volume_id}", f"{volume_id2}"]
5004 keep_waiting = False
5005 result = self.vimconn._delete_created_items(
5006 created_items, volumes_to_hold, keep_waiting
5007 )
5008 self.assertEqual(result, True)
5009 self.assertEqual(mock_get_item_name_id.call_count, 2)
5010 mock_delete_volumes_by_id_wth_cinder.assert_called_once_with(
5011 f"volume:{volume_id}", f"{volume_id}", volumes_to_hold, created_items
5012 )
5013 mock_delete_floating_ip_by_id.assert_called_once_with(
5014 f"floating_ip:{floating_network_vim_id}",
5015 f"{floating_network_vim_id}",
5016 created_items,
5017 )
5018 self.vimconn.logger.error.assert_not_called()
5019
5020 @patch.object(vimconnector, "_get_item_name_id")
5021 @patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
5022 @patch.object(vimconnector, "_delete_floating_ip_by_id")
5023 def test_delete_created_items_wth_keep_waiting_true(
5024 self,
5025 mock_delete_floating_ip_by_id,
5026 mock_delete_volumes_by_id_wth_cinder,
5027 mock_get_item_name_id,
5028 ):
5029 """Keep waiting initial value is True."""
5030 created_items = {
5031 f"floating_ip:{floating_network_vim_id}": True,
5032 f"volume:{volume_id}": True,
5033 f"port:{port_id}": None,
5034 }
5035 mock_get_item_name_id.side_effect = [
5036 ("floating_ip", f"{floating_network_vim_id}"),
5037 ("volume", f"{volume_id}"),
5038 ]
5039 mock_delete_volumes_by_id_wth_cinder.return_value = False
5040 volumes_to_hold = [f"{volume_id}", f"{volume_id2}"]
5041 keep_waiting = True
5042 result = self.vimconn._delete_created_items(
5043 created_items, volumes_to_hold, keep_waiting
5044 )
5045 self.assertEqual(result, True)
5046 self.assertEqual(mock_get_item_name_id.call_count, 2)
5047 mock_delete_volumes_by_id_wth_cinder.assert_called_once_with(
5048 f"volume:{volume_id}", f"{volume_id}", volumes_to_hold, created_items
5049 )
5050 mock_delete_floating_ip_by_id.assert_called_once_with(
5051 f"floating_ip:{floating_network_vim_id}",
5052 f"{floating_network_vim_id}",
5053 created_items,
5054 )
5055 self.vimconn.logger.error.assert_not_called()
5056
5057 @patch.object(vimconnector, "_get_item_name_id")
5058 @patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
5059 @patch.object(vimconnector, "_delete_floating_ip_by_id")
5060 def test_delete_created_items_delete_vol_raises(
5061 self,
5062 mock_delete_floating_ip_by_id,
5063 mock_delete_volumes_by_id_wth_cinder,
5064 mock_get_item_name_id,
5065 ):
5066 """Delete volume raises exception."""
5067 created_items = {
5068 f"floating_ip:{floating_network_vim_id}": True,
5069 f"volume:{volume_id}": True,
5070 f"port:{port_id}": None,
5071 }
5072 mock_get_item_name_id.side_effect = [
5073 ("floating_ip", f"{floating_network_vim_id}"),
5074 ("volume", f"{volume_id}"),
5075 ]
5076 mock_delete_volumes_by_id_wth_cinder.side_effect = ConnectionError(
5077 "Connection failed."
5078 )
5079 volumes_to_hold = []
5080 keep_waiting = False
5081 result = self.vimconn._delete_created_items(
5082 created_items, volumes_to_hold, keep_waiting
5083 )
5084 self.assertEqual(result, False)
5085 self.assertEqual(mock_get_item_name_id.call_count, 2)
5086 mock_delete_volumes_by_id_wth_cinder.assert_called_once_with(
5087 f"volume:{volume_id}", f"{volume_id}", [], created_items
5088 )
5089 mock_delete_floating_ip_by_id.assert_called_once_with(
5090 f"floating_ip:{floating_network_vim_id}",
5091 f"{floating_network_vim_id}",
5092 created_items,
5093 )
5094 self.vimconn.logger.error.assert_called_once_with(
5095 "Error deleting volume:ac408b73-b9cc-4a6a-a270-82cc4811bd4a: Connection failed."
5096 )
5097
5098 @patch.object(vimconnector, "_get_item_name_id")
5099 @patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
5100 @patch.object(vimconnector, "_delete_floating_ip_by_id")
5101 def test_delete_created_items_delete_fip_raises(
5102 self,
5103 mock_delete_floating_ip_by_id,
5104 mock_delete_volumes_by_id_wth_cinder,
5105 mock_get_item_name_id,
5106 ):
5107 """Delete floating ip raises exception."""
5108 created_items = {
5109 f"floating_ip:{floating_network_vim_id}": True,
5110 f"volume:{volume_id}": True,
5111 f"port:{port_id}": None,
5112 }
5113 mock_get_item_name_id.side_effect = [
5114 ("floating_ip", f"{floating_network_vim_id}"),
5115 ("volume", f"{volume_id}"),
5116 ]
5117 mock_delete_volumes_by_id_wth_cinder.return_value = False
5118 mock_delete_floating_ip_by_id.side_effect = ConnectionError(
5119 "Connection failed."
5120 )
5121 volumes_to_hold = []
5122 keep_waiting = True
5123 result = self.vimconn._delete_created_items(
5124 created_items, volumes_to_hold, keep_waiting
5125 )
5126 self.assertEqual(result, True)
5127 self.assertEqual(mock_get_item_name_id.call_count, 2)
5128 mock_delete_volumes_by_id_wth_cinder.assert_called_once_with(
5129 f"volume:{volume_id}", f"{volume_id}", [], created_items
5130 )
5131 mock_delete_floating_ip_by_id.assert_called_once_with(
5132 f"floating_ip:{floating_network_vim_id}",
5133 f"{floating_network_vim_id}",
5134 created_items,
5135 )
5136 self.vimconn.logger.error.assert_called_once_with(
5137 "Error deleting floating_ip:108b73-e9cc-5a6a-t270-82cc4811bd4a: Connection failed."
5138 )
5139
5140 @patch.object(vimconnector, "_get_item_name_id")
5141 @patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
5142 @patch.object(vimconnector, "_delete_floating_ip_by_id")
5143 def test_delete_created_items_get_item_name_raises(
5144 self,
5145 mock_delete_floating_ip_by_id,
5146 mock_delete_volumes_by_id_wth_cinder,
5147 mock_get_item_name_id,
5148 ):
5149 """Get item, name raises exception."""
5150 created_items = {
5151 3: True,
5152 f"volume{volume_id}": True,
5153 f"port:{port_id}": None,
5154 }
5155 mock_get_item_name_id.side_effect = [
5156 TypeError("Invalid Type"),
5157 AttributeError("Invalid attribute"),
5158 ]
5159 volumes_to_hold = []
5160 keep_waiting = False
5161 result = self.vimconn._delete_created_items(
5162 created_items, volumes_to_hold, keep_waiting
5163 )
5164 self.assertEqual(result, False)
5165 self.assertEqual(mock_get_item_name_id.call_count, 2)
5166 mock_delete_volumes_by_id_wth_cinder.assert_not_called()
5167 mock_delete_floating_ip_by_id.assert_not_called()
5168 _call_logger = self.vimconn.logger.error.call_args_list
5169 self.assertEqual(_call_logger[0][0], ("Error deleting 3: Invalid Type",))
5170 self.assertEqual(
5171 _call_logger[1][0],
5172 (f"Error deleting volume{volume_id}: Invalid attribute",),
5173 )
5174
5175 @patch.object(vimconnector, "_get_item_name_id")
5176 @patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
5177 @patch.object(vimconnector, "_delete_floating_ip_by_id")
5178 def test_delete_created_items_no_fip_wth_port(
5179 self,
5180 mock_delete_floating_ip_by_id,
5181 mock_delete_volumes_by_id_wth_cinder,
5182 mock_get_item_name_id,
5183 ):
5184 """Created items has port, does not have floating ip."""
5185 created_items = {
5186 f"volume:{volume_id}": True,
5187 f"port:{port_id}": True,
5188 }
5189 mock_get_item_name_id.side_effect = [
5190 ("volume", f"{volume_id}"),
5191 ("port", f"{port_id}"),
5192 ]
5193 mock_delete_volumes_by_id_wth_cinder.return_value = False
5194 volumes_to_hold = []
5195 keep_waiting = False
5196 result = self.vimconn._delete_created_items(
5197 created_items, volumes_to_hold, keep_waiting
5198 )
5199 self.assertEqual(result, False)
5200 self.assertEqual(mock_get_item_name_id.call_count, 2)
5201 mock_delete_volumes_by_id_wth_cinder.assert_called_once_with(
5202 f"volume:{volume_id}", f"{volume_id}", [], created_items
5203 )
5204 mock_delete_floating_ip_by_id.assert_not_called()
5205 self.vimconn.logger.error.assert_not_called()
5206
5207 @patch.object(vimconnector, "_get_item_name_id")
5208 @patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
5209 @patch.object(vimconnector, "_delete_floating_ip_by_id")
5210 def test_delete_created_items_no_volume(
5211 self,
5212 mock_delete_floating_ip_by_id,
5213 mock_delete_volumes_by_id_wth_cinder,
5214 mock_get_item_name_id,
5215 ):
5216 """Created items does not have volume."""
5217 created_items = {
5218 f"floating_ip:{floating_network_vim_id}": True,
5219 f"port:{port_id}": None,
5220 }
5221 mock_get_item_name_id.side_effect = [
5222 ("floating_ip", f"{floating_network_vim_id}")
5223 ]
5224 volumes_to_hold = []
5225 keep_waiting = False
5226 result = self.vimconn._delete_created_items(
5227 created_items, volumes_to_hold, keep_waiting
5228 )
5229 self.assertEqual(result, False)
5230 self.assertEqual(mock_get_item_name_id.call_count, 1)
5231 mock_delete_volumes_by_id_wth_cinder.assert_not_called()
5232 mock_delete_floating_ip_by_id.assert_called_once_with(
5233 f"floating_ip:{floating_network_vim_id}",
5234 f"{floating_network_vim_id}",
5235 created_items,
5236 )
5237 self.vimconn.logger.error.assert_not_called()
5238
5239 @patch.object(vimconnector, "_get_item_name_id")
5240 @patch.object(vimconnector, "_delete_volumes_by_id_wth_cinder")
5241 @patch.object(vimconnector, "_delete_floating_ip_by_id")
5242 def test_delete_created_items_already_deleted(
5243 self,
5244 mock_delete_floating_ip_by_id,
5245 mock_delete_volumes_by_id_wth_cinder,
5246 mock_get_item_name_id,
5247 ):
5248 """All created items are alerady deleted."""
5249 created_items = {
5250 f"floating_ip:{floating_network_vim_id}": None,
5251 f"volume:{volume_id}": None,
5252 f"port:{port_id}": None,
5253 }
5254 volumes_to_hold = []
5255 keep_waiting = False
5256 result = self.vimconn._delete_created_items(
5257 created_items, volumes_to_hold, keep_waiting
5258 )
5259 self.assertEqual(result, False)
5260 mock_get_item_name_id.assert_not_called()
5261 mock_delete_volumes_by_id_wth_cinder.assert_not_called()
5262 mock_delete_floating_ip_by_id.assert_not_called()
5263 self.vimconn.logger.error.assert_not_called()
5264
5265 @patch("time.sleep")
5266 @patch.object(vimconnector, "_format_exception")
5267 @patch.object(vimconnector, "_reload_connection")
5268 @patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
5269 @patch.object(vimconnector, "_delete_created_items")
5270 def test_delete_vminstance_successfully(
5271 self,
5272 mock_delete_created_items,
5273 mock_delete_vm_ports_attached_to_network,
5274 mock_reload_connection,
5275 mock_format_exception,
5276 mock_sleep,
5277 ):
5278 vm_id = f"{virtual_mac_id}"
5279 created_items = deepcopy(created_items_all_true)
5280 volumes_to_hold = [f"{volume_id}", f"{volume_id2}"]
5281 mock_delete_created_items.return_value = False
5282 self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
5283 mock_reload_connection.assert_called_once()
5284 mock_delete_vm_ports_attached_to_network.assert_called_once_with(created_items)
5285 self.vimconn.nova.servers.delete.assert_called_once_with(vm_id)
5286 mock_delete_created_items.assert_called_once_with(
5287 created_items, volumes_to_hold, False
5288 )
5289 mock_sleep.assert_not_called()
5290 mock_format_exception.assert_not_called()
5291
5292 @patch("time.sleep")
5293 @patch.object(vimconnector, "_format_exception")
5294 @patch.object(vimconnector, "_reload_connection")
5295 @patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
5296 @patch.object(vimconnector, "_delete_created_items")
5297 def test_delete_vminstance_delete_created_items_raises(
5298 self,
5299 mock_delete_created_items,
5300 mock_delete_vm_ports_attached_to_network,
5301 mock_reload_connection,
5302 mock_format_exception,
5303 mock_sleep,
5304 ):
5305 """Delete creted items raises exception."""
5306 vm_id = f"{virtual_mac_id}"
5307 created_items = deepcopy(created_items_all_true)
5308 mock_sleep = MagicMock()
5309 volumes_to_hold = []
5310 err = ConnectionError("ClientException occurred.")
5311 mock_delete_created_items.side_effect = err
5312 with self.assertRaises(ConnectionError) as err:
5313 self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
5314 self.assertEqual(str(err), "ClientException occurred.")
5315 mock_reload_connection.assert_called_once()
5316 mock_delete_vm_ports_attached_to_network.assert_called_once_with(created_items)
5317 self.vimconn.nova.servers.delete.assert_called_once_with(vm_id)
5318 mock_delete_created_items.assert_called_once()
5319 mock_sleep.assert_not_called()
5320
5321 @patch("time.sleep")
5322 @patch.object(vimconnector, "_format_exception")
5323 @patch.object(vimconnector, "_reload_connection")
5324 @patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
5325 @patch.object(vimconnector, "_delete_created_items")
5326 def test_delete_vminstance_delete_vm_ports_raises(
5327 self,
5328 mock_delete_created_items,
5329 mock_delete_vm_ports_attached_to_network,
5330 mock_reload_connection,
5331 mock_format_exception,
5332 mock_sleep,
5333 ):
5334 """Delete vm ports raises exception."""
5335 vm_id = f"{virtual_mac_id}"
5336 created_items = deepcopy(created_items_all_true)
5337 volumes_to_hold = [f"{volume_id}", f"{volume_id2}"]
5338 err = ConnectionError("ClientException occurred.")
5339 mock_delete_vm_ports_attached_to_network.side_effect = err
5340 mock_delete_created_items.side_effect = err
5341 with self.assertRaises(ConnectionError) as err:
5342 self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
5343 self.assertEqual(str(err), "ClientException occurred.")
5344 mock_reload_connection.assert_called_once()
5345 mock_delete_vm_ports_attached_to_network.assert_called_once_with(created_items)
5346 self.vimconn.nova.servers.delete.assert_not_called()
5347 mock_delete_created_items.assert_not_called()
5348 mock_sleep.assert_not_called()
5349
5350 @patch("time.sleep")
5351 @patch.object(vimconnector, "_format_exception")
5352 @patch.object(vimconnector, "_reload_connection")
5353 @patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
5354 @patch.object(vimconnector, "_delete_created_items")
5355 def test_delete_vminstance_nova_server_delete_raises(
5356 self,
5357 mock_delete_created_items,
5358 mock_delete_vm_ports_attached_to_network,
5359 mock_reload_connection,
5360 mock_format_exception,
5361 mock_sleep,
5362 ):
5363 """Nova server delete raises exception."""
5364 vm_id = f"{virtual_mac_id}"
5365 created_items = deepcopy(created_items_all_true)
5366 volumes_to_hold = [f"{volume_id}", f"{volume_id2}"]
5367 err = VimConnConnectionException("ClientException occurred.")
5368 self.vimconn.nova.servers.delete.side_effect = err
5369 mock_delete_created_items.side_effect = err
5370 with self.assertRaises(VimConnConnectionException) as err:
5371 self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
5372 self.assertEqual(str(err), "ClientException occurred.")
5373 mock_reload_connection.assert_called_once()
5374 mock_delete_vm_ports_attached_to_network.assert_called_once_with(created_items)
5375 self.vimconn.nova.servers.delete.assert_called_once_with(vm_id)
5376 mock_delete_created_items.assert_not_called()
5377 mock_sleep.assert_not_called()
5378
5379 @patch("time.sleep")
5380 @patch.object(vimconnector, "_format_exception")
5381 @patch.object(vimconnector, "_reload_connection")
5382 @patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
5383 @patch.object(vimconnector, "_delete_created_items")
5384 def test_delete_vminstance_reload_connection_raises(
5385 self,
5386 mock_delete_created_items,
5387 mock_delete_vm_ports_attached_to_network,
5388 mock_reload_connection,
5389 mock_format_exception,
5390 mock_sleep,
5391 ):
5392 """Reload connection raises exception."""
5393 vm_id = f"{virtual_mac_id}"
5394 created_items = deepcopy(created_items_all_true)
5395 mock_sleep = MagicMock()
5396 volumes_to_hold = [f"{volume_id}", f"{volume_id2}"]
5397 err = ConnectionError("ClientException occurred.")
5398 mock_delete_created_items.return_value = False
5399 mock_reload_connection.side_effect = err
5400 with self.assertRaises(ConnectionError) as err:
5401 self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
5402 self.assertEqual(str(err), "ClientException occurred.")
5403 mock_reload_connection.assert_called_once()
5404 mock_delete_vm_ports_attached_to_network.assert_not_called()
5405 self.vimconn.nova.servers.delete.assert_not_called()
5406 mock_delete_created_items.assert_not_called()
5407 mock_sleep.assert_not_called()
5408
5409 @patch("time.sleep")
5410 @patch.object(vimconnector, "_format_exception")
5411 @patch.object(vimconnector, "_reload_connection")
5412 @patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
5413 @patch.object(vimconnector, "_delete_created_items")
5414 def test_delete_vminstance_created_item_vol_to_hold_are_none(
5415 self,
5416 mock_delete_created_items,
5417 mock_delete_vm_ports_attached_to_network,
5418 mock_reload_connection,
5419 mock_format_exception,
5420 mock_sleep,
5421 ):
5422 """created_items and volumes_to_hold are None."""
5423 vm_id = f"{virtual_mac_id}"
5424 created_items = None
5425 volumes_to_hold = None
5426 mock_delete_created_items.return_value = False
5427 self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
5428 mock_reload_connection.assert_called_once()
5429 mock_delete_vm_ports_attached_to_network.assert_not_called()
5430 self.vimconn.nova.servers.delete.assert_called_once_with(vm_id)
5431 mock_delete_created_items.assert_called_once_with({}, [], False)
5432 mock_sleep.assert_not_called()
5433 mock_format_exception.assert_not_called()
5434
5435 @patch("time.sleep")
5436 @patch.object(vimconnector, "_format_exception")
5437 @patch.object(vimconnector, "_reload_connection")
5438 @patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
5439 @patch.object(vimconnector, "_delete_created_items")
5440 def test_delete_vminstance_vm_id_is_none(
5441 self,
5442 mock_delete_created_items,
5443 mock_delete_vm_ports_attached_to_network,
5444 mock_reload_connection,
5445 mock_format_exception,
5446 mock_sleep,
5447 ):
5448 """vm_id is None."""
5449 vm_id = None
5450 created_items = deepcopy(created_items_all_true)
5451 volumes_to_hold = [f"{volume_id}", f"{volume_id2}"]
5452 mock_delete_created_items.side_effect = [True, True, False]
5453 self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
5454 mock_reload_connection.assert_called_once()
5455 mock_delete_vm_ports_attached_to_network.assert_called_once_with(created_items)
5456 self.vimconn.nova.servers.delete.assert_not_called()
5457 self.assertEqual(mock_delete_created_items.call_count, 3)
5458 self.assertEqual(mock_sleep.call_count, 2)
5459 mock_format_exception.assert_not_called()
5460
5461 @patch("time.sleep")
5462 @patch.object(vimconnector, "_format_exception")
5463 @patch.object(vimconnector, "_reload_connection")
5464 @patch.object(vimconnector, "_delete_vm_ports_attached_to_network")
5465 @patch.object(vimconnector, "_delete_created_items")
5466 def test_delete_vminstance_delete_created_items_return_true(
5467 self,
5468 mock_delete_created_items,
5469 mock_delete_vm_ports_attached_to_network,
5470 mock_reload_connection,
5471 mock_format_exception,
5472 mock_sleep,
5473 ):
5474 """Delete created items always return True."""
5475 vm_id = None
5476 created_items = deepcopy(created_items_all_true)
5477 volumes_to_hold = [f"{volume_id}", f"{volume_id2}"]
5478 mock_delete_created_items.side_effect = [True] * 1800
5479 self.vimconn.delete_vminstance(vm_id, created_items, volumes_to_hold)
5480 mock_reload_connection.assert_called_once()
5481 mock_delete_vm_ports_attached_to_network.assert_called_once_with(created_items)
5482 self.vimconn.nova.servers.delete.assert_not_called()
5483 self.assertEqual(mock_delete_created_items.call_count, 1800)
5484 self.assertEqual(mock_sleep.call_count, 1800)
5485 mock_format_exception.assert_not_called()
5486
5487 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
5488 def test_get_monitoring_data(self, mock_reload_conection):
5489 servers = ["server1", "server2"]
5490 ports = {"ports": ["port1", "port2"]}
5491 self.vimconn.nova.servers.list.return_value = servers
5492 self.vimconn.neutron.list_ports.return_value = ports
5493 result = self.vimconn.get_monitoring_data()
5494 self.assertTupleEqual(result, (servers, ports))
5495 mock_reload_conection.assert_called_once()
5496 self.vimconn.nova.servers.list.assert_called_once_with(detailed=True)
5497 self.vimconn.neutron.list_ports.assert_called_once()
5498
5499 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
5500 def test_get_monitoring_data_reload_connection_raises(self, mock_reload_conection):
5501 mock_reload_conection.side_effect = VimConnNotFoundException(
5502 "Connection object not found."
5503 )
5504 with self.assertRaises(VimConnException) as err:
5505 result = self.vimconn.get_monitoring_data()
5506 self.assertTupleEqual(result, None)
5507 self.assertEqual(
5508 str(err.exception.args[0]),
5509 "Exception in monitoring while getting VMs and ports status: Connection object not found.",
5510 )
5511 mock_reload_conection.assert_called_once()
5512 check_if_assert_not_called(
5513 [self.vimconn.nova.servers.list, self.vimconn.neutron.list_ports]
5514 )
5515
5516 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
5517 def test_get_monitoring_data_server_list_raises(self, mock_reload_conection):
5518 self.vimconn.nova.servers.list.side_effect = VimConnConnectionException(
5519 "Can not connect to Cloud API."
5520 )
5521 with self.assertRaises(VimConnException) as err:
5522 result = self.vimconn.get_monitoring_data()
5523 self.assertTupleEqual(result, None)
5524 self.assertEqual(
5525 str(err.exception.args[0]),
5526 "Exception in monitoring while getting VMs and ports status: Can not connect to Cloud API.",
5527 )
5528 mock_reload_conection.assert_called_once()
5529 self.vimconn.nova.servers.list.assert_called_once_with(detailed=True)
5530 self.vimconn.neutron.list_ports.assert_not_called()
5531
5532 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
5533 def test_get_monitoring_data_list_ports_raises(self, mock_reload_conection):
5534 self.vimconn.neutron.list_ports.side_effect = VimConnConnectionException(
5535 "Can not connect to Cloud API."
5536 )
5537 with self.assertRaises(VimConnException) as err:
5538 result = self.vimconn.get_monitoring_data()
5539 self.assertTupleEqual(result, None)
5540 self.assertEqual(
5541 str(err.exception.args[0]),
5542 "Exception in monitoring while getting VMs and ports status: Can not connect to Cloud API.",
5543 )
5544 mock_reload_conection.assert_called_once()
5545 self.vimconn.nova.servers.list.assert_called_once_with(detailed=True)
5546 self.vimconn.neutron.list_ports.assert_called_once()
5547
5548
5549 class TestNewFlavor(unittest.TestCase):
5550 @patch("logging.getLogger", autospec=True)
5551 def setUp(self, mock_logger):
5552 # We are disabling the logging of exception not to print them to console.
5553 mock_logger = logging.getLogger()
5554 mock_logger.disabled = True
5555 self.vimconn = vimconnector(
5556 "123",
5557 "openstackvim",
5558 "456",
5559 "789",
5560 "http://dummy.url",
5561 None,
5562 "user",
5563 "pass",
5564 )
5565 self.vimconn.nova = CopyingMock(autospec=True)
5566 self.flavor1 = CopyingMock(autospec=True, name="sample-flavor")
5567 self.flavor2 = CopyingMock(autospec=True, name="other-flavor")
5568 self.new_flavor = CopyingMock(autospec=True, name="new_flavor")
5569 self.new_flavor.id = "075d2482-5edb-43e3-91b3-234e65b6268a"
5570 self.vimconn.nova.flavors.create.return_value = self.new_flavor
5571
5572 @patch.object(vimconnector, "process_vio_numa_nodes", new_callable=CopyingMock())
5573 @patch.object(vimconnector, "process_numa_memory", new_callable=CopyingMock())
5574 @patch.object(vimconnector, "process_numa_vcpu", new_callable=CopyingMock())
5575 @patch.object(
5576 vimconnector,
5577 "process_numa_paired_threads",
5578 new_callable=CopyingMock(),
5579 )
5580 @patch.object(vimconnector, "process_numa_cores", new_callable=CopyingMock())
5581 @patch.object(vimconnector, "process_numa_threads", new_callable=CopyingMock())
5582 def test_process_numa_parameters_of_flavor_id_memory_vcpu_in_numa_type_vio(
5583 self,
5584 mock_process_numa_threads,
5585 mock_process_numa_cores,
5586 mock_process_numa_paired_threads,
5587 mock_process_numa_vcpu,
5588 mock_process_numa_memory,
5589 mock_process_vio_numa_nodes,
5590 ):
5591 """Process numa parameters, id, memory, vcpu exist, vim type is VIO,
5592 paired-threads, cores, threads do not exist in numa.
5593 """
5594 numas = [
5595 {"id": 0, "memory": 1, "vcpu": [1, 3]},
5596 {"id": 1, "memory": 2, "vcpu": [2]},
5597 ]
5598 extra_specs = {}
5599 expected_extra_specs = {
5600 "hw:numa_nodes": "2",
5601 "hw:cpu_sockets": "2",
5602 }
5603 self.vimconn.vim_type = "VIO"
5604 self.vimconn._process_numa_parameters_of_flavor(numas, extra_specs)
5605
5606 self.assertEqual(mock_process_numa_memory.call_count, 2)
5607 self.assertEqual(mock_process_numa_vcpu.call_count, 2)
5608 mock_process_vio_numa_nodes.assert_called_once_with(2, {"hw:numa_nodes": "2"})
5609 _call_mock_process_numa_memory = mock_process_numa_memory.call_args_list
5610 self.assertEqual(
5611 _call_mock_process_numa_memory[0].args,
5612 (
5613 {"id": 0, "memory": 1, "vcpu": [1, 3]},
5614 0,
5615 {
5616 "hw:numa_nodes": "2",
5617 },
5618 ),
5619 )
5620 self.assertEqual(
5621 _call_mock_process_numa_memory[1].args,
5622 (
5623 {"id": 1, "memory": 2, "vcpu": [2]},
5624 1,
5625 {
5626 "hw:cpu_sockets": "2",
5627 "hw:numa_nodes": "2",
5628 },
5629 ),
5630 )
5631 _call_mock_process_numa_vcpu = mock_process_numa_vcpu.call_args_list
5632 self.assertEqual(
5633 _call_mock_process_numa_vcpu[0].args,
5634 (
5635 {"id": 0, "memory": 1, "vcpu": [1, 3]},
5636 0,
5637 {
5638 "hw:numa_nodes": "2",
5639 },
5640 ),
5641 )
5642 self.assertEqual(
5643 _call_mock_process_numa_vcpu[1].args,
5644 (
5645 {"id": 1, "memory": 2, "vcpu": [2]},
5646 1,
5647 {
5648 "hw:cpu_sockets": "2",
5649 "hw:numa_nodes": "2",
5650 },
5651 ),
5652 )
5653 self.assertDictEqual(extra_specs, expected_extra_specs)
5654 check_if_assert_not_called(
5655 [
5656 mock_process_numa_threads,
5657 mock_process_numa_cores,
5658 mock_process_numa_paired_threads,
5659 ]
5660 )
5661
5662 @patch.object(vimconnector, "process_vio_numa_nodes", new_callable=CopyingMock())
5663 @patch.object(vimconnector, "process_numa_memory", new_callable=CopyingMock())
5664 @patch.object(vimconnector, "process_numa_vcpu", new_callable=CopyingMock())
5665 @patch.object(
5666 vimconnector,
5667 "process_numa_paired_threads",
5668 new_callable=CopyingMock(),
5669 )
5670 @patch.object(vimconnector, "process_numa_cores", new_callable=CopyingMock())
5671 @patch.object(vimconnector, "process_numa_threads", new_callable=CopyingMock())
5672 def test_process_numa_parameters_of_flavor_id_memory_vcpu_in_numa_type_openstack(
5673 self,
5674 mock_process_numa_threads,
5675 mock_process_numa_cores,
5676 mock_process_numa_paired_threads,
5677 mock_process_numa_vcpu,
5678 mock_process_numa_memory,
5679 mock_process_vio_numa_nodes,
5680 ):
5681 """Process numa parameters, id, memory, vcpu exist, vim type is openstack,
5682 paired-threads, cores, threads do not exist in numa.
5683 """
5684 numas = [
5685 {"id": 0, "memory": 1, "vcpu": [1, 3]},
5686 {"id": 1, "memory": 2, "vcpu": [2]},
5687 ]
5688 extra_specs = {}
5689 expected_extra_specs = {
5690 "hw:numa_nodes": "2",
5691 "hw:cpu_sockets": "2",
5692 }
5693 self.vimconn.vim_type = "openstack"
5694 self.vimconn._process_numa_parameters_of_flavor(numas, extra_specs)
5695
5696 self.assertEqual(mock_process_numa_memory.call_count, 2)
5697 self.assertEqual(mock_process_numa_vcpu.call_count, 2)
5698 _call_mock_process_numa_memory = mock_process_numa_memory.call_args_list
5699 self.assertEqual(
5700 _call_mock_process_numa_memory[0].args,
5701 (
5702 {"id": 0, "memory": 1, "vcpu": [1, 3]},
5703 0,
5704 {"hw:numa_nodes": "2"},
5705 ),
5706 )
5707 self.assertEqual(
5708 _call_mock_process_numa_memory[1].args,
5709 (
5710 {"id": 1, "memory": 2, "vcpu": [2]},
5711 1,
5712 {"hw:cpu_sockets": "2", "hw:numa_nodes": "2"},
5713 ),
5714 )
5715 _call_mock_process_numa_vcpu = mock_process_numa_vcpu.call_args_list
5716 self.assertEqual(
5717 _call_mock_process_numa_vcpu[0].args,
5718 (
5719 {"id": 0, "memory": 1, "vcpu": [1, 3]},
5720 0,
5721 {"hw:numa_nodes": "2"},
5722 ),
5723 )
5724 self.assertEqual(
5725 _call_mock_process_numa_vcpu[1].args,
5726 (
5727 {"id": 1, "memory": 2, "vcpu": [2]},
5728 1,
5729 {"hw:cpu_sockets": "2", "hw:numa_nodes": "2"},
5730 ),
5731 )
5732 self.assertDictEqual(extra_specs, expected_extra_specs)
5733 check_if_assert_not_called(
5734 [
5735 mock_process_numa_threads,
5736 mock_process_numa_cores,
5737 mock_process_numa_paired_threads,
5738 ]
5739 )
5740
5741 @patch.object(vimconnector, "process_vio_numa_nodes", new_callable=CopyingMock())
5742 @patch.object(vimconnector, "process_numa_memory", new_callable=CopyingMock())
5743 @patch.object(vimconnector, "process_numa_vcpu", new_callable=CopyingMock())
5744 @patch.object(
5745 vimconnector,
5746 "process_numa_paired_threads",
5747 new_callable=CopyingMock(),
5748 )
5749 @patch.object(vimconnector, "process_numa_cores", new_callable=CopyingMock())
5750 @patch.object(vimconnector, "process_numa_threads", new_callable=CopyingMock())
5751 def test_process_numa_parameters_of_flavor_id_paired_threads_in_numa_type_openstack_extra_spec_not_empty(
5752 self,
5753 mock_process_numa_threads,
5754 mock_process_numa_cores,
5755 mock_process_numa_paired_threads,
5756 mock_process_numa_vcpu,
5757 mock_process_numa_memory,
5758 mock_process_vio_numa_nodes,
5759 ):
5760 """Process numa parameters, id, paired-threads exist, vim type is openstack.
5761 vcpus calculation according to paired-threads in numa, there is extra_spec.
5762 ."""
5763 numas = [{"id": 0, "paired-threads": 3}, {"id": 1, "paired-threads": 3}]
5764 extra_specs = {"some-key": "some-value"}
5765 expected_extra_specs = {
5766 "hw:cpu_sockets": "2",
5767 "hw:cpu_threads": "12",
5768 "hw:numa_nodes": "2",
5769 "some-key": "some-value",
5770 }
5771 self.vimconn.vim_type = "openstack"
5772 mock_process_numa_paired_threads.side_effect = [6, 6]
5773 self.vimconn._process_numa_parameters_of_flavor(numas, extra_specs)
5774
5775 check_if_assert_not_called([mock_process_numa_threads, mock_process_numa_cores])
5776 self.assertEqual(mock_process_numa_memory.call_count, 2)
5777 self.assertEqual(mock_process_numa_vcpu.call_count, 2)
5778 self.assertEqual(mock_process_numa_paired_threads.call_count, 2)
5779 _call_mock_process_numa_paired_threads = (
5780 mock_process_numa_paired_threads.call_args_list
5781 )
5782 self.assertEqual(
5783 _call_mock_process_numa_paired_threads[0].args,
5784 (
5785 {"id": 0, "paired-threads": 3},
5786 {"hw:cpu_sockets": "2", "hw:numa_nodes": "2", "some-key": "some-value"},
5787 ),
5788 )
5789 self.assertEqual(
5790 _call_mock_process_numa_paired_threads[1].args,
5791 (
5792 {"id": 1, "paired-threads": 3},
5793 {"hw:cpu_sockets": "2", "hw:numa_nodes": "2", "some-key": "some-value"},
5794 ),
5795 )
5796 self.assertDictEqual(extra_specs, expected_extra_specs)
5797
5798 @patch.object(vimconnector, "process_vio_numa_nodes", new_callable=CopyingMock())
5799 @patch.object(vimconnector, "process_numa_memory", new_callable=CopyingMock())
5800 @patch.object(vimconnector, "process_numa_vcpu", new_callable=CopyingMock())
5801 @patch.object(
5802 vimconnector,
5803 "process_numa_paired_threads",
5804 new_callable=CopyingMock(),
5805 )
5806 @patch.object(vimconnector, "process_numa_cores", new_callable=CopyingMock())
5807 @patch.object(vimconnector, "process_numa_threads", new_callable=CopyingMock())
5808 def test_process_numa_parameters_of_flavor_id_paired_threads_in_numa_type_vio_extra_spec_not_empty(
5809 self,
5810 mock_process_numa_threads,
5811 mock_process_numa_cores,
5812 mock_process_numa_paired_threads,
5813 mock_process_numa_vcpu,
5814 mock_process_numa_memory,
5815 mock_process_vio_numa_nodes,
5816 ):
5817 """Process numa parameters, id, paired-threads exist, vim type is VIO.
5818 vcpus calculation according to paired-threads in numa, there is extra_spec.
5819 """
5820 numas = [{"id": 0, "paired-threads": 2}, {"id": 1, "paired-threads": 2}]
5821 extra_specs = {"some-key": "some-value"}
5822 expected_extra_specs = {
5823 "hw:numa_nodes": "2",
5824 "hw:cpu_sockets": "2",
5825 "hw:cpu_threads": "8",
5826 "some-key": "some-value",
5827 }
5828 self.vimconn.vim_type = "VIO"
5829 mock_process_numa_paired_threads.side_effect = [4, 4]
5830 self.vimconn._process_numa_parameters_of_flavor(numas, extra_specs)
5831 check_if_assert_not_called([mock_process_numa_threads, mock_process_numa_cores])
5832 self.assertEqual(mock_process_numa_paired_threads.call_count, 2)
5833 self.assertEqual(mock_process_numa_memory.call_count, 2)
5834 self.assertEqual(mock_process_numa_vcpu.call_count, 2)
5835 _call_mock_process_numa_paired_threads = (
5836 mock_process_numa_paired_threads.call_args_list
5837 )
5838 mock_process_vio_numa_nodes.assert_called_once_with(
5839 2, {"some-key": "some-value", "hw:numa_nodes": "2"}
5840 )
5841 self.assertEqual(
5842 _call_mock_process_numa_paired_threads[0].args,
5843 (
5844 {"id": 0, "paired-threads": 2},
5845 {
5846 "hw:cpu_sockets": "2",
5847 "hw:numa_nodes": "2",
5848 "some-key": "some-value",
5849 },
5850 ),
5851 )
5852 self.assertEqual(
5853 _call_mock_process_numa_paired_threads[1].args,
5854 (
5855 {"id": 1, "paired-threads": 2},
5856 {
5857 "hw:cpu_sockets": "2",
5858 "hw:numa_nodes": "2",
5859 "some-key": "some-value",
5860 },
5861 ),
5862 )
5863 self.assertDictEqual(extra_specs, expected_extra_specs)
5864
5865 @patch.object(vimconnector, "process_vio_numa_nodes", new_callable=CopyingMock())
5866 @patch.object(vimconnector, "process_numa_memory", new_callable=CopyingMock())
5867 @patch.object(vimconnector, "process_numa_vcpu", new_callable=CopyingMock())
5868 @patch.object(
5869 vimconnector,
5870 "process_numa_paired_threads",
5871 new_callable=CopyingMock(),
5872 )
5873 @patch.object(vimconnector, "process_numa_cores", new_callable=CopyingMock())
5874 @patch.object(vimconnector, "process_numa_threads", new_callable=CopyingMock())
5875 def test_process_numa_parameters_of_flavor_id_cores_in_numa_type_openstack(
5876 self,
5877 mock_process_numa_threads,
5878 mock_process_numa_cores,
5879 mock_process_numa_paired_threads,
5880 mock_process_numa_vcpu,
5881 mock_process_numa_memory,
5882 mock_process_vio_numa_nodes,
5883 ):
5884 """Process numa parameters, id, cores exist, vim type is openstack.
5885 vcpus calculation according to cores in numa.
5886 """
5887 numas = [{"id": 0, "cores": 1}, {"id": 1, "cores": 2}]
5888 extra_specs = {}
5889 updated_extra_specs = {"hw:numa_nodes": "2", "hw:cpu_sockets": "2"}
5890 expected_extra_specs = {
5891 "hw:numa_nodes": "2",
5892 "hw:cpu_sockets": "2",
5893 "hw:cpu_cores": "3",
5894 }
5895 self.vimconn.vim_type = "openstack"
5896 mock_process_numa_cores.side_effect = [1, 2]
5897 self.vimconn._process_numa_parameters_of_flavor(numas, extra_specs)
5898
5899 check_if_assert_not_called(
5900 [mock_process_numa_threads, mock_process_numa_paired_threads]
5901 )
5902 self.assertEqual(mock_process_numa_cores.call_count, 2)
5903 self.assertEqual(mock_process_numa_memory.call_count, 2)
5904 self.assertEqual(mock_process_numa_vcpu.call_count, 2)
5905 _call_mock_process_numa_cores = mock_process_numa_cores.call_args_list
5906 self.assertEqual(
5907 _call_mock_process_numa_cores[0].args,
5908 ({"id": 0, "cores": 1}, updated_extra_specs),
5909 )
5910 self.assertEqual(
5911 _call_mock_process_numa_cores[1].args,
5912 ({"id": 1, "cores": 2}, updated_extra_specs),
5913 )
5914 self.assertDictEqual(extra_specs, expected_extra_specs)
5915
5916 @patch.object(vimconnector, "process_vio_numa_nodes", new_callable=CopyingMock())
5917 @patch.object(vimconnector, "process_numa_memory", new_callable=CopyingMock())
5918 @patch.object(vimconnector, "process_numa_vcpu", new_callable=CopyingMock())
5919 @patch.object(
5920 vimconnector,
5921 "process_numa_paired_threads",
5922 new_callable=CopyingMock(),
5923 )
5924 @patch.object(vimconnector, "process_numa_cores", new_callable=CopyingMock())
5925 @patch.object(vimconnector, "process_numa_threads", new_callable=CopyingMock())
5926 def test_process_numa_parameters_of_flavor_id_cores_in_numa_type_vio(
5927 self,
5928 mock_process_numa_threads,
5929 mock_process_numa_cores,
5930 mock_process_numa_paired_threads,
5931 mock_process_numa_vcpu,
5932 mock_process_numa_memory,
5933 mock_process_vio_numa_nodes,
5934 ):
5935 """Process numa parameters, id, cores exist, vim type is VIO.
5936 vcpus calculation according to cores in numa.
5937 """
5938 numas = [{"id": 0, "cores": 1}, {"id": 1, "cores": 2}]
5939 extra_specs = {}
5940 expected_extra_specs = {
5941 "hw:cpu_cores": "3",
5942 "hw:cpu_sockets": "2",
5943 "hw:numa_nodes": "2",
5944 }
5945 self.vimconn.vim_type = "VIO"
5946 mock_process_numa_cores.side_effect = [1, 2]
5947 self.vimconn._process_numa_parameters_of_flavor(numas, extra_specs)
5948 check_if_assert_not_called(
5949 [mock_process_numa_threads, mock_process_numa_paired_threads]
5950 )
5951 self.assertEqual(mock_process_numa_memory.call_count, 2)
5952 self.assertEqual(mock_process_numa_vcpu.call_count, 2)
5953 self.assertEqual(mock_process_numa_cores.call_count, 2)
5954 mock_process_vio_numa_nodes.assert_called_once_with(2, {"hw:numa_nodes": "2"})
5955 _call_mock_process_numa_cores = mock_process_numa_cores.call_args_list
5956 self.assertEqual(
5957 _call_mock_process_numa_cores[0].args,
5958 (
5959 {"id": 0, "cores": 1},
5960 {
5961 "hw:cpu_sockets": "2",
5962 "hw:numa_nodes": "2",
5963 },
5964 ),
5965 )
5966 self.assertEqual(
5967 _call_mock_process_numa_cores[1].args,
5968 (
5969 {"id": 1, "cores": 2},
5970 {
5971 "hw:cpu_sockets": "2",
5972 "hw:numa_nodes": "2",
5973 },
5974 ),
5975 )
5976 self.assertDictEqual(extra_specs, expected_extra_specs)
5977
5978 @patch.object(vimconnector, "process_vio_numa_nodes", new_callable=CopyingMock())
5979 @patch.object(vimconnector, "process_numa_memory", new_callable=CopyingMock())
5980 @patch.object(vimconnector, "process_numa_vcpu", new_callable=CopyingMock())
5981 @patch.object(
5982 vimconnector,
5983 "process_numa_paired_threads",
5984 new_callable=CopyingMock(),
5985 )
5986 @patch.object(vimconnector, "process_numa_cores", new_callable=CopyingMock())
5987 @patch.object(vimconnector, "process_numa_threads", new_callable=CopyingMock())
5988 def test_process_numa_parameters_of_flavor_without_numa_id_with_threads_type_vio(
5989 self,
5990 mock_process_numa_threads,
5991 mock_process_numa_cores,
5992 mock_process_numa_paired_threads,
5993 mock_process_numa_vcpu,
5994 mock_process_numa_memory,
5995 mock_process_vio_numa_nodes,
5996 ):
5997 """Process numa parameters, memory, vcpu, thread exist, vim type is VIO,
5998 vcpus calculation according threads in numa, there are not numa ids.
5999 """
6000 numas = [
6001 {"memory": 1, "vcpu": [1, 3], "threads": 3},
6002 {"memory": 2, "vcpu": [2]},
6003 ]
6004 extra_specs = {}
6005 expected_extra_specs = {
6006 "hw:numa_nodes": "2",
6007 "hw:cpu_sockets": "2",
6008 "hw:cpu_threads": "3",
6009 }
6010 self.vimconn.vim_type = "VIO"
6011 mock_process_numa_threads.return_value = 3
6012 self.vimconn._process_numa_parameters_of_flavor(numas, extra_specs)
6013 check_if_assert_not_called(
6014 [
6015 mock_process_numa_memory,
6016 mock_process_numa_vcpu,
6017 mock_process_numa_cores,
6018 mock_process_numa_paired_threads,
6019 ]
6020 )
6021 mock_process_vio_numa_nodes.assert_called_once_with(2, {"hw:numa_nodes": "2"})
6022 self.assertEqual(mock_process_numa_threads.call_count, 1)
6023 _call_mock_process_numa_threads = mock_process_numa_threads.call_args_list
6024 self.assertEqual(
6025 _call_mock_process_numa_threads[0].args,
6026 (
6027 {"memory": 1, "vcpu": [1, 3], "threads": 3},
6028 {
6029 "hw:cpu_sockets": "2",
6030 "hw:numa_nodes": "2",
6031 },
6032 ),
6033 )
6034 self.assertDictEqual(extra_specs, expected_extra_specs)
6035
6036 @patch.object(vimconnector, "process_vio_numa_nodes", new_callable=CopyingMock())
6037 @patch.object(vimconnector, "process_numa_memory", new_callable=CopyingMock())
6038 @patch.object(vimconnector, "process_numa_vcpu", new_callable=CopyingMock())
6039 @patch.object(
6040 vimconnector,
6041 "process_numa_paired_threads",
6042 new_callable=CopyingMock(autospec=True),
6043 )
6044 @patch.object(vimconnector, "process_numa_cores", new_callable=CopyingMock())
6045 @patch.object(vimconnector, "process_numa_threads", new_callable=CopyingMock())
6046 def test_process_numa_parameters_of_flavor_without_numa_id_with_threads_type_openstack(
6047 self,
6048 mock_process_numa_threads,
6049 mock_process_numa_cores,
6050 mock_process_numa_paired_threads,
6051 mock_process_numa_vcpu,
6052 mock_process_numa_memory,
6053 mock_process_vio_numa_nodes,
6054 ):
6055 """Process numa parameters, memory, vcpu, thread exist, vim type is openstack,
6056 vcpus calculation according threads in numa, there are not numa ids.
6057 """
6058 numas = [
6059 {"memory": 1, "vcpu": [1, 3], "threads": 3},
6060 {"memory": 2, "vcpu": [2]},
6061 ]
6062 extra_specs = {}
6063 expected_extra_specs = {
6064 "hw:numa_nodes": "2",
6065 "hw:cpu_sockets": "2",
6066 "hw:cpu_threads": "3",
6067 }
6068 self.vimconn.vim_type = "openstack"
6069 mock_process_numa_threads.return_value = 3
6070 self.vimconn._process_numa_parameters_of_flavor(numas, extra_specs)
6071
6072 check_if_assert_not_called(
6073 [
6074 mock_process_numa_memory,
6075 mock_process_numa_vcpu,
6076 mock_process_numa_cores,
6077 mock_process_numa_paired_threads,
6078 mock_process_vio_numa_nodes,
6079 ]
6080 )
6081 self.assertEqual(mock_process_numa_threads.call_count, 1)
6082 _call_mock_process_numa_threads = mock_process_numa_threads.call_args_list
6083 self.assertEqual(
6084 _call_mock_process_numa_threads[0].args,
6085 (
6086 {"memory": 1, "vcpu": [1, 3], "threads": 3},
6087 {"hw:cpu_sockets": "2", "hw:numa_nodes": "2"},
6088 ),
6089 )
6090 self.assertDictEqual(extra_specs, expected_extra_specs)
6091
6092 @patch.object(vimconnector, "process_vio_numa_nodes", new_callable=CopyingMock())
6093 @patch.object(vimconnector, "process_numa_memory", new_callable=CopyingMock())
6094 @patch.object(vimconnector, "process_numa_vcpu", new_callable=CopyingMock())
6095 @patch.object(
6096 vimconnector,
6097 "process_numa_paired_threads",
6098 new_callable=CopyingMock(),
6099 )
6100 @patch.object(vimconnector, "process_numa_cores", new_callable=CopyingMock())
6101 @patch.object(vimconnector, "process_numa_threads", new_callable=CopyingMock())
6102 def test_process_numa_parameters_of_flavor_empty_numas_list_type_vio(
6103 self,
6104 mock_process_numa_threads,
6105 mock_process_numa_cores,
6106 mock_process_numa_paired_threads,
6107 mock_process_numa_vcpu,
6108 mock_process_numa_memory,
6109 mock_process_vio_numa_nodes,
6110 ):
6111 """Numa list is empty, vim type is VIO."""
6112 numas = []
6113 extra_specs = {}
6114 expected_extra_specs = {"hw:numa_nodes": "0"}
6115 self.vimconn.vim_type = "VIO"
6116 self.vimconn._process_numa_parameters_of_flavor(numas, extra_specs)
6117 check_if_assert_not_called(
6118 [
6119 mock_process_numa_memory,
6120 mock_process_numa_vcpu,
6121 mock_process_numa_cores,
6122 mock_process_numa_paired_threads,
6123 mock_process_numa_threads,
6124 ]
6125 )
6126 mock_process_vio_numa_nodes.assert_called_once_with(0, {"hw:numa_nodes": "0"})
6127 self.assertDictEqual(extra_specs, expected_extra_specs)
6128
6129 @patch.object(vimconnector, "process_vio_numa_nodes", new_callable=CopyingMock())
6130 @patch.object(vimconnector, "process_numa_memory", new_callable=CopyingMock())
6131 @patch.object(vimconnector, "process_numa_vcpu", new_callable=CopyingMock())
6132 @patch.object(
6133 vimconnector,
6134 "process_numa_paired_threads",
6135 new_callable=CopyingMock(),
6136 )
6137 @patch.object(vimconnector, "process_numa_cores", new_callable=CopyingMock())
6138 @patch.object(vimconnector, "process_numa_threads", new_callable=CopyingMock())
6139 def test_process_numa_parameters_of_flavor_empty_numas_list_type_openstack(
6140 self,
6141 mock_process_numa_threads,
6142 mock_process_numa_cores,
6143 mock_process_numa_paired_threads,
6144 mock_process_numa_vcpu,
6145 mock_process_numa_memory,
6146 mock_process_vio_numa_nodes,
6147 ):
6148 """Numa list is empty, vim type is openstack."""
6149 numas = []
6150 extra_specs = {}
6151 expected_extra_specs = {"hw:numa_nodes": "0"}
6152 self.vimconn.vim_type = "openstack"
6153 mock_process_numa_threads.return_value = None
6154 self.vimconn._process_numa_parameters_of_flavor(numas, extra_specs)
6155
6156 check_if_assert_not_called(
6157 [
6158 mock_process_numa_memory,
6159 mock_process_numa_vcpu,
6160 mock_process_numa_cores,
6161 mock_process_numa_paired_threads,
6162 mock_process_numa_threads,
6163 mock_process_vio_numa_nodes,
6164 ]
6165 )
6166 self.assertDictEqual(extra_specs, expected_extra_specs)
6167
6168 def test_process_numa_memory_empty_extra_spec(self):
6169 numa = {"memory": 2, "vcpu": [2]}
6170 node_id = 2
6171 extra_specs = {}
6172 expected_extra_spec = {"hw:numa_mem.2": 2048}
6173 self.vimconn.process_numa_memory(numa, node_id, extra_specs)
6174 self.assertDictEqual(extra_specs, expected_extra_spec)
6175
6176 def test_process_numa_memory_not_exist(self):
6177 numa = {"vcpu": [2]}
6178 node_id = 2
6179 extra_specs = {"vmware:latency_sensitivity_level": "high"}
6180 self.vimconn.process_numa_memory(numa, node_id, extra_specs)
6181 self.assertDictEqual(extra_specs, {"vmware:latency_sensitivity_level": "high"})
6182
6183 def test_process_numa_memory_node_id_is_none(self):
6184 numa = {"memory": 2, "vcpu": [2]}
6185 node_id = None
6186 extra_specs = {}
6187 expected_extra_spec = {"hw:numa_mem.None": 2048}
6188 self.vimconn.process_numa_memory(numa, node_id, extra_specs)
6189 self.assertDictEqual(extra_specs, expected_extra_spec)
6190
6191 def test_process_numa_vcpu_empty_extra_spec(self):
6192 numa = {"vcpu": [2]}
6193 node_id = 0
6194 extra_specs = {}
6195 expected_extra_spec = {"hw:numa_cpus.0": "2"}
6196 self.vimconn.process_numa_vcpu(numa, node_id, extra_specs)
6197 self.assertDictEqual(extra_specs, expected_extra_spec)
6198
6199 def test_process_numa_vcpu_not_exist(self):
6200 numa = {"memory": 2}
6201 node_id = 0
6202 extra_specs = {"vmware:latency_sensitivity_level": "high"}
6203 expected_extra_spec = {"vmware:latency_sensitivity_level": "high"}
6204 self.vimconn.process_numa_vcpu(numa, node_id, extra_specs)
6205 self.assertDictEqual(extra_specs, expected_extra_spec)
6206
6207 def test_process_numa_vcpu_empty_node_id(self):
6208 numa = {"vcpu": [2]}
6209 node_id = ""
6210 extra_specs = {}
6211 expected_extra_spec = {"hw:numa_cpus.": "2"}
6212 self.vimconn.process_numa_vcpu(numa, node_id, extra_specs)
6213 self.assertDictEqual(extra_specs, expected_extra_spec)
6214
6215 def test_process_numa_vcpu_empty_numa_dict(self):
6216 numa = {}
6217 node_id = 4
6218 extra_specs = {}
6219 self.vimconn.process_numa_vcpu(numa, node_id, extra_specs)
6220 self.assertDictEqual(extra_specs, {})
6221
6222 def test_process_numa_vcpu_str_node_id(self):
6223 numa = {"vcpu": [2]}
6224 node_id = "12"
6225 extra_specs = {}
6226 expected_extra_spec = {"hw:numa_cpus.12": "2"}
6227 self.vimconn.process_numa_vcpu(numa, node_id, extra_specs)
6228 self.assertDictEqual(extra_specs, expected_extra_spec)
6229
6230 def test_process_numa_paired_threads_empty_extra_spec(self):
6231 numa = {"id": 0, "paired-threads": 3}
6232 extra_specs = {}
6233 expected_extra_spec = {
6234 "hw:cpu_thread_policy": "require",
6235 "hw:cpu_policy": "dedicated",
6236 }
6237 result = self.vimconn.process_numa_paired_threads(numa, extra_specs)
6238 self.assertDictEqual(extra_specs, expected_extra_spec)
6239 self.assertEqual(result, 6)
6240
6241 def test_process_numa_paired_threads_empty_numa(self):
6242 numa = {}
6243 extra_specs = {}
6244 result = self.vimconn.process_numa_paired_threads(numa, extra_specs)
6245 self.assertDictEqual(extra_specs, {})
6246 self.assertEqual(result, None)
6247
6248 def test_process_numa_paired_threads_not_exist(self):
6249 numa = {"vcpu": [2]}
6250 extra_specs = {}
6251 result = self.vimconn.process_numa_paired_threads(numa, extra_specs)
6252 self.assertDictEqual(extra_specs, {})
6253 self.assertEqual(result, None)
6254
6255 def test_process_numa_paired_threads_str_thread_num(self):
6256 numa = {"id": 0, "paired-threads": "3"}
6257 extra_specs = {}
6258 expected_extra_spec = {
6259 "hw:cpu_thread_policy": "require",
6260 "hw:cpu_policy": "dedicated",
6261 }
6262 result = self.vimconn.process_numa_paired_threads(numa, extra_specs)
6263 self.assertDictEqual(extra_specs, expected_extra_spec)
6264 self.assertEqual(result, "33")
6265
6266 def test_process_numa_paired_threads_none_thread_num(self):
6267 numa = {"id": 0, "paired-threads": None}
6268 extra_specs = {}
6269 result = self.vimconn.process_numa_paired_threads(numa, extra_specs)
6270 self.assertDictEqual(extra_specs, {})
6271 self.assertEqual(result, None)
6272
6273 def test_process_numa_cores_empty_extra_spec(self):
6274 numa = {"id": 0, "cores": 1}
6275 extra_specs = {}
6276 expected_extra_spec = {
6277 "hw:cpu_policy": "dedicated",
6278 "hw:cpu_thread_policy": "isolate",
6279 }
6280 result = self.vimconn.process_numa_cores(numa, extra_specs)
6281 self.assertDictEqual(extra_specs, expected_extra_spec)
6282 self.assertEqual(result, 1)
6283
6284 def test_process_numa_cores_not_exist(self):
6285 numa = {"id": 0, "paired-threads": 3}
6286 extra_specs = {}
6287 result = self.vimconn.process_numa_cores(numa, extra_specs)
6288 self.assertDictEqual(extra_specs, {})
6289 self.assertEqual(result, None)
6290
6291 def test_process_numa_cores_empty_numa(self):
6292 numa = {}
6293 extra_specs = expected_extra_spec = {"some-key": "some-val"}
6294 result = self.vimconn.process_numa_cores(numa, extra_specs)
6295 self.assertDictEqual(extra_specs, expected_extra_spec)
6296 self.assertEqual(result, None)
6297
6298 def test_process_numa_cores_none_core_num(self):
6299 numa = {"memory": 1, "cores": None}
6300 extra_specs = {}
6301 result = self.vimconn.process_numa_cores(numa, extra_specs)
6302 self.assertDictEqual(extra_specs, {})
6303 self.assertEqual(result, None)
6304
6305 def test_process_numa_cores_string_core_num(self):
6306 numa = {"id": 0, "cores": "1"}
6307 extra_specs = {"some-key": "some-val"}
6308 expected_extra_spec = {
6309 "hw:cpu_policy": "dedicated",
6310 "hw:cpu_thread_policy": "isolate",
6311 "some-key": "some-val",
6312 }
6313 result = self.vimconn.process_numa_cores(numa, extra_specs)
6314 self.assertDictEqual(extra_specs, expected_extra_spec)
6315 self.assertEqual(result, "1")
6316
6317 def test_process_numa_cores_float_core_num(self):
6318 numa = {"memory": 2, "cores": 10.03}
6319 extra_specs = {"some-key": "some-val"}
6320 expected_extra_spec = {
6321 "hw:cpu_policy": "dedicated",
6322 "hw:cpu_thread_policy": "isolate",
6323 "some-key": "some-val",
6324 }
6325 result = self.vimconn.process_numa_cores(numa, extra_specs)
6326 self.assertDictEqual(extra_specs, expected_extra_spec)
6327 self.assertEqual(result, 10.03)
6328
6329 def test_process_numa_threads_empty_extra_spec_int_thread_num(self):
6330 numa = {"memory": 1, "vcpu": [1, 3], "threads": 3}
6331 extra_specs = {}
6332 expected_extra_spec = {
6333 "hw:cpu_policy": "dedicated",
6334 "hw:cpu_thread_policy": "prefer",
6335 }
6336 result = self.vimconn.process_numa_threads(numa, extra_specs)
6337 self.assertDictEqual(extra_specs, expected_extra_spec)
6338 self.assertEqual(result, 3)
6339
6340 def test_process_numa_threads_empty_numa(self):
6341 numa = {}
6342 extra_specs = {"some-key": "some-val"}
6343 expected_extra_spec = {"some-key": "some-val"}
6344 result = self.vimconn.process_numa_threads(numa, extra_specs)
6345 self.assertDictEqual(extra_specs, expected_extra_spec)
6346 self.assertEqual(result, None)
6347
6348 def test_process_numa_threads_not_exist(self):
6349 numa = {"memory": 1}
6350 extra_specs = expected_extra_spec = {"some-key": "some-val"}
6351 result = self.vimconn.process_numa_threads(numa, extra_specs)
6352 self.assertDictEqual(extra_specs, expected_extra_spec)
6353 self.assertEqual(result, None)
6354
6355 def test_process_numa_threads_str_thread_num(self):
6356 numa = {"vcpu": [1, 3], "threads": "3"}
6357 extra_specs = {}
6358 expected_extra_spec = {
6359 "hw:cpu_policy": "dedicated",
6360 "hw:cpu_thread_policy": "prefer",
6361 }
6362 result = self.vimconn.process_numa_threads(numa, extra_specs)
6363 self.assertDictEqual(extra_specs, expected_extra_spec)
6364 self.assertEqual(result, "3")
6365
6366 def test_process_numa_threads_none_thread_num(self):
6367 numa = {"vcpu": [1, 3], "threads": None}
6368 extra_specs = {}
6369 result = self.vimconn.process_numa_threads(numa, extra_specs)
6370 self.assertDictEqual(extra_specs, {})
6371 self.assertEqual(result, None)
6372
6373 def test_process_numa_threads_float_thread_num(self):
6374 numa = {"memory": 1, "vcpu": [1, 3], "threads": 3.3}
6375 extra_specs = {"some-key": "some-val"}
6376 expected_extra_spec = {
6377 "hw:cpu_policy": "dedicated",
6378 "hw:cpu_thread_policy": "prefer",
6379 "some-key": "some-val",
6380 }
6381 result = self.vimconn.process_numa_threads(numa, extra_specs)
6382 self.assertDictEqual(extra_specs, expected_extra_spec)
6383 self.assertEqual(result, 3.3)
6384
6385 def test_change_the_flavor_name_not_existing_name(self):
6386 """Flavor name does not exist in Openstack flavor list."""
6387 self.flavor1.name = "sample-flavor-3"
6388 self.flavor2.name = "other-flavor-4"
6389 self.vimconn.nova.flavors.list.return_value = [self.flavor1, self.flavor2]
6390 name = "other-flavor-3"
6391 name_suffix = 3
6392 flavor_data = {"name": "other-flavor"}
6393 result = self.vimconn._change_flavor_name(name, name_suffix, flavor_data)
6394 self.assertEqual(result, name)
6395 self.vimconn.nova.flavors.list.assert_called_once()
6396 # Checking whether name_suffix changed or not.
6397 self.assertEqual(name_suffix, 3)
6398
6399 def test_change_the_flavor_name_existing_name(self):
6400 """Flavor name exists in Openstack flavor list."""
6401 self.flavor1.name = "other-flavor-6"
6402 self.flavor2.name = "other-flavor-3"
6403 self.vimconn.nova.flavors.list.return_value = [self.flavor1, self.flavor2]
6404 name = "other-flavor-3"
6405 name_suffix = 5
6406 flavor_data = {"name": "other-flavor"}
6407 expected_result = "other-flavor-7"
6408 result = self.vimconn._change_flavor_name(name, name_suffix, flavor_data)
6409 self.assertEqual(result, expected_result)
6410 # Checking whether name_suffix changed or not.
6411 self.assertEqual(name_suffix, 5)
6412 self.vimconn.nova.flavors.list.assert_called_once()
6413
6414 def test_change_the_flavor_name_flavor_data_does_not_have_name(self):
6415 """Flavor data does not have name."""
6416 self.flavor1.name = "other-flavor-6"
6417 self.flavor2.name = "other-flavor-3"
6418 self.vimconn.nova.flavors.list.return_value = [self.flavor1, self.flavor2]
6419 name = "other-flavor-3"
6420 name_suffix = 5
6421 flavor_data = {}
6422 with self.assertRaises(KeyError):
6423 self.vimconn._change_flavor_name(name, name_suffix, flavor_data)
6424 self.vimconn.nova.flavors.list.assert_called_once()
6425 # Checking whether name_suffix changed or not.
6426 self.assertEqual(name_suffix, 5)
6427
6428 def test_change_the_flavor_name_invalid_name_suffix(self):
6429 """Name suffix is invalid."""
6430 self.flavor1.name = "other-flavor-6"
6431 self.flavor2.name = "other-flavor-3"
6432 self.vimconn.nova.flavors.list.return_value = [self.flavor1, self.flavor2]
6433 name = "other-flavor-3"
6434 name_suffix = "a"
6435 flavor_data = {"name": "other-flavor"}
6436 with self.assertRaises(TypeError):
6437 self.vimconn._change_flavor_name(name, name_suffix, flavor_data)
6438 self.vimconn.nova.flavors.list.assert_called_once()
6439 # Checking whether name_suffix changed or not.
6440 self.assertEqual(name_suffix, "a")
6441
6442 def test_change_the_flavor_name_given_name_is_empty(self):
6443 """Given name is empty string."""
6444 self.flavor1.name = "other-flavor-6"
6445 self.flavor2.name = "other-flavor-3"
6446 self.vimconn.nova.flavors.list.return_value = [self.flavor1, self.flavor2]
6447 name = ""
6448 name_suffix = 3
6449 flavor_data = {"name": "other-flavor"}
6450 result = self.vimconn._change_flavor_name(name, name_suffix, flavor_data)
6451 self.assertEqual(result, "")
6452 self.vimconn.nova.flavors.list.assert_called_once()
6453 # Checking whether name_suffix increased or not.
6454 self.assertEqual(name_suffix, 3)
6455
6456 def test_change_the_flavor_name_given_name_is_none(self):
6457 """Given name is None."""
6458 self.flavor1.name = "other-flavor-6"
6459 self.flavor2.name = "other-flavor-3"
6460 self.vimconn.nova.flavors.list.return_value = [self.flavor1, self.flavor2]
6461 name = None
6462 name_suffix = 6
6463 flavor_data = {"name": "other-flavor"}
6464 result = self.vimconn._change_flavor_name(name, name_suffix, flavor_data)
6465 self.assertEqual(result, None)
6466 self.vimconn.nova.flavors.list.assert_called_once()
6467 # Checking whether name_suffix increased or not.
6468 self.assertEqual(name_suffix, 6)
6469
6470 def test_change_the_flavor_name_empty_nova_flavor_list(self):
6471 """Nova flavor list is empty."""
6472 self.vimconn.nova.flavors.list.return_value = []
6473 name = "other-flavor-3"
6474 name_suffix = 5
6475 flavor_data = {"name": "other-flavor"}
6476 result = self.vimconn._change_flavor_name(name, name_suffix, flavor_data)
6477 self.vimconn.nova.flavors.list.assert_called_once()
6478 self.assertEqual(result, name)
6479 # Checking whether name_suffix increased or not.
6480 self.assertEqual(name_suffix, 5)
6481
6482 @patch.object(
6483 vimconnector,
6484 "_process_numa_parameters_of_flavor",
6485 new_callable=CopyingMock(),
6486 )
6487 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6488 def test_process_extended_config_of_flavor_with_numa_cpu_mem_vif_disk_quota(
6489 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6490 ):
6491 """Process extended config, extended has numas, cpu, mem, vif and disk-io quota."""
6492 numas = [
6493 {"memory": 1, "vcpu": [1, 3], "threads": 3},
6494 {"memory": 2, "vcpu": [2]},
6495 ]
6496 extended = {
6497 "numas": numas,
6498 "cpu-quota": {"limit": 3},
6499 "mem-quota": {"limit": 1},
6500 "vif-quota": {"limit": 10},
6501 "disk-io-quota": {"limit": 50},
6502 "mempage-size": "LARGE",
6503 }
6504 extra_specs = {}
6505 expected_extra_specs = {
6506 "hw:mem_page_size": "large",
6507 }
6508 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6509
6510 self.assertEqual(mock_process_resource_quota.call_count, 4)
6511 mock_process_numa_parameters_of_flavor.assert_called_once_with(numas, {})
6512 self.assertEqual(extra_specs, expected_extra_specs)
6513
6514 @patch.object(
6515 vimconnector,
6516 "_process_numa_parameters_of_flavor",
6517 new_callable=CopyingMock(),
6518 )
6519 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6520 def test_process_extended_config_of_flavor_with_numa_wrong_disk_quota(
6521 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6522 ):
6523 """Process extended config, extended has wrong disk quota key."""
6524 numas = [
6525 {"memory": 1, "threads": 3},
6526 {"memory": 2, "vcpu": [2]},
6527 ]
6528 extended = {
6529 "numas": numas,
6530 "disk-quota": {"limit": 50},
6531 "mempage-size": "PREFER_LARGE",
6532 }
6533 extra_specs = {}
6534 expected_extra_specs = {
6535 "hw:mem_page_size": "any",
6536 }
6537 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6538 mock_process_resource_quota.assert_not_called()
6539 mock_process_numa_parameters_of_flavor.assert_called_once_with(numas, {})
6540 self.assertEqual(extra_specs, expected_extra_specs)
6541
6542 @patch.object(
6543 vimconnector,
6544 "_process_numa_parameters_of_flavor",
6545 new_callable=CopyingMock(),
6546 )
6547 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6548 def test_process_extended_config_of_flavor_without_numa_cpu_mem_vif_disk_quota(
6549 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6550 ):
6551 """Process extended config, extended has cpu, mem, vif and disk-io quota but not numas."""
6552 extended = {
6553 "cpu-quota": {"limit": 3},
6554 "mem-quota": {"limit": 1},
6555 "vif-quota": {"limit": 10},
6556 "disk-io-quota": {"limit": 50},
6557 "mempage-size": "SMALL",
6558 }
6559 extra_specs = {}
6560 expected_extra_specs = {
6561 "hw:mem_page_size": "small",
6562 }
6563 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6564 self.assertEqual(mock_process_resource_quota.call_count, 4)
6565 mock_process_numa_parameters_of_flavor.assert_not_called()
6566 self.assertEqual(extra_specs, expected_extra_specs)
6567
6568 @patch.object(
6569 vimconnector,
6570 "_process_numa_parameters_of_flavor",
6571 new_callable=CopyingMock(),
6572 )
6573 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6574 def test_process_extended_config_of_flavor_with_numa_with_cpu_pinning_mem_policy(
6575 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6576 ):
6577 """Process extended config, extended has cpu, mem quota, cpu-pinning and mem-policy."""
6578 numas = [
6579 {"memory": 1},
6580 {"memory": 2, "vcpu": [2]},
6581 ]
6582 extended = {
6583 "numas": numas,
6584 "cpu-quota": {"limit": 3},
6585 "mem-quota": {"limit": 1},
6586 "mempage-size": "LARGE",
6587 "cpu-pinning-policy": "DEDICATED",
6588 "mem-policy": "STRICT",
6589 }
6590 extra_specs = {}
6591 expected_extra_specs = {
6592 "hw:mem_page_size": "large",
6593 "hw:cpu_policy": "dedicated",
6594 "hw:numa_mempolicy": "strict",
6595 }
6596 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6597 self.assertEqual(mock_process_resource_quota.call_count, 2)
6598 mock_process_numa_parameters_of_flavor.assert_called_once_with(numas, {})
6599 self.assertEqual(extra_specs, expected_extra_specs)
6600
6601 @patch.object(
6602 vimconnector,
6603 "_process_numa_parameters_of_flavor",
6604 new_callable=CopyingMock(),
6605 )
6606 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6607 def test_process_extended_config_of_flavor_without_numa_with_cpu_pinning_mem_policy(
6608 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6609 ):
6610 """Process extended config, extended has cpu, mem quota, cpu-pinning and mem-policy but not numas."""
6611 extended = {
6612 "cpu-quota": {"limit": 3},
6613 "mem-quota": {"limit": 1},
6614 "mempage-size": "LARGE",
6615 "cpu-pinning-policy": "DEDICATED",
6616 "mem-policy": "STRICT",
6617 }
6618 extra_specs = {}
6619 expected_extra_specs = {
6620 "hw:mem_page_size": "large",
6621 "hw:cpu_policy": "dedicated",
6622 "hw:numa_mempolicy": "strict",
6623 }
6624 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6625 self.assertEqual(mock_process_resource_quota.call_count, 2)
6626 mock_process_numa_parameters_of_flavor.assert_not_called()
6627 self.assertEqual(extra_specs, expected_extra_specs)
6628
6629 @patch.object(
6630 vimconnector,
6631 "_process_numa_parameters_of_flavor",
6632 new_callable=CopyingMock(),
6633 )
6634 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6635 def test_process_extended_config_of_flavor_without_numa_with_wrong_mempage_size(
6636 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6637 ):
6638 """Process extended config, extended has wrong mempage-size without numas."""
6639 extended = {
6640 "cpu-quota": {"limit": 3},
6641 "mem-quota": {"limit": 1},
6642 "mempage-size": "SIZE_2GB",
6643 "cpu-pinning-policy": "DEDICATED",
6644 "mem-policy": "STRICT",
6645 }
6646 extra_specs = {}
6647
6648 expected_extra_specs = {
6649 "hw:cpu_policy": "dedicated",
6650 "hw:numa_mempolicy": "strict",
6651 }
6652 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6653 self.assertEqual(mock_process_resource_quota.call_count, 2)
6654 mock_process_numa_parameters_of_flavor.assert_not_called()
6655 self.assertEqual(extra_specs, expected_extra_specs)
6656
6657 @patch.object(
6658 vimconnector,
6659 "_process_numa_parameters_of_flavor",
6660 new_callable=CopyingMock(),
6661 )
6662 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6663 def test_process_extended_config_of_flavor_with_numa_with_wrong_mempage_size(
6664 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6665 ):
6666 """Process extended config, extended has wrong mempage-size with numas."""
6667 numas = [
6668 {"memory": 1},
6669 {"memory": 2, "vcpu": [2]},
6670 ]
6671 extended = {
6672 "numas": numas,
6673 "cpu-quota": {"limit": 3},
6674 "mem-quota": {"limit": 1},
6675 "mempage-size": "SIZE_2GB",
6676 "cpu-pinning-policy": "DEDICATED",
6677 "mem-policy": "STRICT",
6678 }
6679 extra_specs = {}
6680 expected_extra_specs = {
6681 "hw:cpu_policy": "dedicated",
6682 "hw:numa_mempolicy": "strict",
6683 }
6684 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6685 self.assertEqual(mock_process_resource_quota.call_count, 2)
6686 mock_process_numa_parameters_of_flavor.assert_called_once_with(numas, {})
6687 self.assertEqual(extra_specs, expected_extra_specs)
6688
6689 @patch.object(
6690 vimconnector,
6691 "_process_numa_parameters_of_flavor",
6692 new_callable=CopyingMock(),
6693 )
6694 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6695 def test_process_extended_config_of_flavor_none_vcpus(
6696 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6697 ):
6698 """Process extended config, extended has cpu, mem quota, cpu-pinning and mem-policy, vcpus is None."""
6699 numas = [
6700 {"memory": 1},
6701 {"memory": 2, "vcpu": [2]},
6702 ]
6703 extended = {
6704 "numas": numas,
6705 "cpu-quota": {"limit": 3},
6706 "mem-quota": {"limit": 1},
6707 "mempage-size": "SIZE_2GB",
6708 "cpu-pinning-policy": "DEDICATED",
6709 "mem-policy": "STRICT",
6710 }
6711 extra_specs = {}
6712 expected_extra_specs = {
6713 "hw:cpu_policy": "dedicated",
6714 "hw:numa_mempolicy": "strict",
6715 }
6716 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6717 self.assertEqual(mock_process_resource_quota.call_count, 2)
6718 mock_process_numa_parameters_of_flavor.assert_called_once_with(numas, {})
6719 self.assertEqual(extra_specs, expected_extra_specs)
6720
6721 @patch.object(
6722 vimconnector,
6723 "_process_numa_parameters_of_flavor",
6724 new_callable=CopyingMock(),
6725 )
6726 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6727 def test_process_extended_config_of_flavor_none_vcpus_without_numas(
6728 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6729 ):
6730 """Process extended config, extended has cpu, mem quota, cpu-pinning and mem-policy, vcpus is None."""
6731 extended = {
6732 "cpu-quota": {"limit": 3},
6733 "mem-quota": {"limit": 1},
6734 "mempage-size": "SIZE_2GB",
6735 "cpu-pinning-policy": "DEDICATED",
6736 "mem-policy": "STRICT",
6737 }
6738 extra_specs = {"some-key": "some-val"}
6739 expected_extra_specs = {
6740 "hw:cpu_policy": "dedicated",
6741 "hw:numa_mempolicy": "strict",
6742 "some-key": "some-val",
6743 }
6744 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6745 self.assertEqual(mock_process_resource_quota.call_count, 2)
6746 mock_process_numa_parameters_of_flavor.assert_not_called()
6747 self.assertEqual(extra_specs, expected_extra_specs)
6748
6749 @patch.object(
6750 vimconnector,
6751 "_process_numa_parameters_of_flavor",
6752 new_callable=CopyingMock(),
6753 )
6754 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6755 def test_process_extended_config_of_flavor_wrong_cpu_pinning_mem_policy_empty_vcpus(
6756 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6757 ):
6758 """Process extended config, extended has wrong cpu-pinning and mem-policy keys."""
6759 numas = [
6760 {"memory": 1},
6761 {"memory": 2, "vcpu": [2]},
6762 ]
6763 extended = {
6764 "numas": numas,
6765 "cpu-quota": {"limit": 3},
6766 "mem-quota": {"limit": 1},
6767 "mempage-size": "SIZE_2GB",
6768 "cpu-pinning-pol": "DEDICATED",
6769 "mem-pol": "STRICT",
6770 }
6771 extra_specs = {}
6772 expected_extra_specs = {}
6773 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6774 self.assertEqual(mock_process_resource_quota.call_count, 2)
6775 mock_process_numa_parameters_of_flavor.assert_called_once_with(
6776 numas, extra_specs
6777 )
6778 self.assertEqual(extra_specs, expected_extra_specs)
6779
6780 @patch.object(
6781 vimconnector,
6782 "_process_numa_parameters_of_flavor",
6783 new_callable=CopyingMock(),
6784 )
6785 @patch.object(vimconnector, "process_resource_quota", new_callable=CopyingMock())
6786 def test_process_extended_config_of_flavor_empty_extended(
6787 self, mock_process_resource_quota, mock_process_numa_parameters_of_flavor
6788 ):
6789 """Process extended config, extended is empty."""
6790 extended = {}
6791 extra_specs = {}
6792 self.vimconn._process_extended_config_of_flavor(extended, extra_specs)
6793 check_if_assert_not_called(
6794 [mock_process_resource_quota, mock_process_numa_parameters_of_flavor]
6795 )
6796 self.assertEqual(extra_specs, {})
6797
6798 def test_get_flavor_details_empty_flavor_data(self):
6799 flavor_data = {}
6800 expected_result = (64, 1, {}, None)
6801 result = self.vimconn._get_flavor_details(flavor_data)
6802 self.assertEqual(result, expected_result)
6803
6804 def test_get_flavor_details_flavor_data_has_ram_vcpus_extended(self):
6805 flavor_data = {
6806 "ram": 32,
6807 "vcpus": 3,
6808 "extended": {
6809 "some-key": "some-val",
6810 },
6811 }
6812 expected_result = (32, 3, {}, {"some-key": "some-val"})
6813 result = self.vimconn._get_flavor_details(flavor_data)
6814 self.assertEqual(result, expected_result)
6815
6816 def test_get_flavor_details_flavor_data_is_none(self):
6817 flavor_data = None
6818 with self.assertRaises(AttributeError):
6819 self.vimconn._get_flavor_details(flavor_data)
6820
6821 def test_get_flavor_details_flavor_data_has_only_extended(self):
6822 flavor_data = {
6823 "extended": {
6824 "some-key": "some-val",
6825 }
6826 }
6827 expected_result = (64, 1, {}, {"some-key": "some-val"})
6828 result = self.vimconn._get_flavor_details(flavor_data)
6829 self.assertEqual(result, expected_result)
6830
6831 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
6832 @patch.object(
6833 vimconnector,
6834 "_process_extended_config_of_flavor",
6835 new_callable=CopyingMock(),
6836 )
6837 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
6838 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
6839 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
6840 def test_new_flavor_with_extended_with_extra_specs(
6841 self,
6842 mock_format_exception,
6843 mock_reload_connection,
6844 mock_change_flavor_name,
6845 mock_extended_config_of_flavor,
6846 mock_get_flavor_details,
6847 ):
6848 """Create new flavor with using extended parameters and extra specs."""
6849 name_suffix = 0
6850 vcpus = 8
6851 mock_change_flavor_name.return_value = name1
6852 mock_get_flavor_details.return_value = (
6853 3,
6854 vcpus,
6855 {"some-key": "some-value"},
6856 extended,
6857 )
6858 expected_result = self.new_flavor.id
6859 result = self.vimconn.new_flavor(flavor_data)
6860 self.assertEqual(result, expected_result)
6861 mock_reload_connection.assert_called_once()
6862 self.new_flavor.set_keys.assert_called_once()
6863 mock_get_flavor_details.assert_called_once_with(flavor_data)
6864 mock_change_flavor_name.assert_called_once_with(name1, name_suffix, flavor_data)
6865 mock_extended_config_of_flavor.assert_called_once_with(
6866 extended, {"some-key": "some-value"}
6867 )
6868 self.vimconn.nova.flavors.create.assert_called_once_with(
6869 name=name1, ram=3, vcpus=8, disk=50, ephemeral=0, swap=0, is_public=True
6870 )
6871 mock_format_exception.assert_not_called()
6872
6873 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
6874 @patch.object(
6875 vimconnector,
6876 "_process_extended_config_of_flavor",
6877 new_callable=CopyingMock(),
6878 )
6879 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
6880 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
6881 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
6882 def test_new_flavor_with_extended_without_extra_specs(
6883 self,
6884 mock_format_exception,
6885 mock_reload_connection,
6886 mock_change_flavor_name,
6887 mock_extended_config_of_flavor,
6888 mock_get_flavor_details,
6889 ):
6890 """Create new flavor with using extended parameters without extra specs."""
6891 name_suffix = 0
6892 vcpus = 8
6893 mock_change_flavor_name.return_value = name1
6894 mock_get_flavor_details.return_value = (3, vcpus, {}, extended)
6895 expected_result = self.new_flavor.id
6896 result = self.vimconn.new_flavor(flavor_data)
6897 self.assertEqual(result, expected_result)
6898 mock_reload_connection.assert_called_once()
6899 mock_get_flavor_details.assert_called_once_with(flavor_data)
6900 mock_change_flavor_name.assert_called_once_with(name1, name_suffix, flavor_data)
6901 mock_extended_config_of_flavor.assert_called_once_with(extended, {})
6902 self.vimconn.nova.flavors.create.assert_called_once_with(
6903 name=name1, ram=3, vcpus=vcpus, disk=50, ephemeral=0, swap=0, is_public=True
6904 )
6905 check_if_assert_not_called([self.new_flavor.set_keys, mock_format_exception])
6906
6907 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
6908 @patch.object(
6909 vimconnector,
6910 "_process_extended_config_of_flavor",
6911 new_callable=CopyingMock(),
6912 )
6913 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
6914 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
6915 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
6916 def test_new_flavor_change_name_if_used_false_with_extended(
6917 self,
6918 mock_format_exception,
6919 mock_reload_connection,
6920 mock_change_flavor_name,
6921 mock_extended_config_of_flavor,
6922 mock_get_flavor_details,
6923 ):
6924 """Create new flavor, change_name_if_used_false, there is extended."""
6925 vcpus = 8
6926 mock_get_flavor_details.return_value = (3, vcpus, {}, extended)
6927 expected_result = self.new_flavor.id
6928 result = self.vimconn.new_flavor(flavor_data, False)
6929 self.assertEqual(result, expected_result)
6930 mock_reload_connection.assert_called_once()
6931 self.assertEqual(mock_get_flavor_details.call_count, 1)
6932 mock_extended_config_of_flavor.assert_called_once_with(extended, {})
6933 self.vimconn.nova.flavors.create.assert_called_once_with(
6934 name=name1, ram=3, vcpus=8, disk=50, ephemeral=0, swap=0, is_public=True
6935 )
6936 check_if_assert_not_called(
6937 [mock_change_flavor_name, mock_format_exception, self.new_flavor.set_keys]
6938 )
6939
6940 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
6941 @patch.object(
6942 vimconnector,
6943 "_process_extended_config_of_flavor",
6944 new_callable=CopyingMock(),
6945 )
6946 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
6947 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
6948 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
6949 def test_new_flavor_change_name_if_used_true_without_extended(
6950 self,
6951 mock_format_exception,
6952 mock_reload_connection,
6953 mock_change_flavor_name,
6954 mock_extended_config_of_flavor,
6955 mock_get_flavor_details,
6956 ):
6957 """Create new flavor without extended parameters."""
6958 name_suffix = 0
6959 mock_change_flavor_name.return_value = name1
6960 expected_result = self.new_flavor.id
6961 mock_get_flavor_details.return_value = (3, 8, {}, None)
6962 result = self.vimconn.new_flavor(flavor_data2)
6963 self.assertEqual(result, expected_result)
6964 mock_reload_connection.assert_called_once()
6965 mock_change_flavor_name.assert_called_once_with(
6966 name1, name_suffix, flavor_data2
6967 )
6968 self.assertEqual(mock_get_flavor_details.call_count, 1)
6969 self.vimconn.nova.flavors.create.assert_called_once_with(
6970 name=name1, ram=3, vcpus=8, disk=50, ephemeral=0, swap=0, is_public=True
6971 )
6972 check_if_assert_not_called(
6973 [
6974 self.new_flavor.set_keys,
6975 mock_extended_config_of_flavor,
6976 mock_format_exception,
6977 ]
6978 )
6979
6980 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
6981 @patch.object(
6982 vimconnector,
6983 "_process_extended_config_of_flavor",
6984 new_callable=CopyingMock(),
6985 )
6986 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
6987 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
6988 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
6989 def test_new_flavor_reload_connection_exception(
6990 self,
6991 mock_format_exception,
6992 mock_reload_connection,
6993 mock_change_flavor_name,
6994 mock_extended_config_of_flavor,
6995 mock_get_flavor_details,
6996 ):
6997 """Create new flavor, reload connection exception occurred."""
6998 error_msg = "Can not connect to client APIs."
6999 error = nvExceptions.ClientException(error_msg)
7000 mock_change_flavor_name.return_value = name1
7001 mock_reload_connection.side_effect = error
7002 with self.assertRaises(Exception) as err:
7003 self.vimconn.new_flavor(flavor_data2)
7004 self.assertEqual(str(err.exception), "Can not connect to client APIs.")
7005 self.assertEqual(mock_reload_connection.call_count, 1)
7006 call_mock_format_exception = mock_format_exception.call_args
7007 self.assertEqual(
7008 str(call_mock_format_exception[0][0]), str(ClientException(error_msg))
7009 )
7010 check_if_assert_not_called(
7011 [
7012 mock_change_flavor_name,
7013 mock_get_flavor_details,
7014 mock_extended_config_of_flavor,
7015 self.vimconn.nova.flavors.create,
7016 ]
7017 )
7018
7019 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
7020 @patch.object(
7021 vimconnector,
7022 "_process_extended_config_of_flavor",
7023 new_callable=CopyingMock(autospec=True),
7024 )
7025 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
7026 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
7027 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
7028 def test_new_flavor_flavor_data_without_name(
7029 self,
7030 mock_format_exception,
7031 mock_reload_connection,
7032 mock_change_flavor_name,
7033 mock_extended_config_of_flavor,
7034 mock_get_flavor_details,
7035 ):
7036 """Create new flavor, flavor data does not have name."""
7037 flavor_data3 = {
7038 "ram": 3,
7039 "vcpus": 8,
7040 "disk": 50,
7041 }
7042 error_msg = "name"
7043 self.vimconn.new_flavor(flavor_data3)
7044 mock_format_exception.assert_called_once()
7045 call_mock_format_exception = mock_format_exception.call_args
7046 self.assertEqual(
7047 str(call_mock_format_exception[0][0]), str(KeyError(error_msg))
7048 )
7049 check_if_assert_not_called(
7050 [
7051 mock_reload_connection,
7052 mock_change_flavor_name,
7053 mock_get_flavor_details,
7054 mock_extended_config_of_flavor,
7055 self.vimconn.nova.flavors.create,
7056 ]
7057 )
7058
7059 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
7060 @patch.object(
7061 vimconnector,
7062 "_process_extended_config_of_flavor",
7063 new_callable=CopyingMock(),
7064 )
7065 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
7066 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
7067 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
7068 def test_new_flavor_change_flavor_name_has_extended_conflict_exception_recovered_in_retry(
7069 self,
7070 mock_format_exception,
7071 mock_reload_connection,
7072 mock_change_flavor_name,
7073 mock_extended_config_of_flavor,
7074 mock_get_flavor_details,
7075 ):
7076 """Create new flavor, nvExceptions.Conflict occurred and recovered, there is extended config."""
7077 name_suffix = 0
7078 error_msg = "Conflict has occurred while creating flavor name."
7079 error2 = nvExceptions.Conflict(error_msg)
7080 mock_change_flavor_name.side_effect = [error2, "sample-flavor-3"]
7081 expected_result = self.new_flavor.id
7082 mock_get_flavor_details.return_value = (3, 8, {}, extended)
7083 result = self.vimconn.new_flavor(flavor_data2)
7084 self.assertEqual(result, expected_result)
7085 self.assertEqual(mock_reload_connection.call_count, 2)
7086 mock_change_flavor_name.assert_called_with(name1, name_suffix, flavor_data2)
7087 self.assertEqual(mock_change_flavor_name.call_count, 2)
7088 self.assertEqual(mock_get_flavor_details.call_count, 1)
7089 self.assertEqual(mock_extended_config_of_flavor.call_count, 1)
7090 self.vimconn.nova.flavors.create.assert_called_once_with(
7091 name="sample-flavor-3",
7092 ram=3,
7093 vcpus=8,
7094 disk=50,
7095 ephemeral=0,
7096 swap=0,
7097 is_public=True,
7098 )
7099 check_if_assert_not_called([self.new_flavor.set_keys, mock_format_exception])
7100
7101 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
7102 @patch.object(
7103 vimconnector,
7104 "_process_extended_config_of_flavor",
7105 new_callable=CopyingMock(),
7106 )
7107 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
7108 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
7109 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
7110 def test_new_flavor_change_flavor_name_without_extended_conflict_exception_recovered_in_retry(
7111 self,
7112 mock_format_exception,
7113 mock_reload_connection,
7114 mock_change_flavor_name,
7115 mock_extended_config_of_flavor,
7116 mock_get_flavor_details,
7117 ):
7118 """Create new flavor, nvExceptions.Conflict occurred and recovered, there is not extended config."""
7119 name_suffix = 0
7120 error2 = nvExceptions.Conflict(
7121 "Conflict has occurred while creating flavor name."
7122 )
7123 mock_change_flavor_name.side_effect = [error2, "sample-flavor-3"]
7124 expected_result = self.new_flavor.id
7125 mock_get_flavor_details.return_value = (3, 8, {}, None)
7126 result = self.vimconn.new_flavor(flavor_data2)
7127 self.assertEqual(result, expected_result)
7128 self.assertEqual(mock_reload_connection.call_count, 2)
7129 mock_change_flavor_name.assert_called_with(name1, name_suffix, flavor_data2)
7130 self.assertEqual(mock_change_flavor_name.call_count, 2)
7131 self.assertEqual(mock_get_flavor_details.call_count, 1)
7132 self.vimconn.nova.flavors.create.assert_called_once_with(
7133 name="sample-flavor-3",
7134 ram=3,
7135 vcpus=8,
7136 disk=50,
7137 ephemeral=0,
7138 swap=0,
7139 is_public=True,
7140 )
7141 check_if_assert_not_called(
7142 [
7143 self.new_flavor.set_keys,
7144 mock_extended_config_of_flavor,
7145 mock_format_exception,
7146 ]
7147 )
7148
7149 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
7150 @patch.object(
7151 vimconnector,
7152 "_process_extended_config_of_flavor",
7153 new_callable=CopyingMock(),
7154 )
7155 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
7156 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
7157 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
7158 def test_new_flavor_change_flavor_name_conflict_exception_change_name_if_used_false(
7159 self,
7160 mock_format_exception,
7161 mock_reload_connection,
7162 mock_change_flavor_name,
7163 mock_extended_config_of_flavor,
7164 mock_get_flavor_details,
7165 ):
7166 """Create new flavor, nvExceptions.Conflict occurred,
7167 change_name_if_used is false."""
7168 change_name_if_used = False
7169 error_msg = "Conflict has occurred while creating flavor name."
7170 error2 = nvExceptions.Conflict(error_msg)
7171 mock_get_flavor_details.return_value = (4, 8, {}, None)
7172 self.vimconn.nova.flavors.create.side_effect = error2
7173 with self.assertRaises(Exception) as err:
7174 self.vimconn.new_flavor(flavor_data2, change_name_if_used)
7175 self.assertEqual(str(err.exception), error_msg)
7176 self.assertEqual(type(err.exception), nvExceptions.Conflict)
7177 self.vimconn.nova.flavors.create.assert_called_with(
7178 name="sample-flavor",
7179 ram=4,
7180 vcpus=8,
7181 disk=50,
7182 ephemeral=0,
7183 swap=0,
7184 is_public=True,
7185 )
7186 self.assertEqual(mock_get_flavor_details.call_count, 3)
7187 self.assertEqual(self.vimconn.nova.flavors.create.call_count, 3)
7188 self.assertEqual(mock_reload_connection.call_count, 3)
7189 check_if_assert_not_called(
7190 [mock_change_flavor_name, mock_extended_config_of_flavor]
7191 )
7192 _call_mock_format_exception = mock_format_exception.call_args
7193 self.assertEqual(
7194 str(_call_mock_format_exception[0][0]), str(Conflict(error_msg))
7195 )
7196 self.assertEqual(mock_format_exception.call_count, 3)
7197
7198 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
7199 @patch.object(
7200 vimconnector,
7201 "_process_extended_config_of_flavor",
7202 new_callable=CopyingMock(),
7203 )
7204 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
7205 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
7206 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
7207 def test_new_flavor_client_exception_occurred_change_name_if_used_true(
7208 self,
7209 mock_format_exception,
7210 mock_reload_connection,
7211 mock_change_flavor_name,
7212 mock_extended_config_of_flavor,
7213 mock_get_flavor_details,
7214 ):
7215 """Create new flavor, nvExceptions.ClientException occurred,
7216 change_name_if_used is true."""
7217 error_msg = "Connection failed."
7218 error2 = nvExceptions.ClientException(error_msg)
7219 mock_change_flavor_name.side_effect = [
7220 "sample-flavor-3",
7221 "sample-flavor-4",
7222 "sample-flavor-5",
7223 ]
7224 mock_get_flavor_details.return_value = (3, 8, {}, None)
7225 self.vimconn.nova.flavors.create.side_effect = error2
7226 with self.assertRaises(Exception) as err:
7227 self.vimconn.new_flavor(flavor_data2)
7228 self.assertEqual(
7229 str(err.exception), "Conflict has occurred while creating flavor name."
7230 )
7231 self.assertEqual(type(err.exception), nvExceptions.Conflict)
7232 self.assertEqual(self.vimconn.nova.flavors.create.call_count, 1)
7233 _call_mock_nova_create_flavor = self.vimconn.nova.flavors.create.call_args_list
7234 self.assertEqual(
7235 _call_mock_nova_create_flavor[0][1],
7236 (
7237 {
7238 "name": "sample-flavor-3",
7239 "ram": 3,
7240 "vcpus": 8,
7241 "disk": 50,
7242 "ephemeral": 0,
7243 "swap": 0,
7244 "is_public": True,
7245 }
7246 ),
7247 )
7248
7249 self.assertEqual(mock_reload_connection.call_count, 1)
7250 self.assertEqual(mock_get_flavor_details.call_count, 1)
7251 _call_mock_change_flavor = mock_change_flavor_name.call_args_list
7252 self.assertEqual(
7253 _call_mock_change_flavor[0][0],
7254 (
7255 "sample-flavor",
7256 0,
7257 {"name": "sample-flavor", "ram": 3, "vcpus": 8, "disk": 50},
7258 ),
7259 )
7260 self.assertEqual(mock_change_flavor_name.call_count, 1)
7261 mock_extended_config_of_flavor.assert_not_called()
7262 call_mock_format_exception = mock_format_exception.call_args
7263 self.assertEqual(
7264 str(call_mock_format_exception[0][0]), str(ClientException(error_msg))
7265 )
7266 self.assertEqual(mock_format_exception.call_count, 1)
7267
7268 @patch.object(vimconnector, "_get_flavor_details", new_callable=CopyingMock())
7269 @patch.object(
7270 vimconnector,
7271 "_process_extended_config_of_flavor",
7272 new_callable=CopyingMock(),
7273 )
7274 @patch.object(vimconnector, "_change_flavor_name", new_callable=CopyingMock())
7275 @patch.object(vimconnector, "_reload_connection", new_callable=CopyingMock())
7276 @patch.object(vimconnector, "_format_exception", new_callable=CopyingMock())
7277 def test_new_flavor_change_flavor_name_conflict_exception_occurred_change_name_if_used_true(
7278 self,
7279 mock_format_exception,
7280 mock_reload_connection,
7281 mock_change_flavor_name,
7282 mock_extended_config_of_flavor,
7283 mock_get_flavor_details,
7284 ):
7285 """Create new flavor, nvExceptions.Conflict occurred,
7286 change_name_if_used is true."""
7287 error_msg = "Conflict has occurred while creating flavor name."
7288 error2 = nvExceptions.Conflict(error_msg)
7289 mock_change_flavor_name.side_effect = [
7290 "sample-flavor-3",
7291 "sample-flavor-4",
7292 "sample-flavor-5",
7293 ]
7294 mock_get_flavor_details.return_value = (3, 8, {}, None)
7295 self.vimconn.nova.flavors.create.side_effect = error2
7296 with self.assertRaises(Exception) as err:
7297 self.vimconn.new_flavor(flavor_data2)
7298 self.assertEqual(str(err.exception), error_msg)
7299 self.assertEqual(type(err.exception), nvExceptions.Conflict)
7300 self.assertEqual(self.vimconn.nova.flavors.create.call_count, 3)
7301 _call_mock_nova_create_flavor = self.vimconn.nova.flavors.create.call_args_list
7302 self.assertEqual(
7303 _call_mock_nova_create_flavor[0][1],
7304 (
7305 {
7306 "name": "sample-flavor-3",
7307 "ram": 3,
7308 "vcpus": 8,
7309 "disk": 50,
7310 "ephemeral": 0,
7311 "swap": 0,
7312 "is_public": True,
7313 }
7314 ),
7315 )
7316 self.assertEqual(
7317 _call_mock_nova_create_flavor[1][1],
7318 (
7319 {
7320 "name": "sample-flavor-4",
7321 "ram": 3,
7322 "vcpus": 8,
7323 "disk": 50,
7324 "ephemeral": 0,
7325 "swap": 0,
7326 "is_public": True,
7327 }
7328 ),
7329 )
7330 self.assertEqual(
7331 _call_mock_nova_create_flavor[2][1],
7332 (
7333 {
7334 "name": "sample-flavor-5",
7335 "ram": 3,
7336 "vcpus": 8,
7337 "disk": 50,
7338 "ephemeral": 0,
7339 "swap": 0,
7340 "is_public": True,
7341 }
7342 ),
7343 )
7344 self.assertEqual(mock_reload_connection.call_count, 3)
7345 _call_mock_change_flavor = mock_change_flavor_name.call_args_list
7346 self.assertEqual(
7347 _call_mock_change_flavor[0][0],
7348 (
7349 "sample-flavor",
7350 0,
7351 {"name": "sample-flavor", "ram": 3, "vcpus": 8, "disk": 50},
7352 ),
7353 )
7354 self.assertEqual(
7355 _call_mock_change_flavor[1][0],
7356 (
7357 "sample-flavor-3",
7358 0,
7359 {"name": "sample-flavor", "ram": 3, "vcpus": 8, "disk": 50},
7360 ),
7361 )
7362 self.assertEqual(
7363 _call_mock_change_flavor[2][0],
7364 (
7365 "sample-flavor-4",
7366 0,
7367 {"name": "sample-flavor", "ram": 3, "vcpus": 8, "disk": 50},
7368 ),
7369 )
7370 self.assertEqual(mock_change_flavor_name.call_count, 3)
7371 mock_extended_config_of_flavor.assert_not_called()
7372 call_mock_format_exception = mock_format_exception.call_args
7373 self.assertEqual(
7374 str(call_mock_format_exception[0][0]), str(Conflict(error_msg))
7375 )
7376 self.assertEqual(mock_format_exception.call_count, 1)
7377
7378 def test_process_process_vio_numa_nodes_without_numa_with_extra_spec(self):
7379 numa_nodes = 0
7380 extra_specs = {"hw:numa_nodes": "0"}
7381 expected_extra_spec = {
7382 "vmware:latency_sensitivity_level": "high",
7383 "hw:numa_nodes": "0",
7384 }
7385 self.vimconn.process_vio_numa_nodes(numa_nodes, extra_specs)
7386 self.assertDictEqual(extra_specs, expected_extra_spec)
7387
7388 def test_process_process_vio_numa_nodes_list_type_numa_nodes_empty_extra_spec(self):
7389 numa_nodes = [7, 9, 4]
7390 extra_specs = {}
7391 expected_extra_spec = {
7392 "vmware:latency_sensitivity_level": "high",
7393 }
7394 self.vimconn.process_vio_numa_nodes(numa_nodes, extra_specs)
7395 self.assertDictEqual(extra_specs, expected_extra_spec)
7396
7397 def test_process_process_vio_numa_nodes_with_numa_with_extra_spec(self):
7398 numa_nodes = 5
7399 extra_specs = {"hw:numa_nodes": "5"}
7400 expected_extra_spec = {
7401 "vmware:latency_sensitivity_level": "high",
7402 "hw:numa_nodes": "5",
7403 }
7404 self.vimconn.process_vio_numa_nodes(numa_nodes, extra_specs)
7405 self.assertDictEqual(extra_specs, expected_extra_spec)
7406
7407 def test_process_process_vio_numa_nodes_none_numa_nodes(self):
7408 numa_nodes = None
7409 extra_specs = {"hw:numa_nodes": "None"}
7410 expected_extra_spec = {
7411 "vmware:latency_sensitivity_level": "high",
7412 "hw:numa_nodes": "None",
7413 }
7414 self.vimconn.process_vio_numa_nodes(numa_nodes, extra_specs)
7415 self.assertDictEqual(extra_specs, expected_extra_spec)
7416
7417 def test_process_process_vio_numa_nodes_invalid_type_extra_specs(self):
7418 numa_nodes = 5
7419 extra_specs = []
7420 with self.assertRaises(TypeError):
7421 self.vimconn.process_vio_numa_nodes(numa_nodes, extra_specs)
7422
7423
7424 if __name__ == "__main__":
7425 unittest.main()