Removed floating IP list from OpenStackVmInstance.
[snaps.git] / snaps / openstack / tests / create_instance_tests.py
1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 #                    and others.  All rights reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 import logging
16 import re
17 import shutil
18 import time
19 import unittest
20 import uuid
21
22 import os
23 from neutronclient.common.exceptions import InvalidIpForSubnetClient
24
25 from snaps import file_utils
26 from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings
27 from snaps.openstack.create_image import OpenStackImage, ImageSettings
28 from snaps.openstack.create_instance import (
29     VmInstanceSettings, OpenStackVmInstance, FloatingIpSettings,
30     VmInstanceSettingsError, FloatingIpSettingsError)
31 from snaps.openstack.create_keypairs import OpenStackKeypair, KeypairSettings
32 from snaps.openstack.create_network import OpenStackNetwork, PortSettings
33 from snaps.openstack.create_router import OpenStackRouter
34 from snaps.openstack.create_security_group import (
35     SecurityGroupSettings, OpenStackSecurityGroup, SecurityGroupRuleSettings,
36     Direction, Protocol)
37 from snaps.openstack.tests import openstack_tests, validation_utils
38 from snaps.openstack.tests.os_source_file_test import (
39     OSIntegrationTestCase, OSComponentTestCase)
40 from snaps.openstack.utils import nova_utils
41
42 __author__ = 'spisarski'
43
44 VM_BOOT_TIMEOUT = 600
45
46 logger = logging.getLogger('create_instance_tests')
47
48
49 class VmInstanceSettingsUnitTests(unittest.TestCase):
50     """
51     Tests the construction of the VmInstanceSettings class
52     """
53
54     def test_no_params(self):
55         with self.assertRaises(VmInstanceSettingsError):
56             VmInstanceSettings()
57
58     def test_empty_config(self):
59         with self.assertRaises(VmInstanceSettingsError):
60             VmInstanceSettings(config=dict())
61
62     def test_name_only(self):
63         with self.assertRaises(VmInstanceSettingsError):
64             VmInstanceSettings(name='foo')
65
66     def test_config_with_name_only(self):
67         with self.assertRaises(VmInstanceSettingsError):
68             VmInstanceSettings(config={'name': 'foo'})
69
70     def test_name_flavor_only(self):
71         with self.assertRaises(VmInstanceSettingsError):
72             VmInstanceSettings(name='foo', flavor='bar')
73
74     def test_config_with_name_flavor_only(self):
75         with self.assertRaises(VmInstanceSettingsError):
76             VmInstanceSettings(config={'name': 'foo', 'flavor': 'bar'})
77
78     def test_name_flavor_port_only(self):
79         port_settings = PortSettings(name='foo-port', network_name='bar-net')
80         settings = VmInstanceSettings(name='foo', flavor='bar',
81                                       port_settings=[port_settings])
82         self.assertEqual('foo', settings.name)
83         self.assertEqual('bar', settings.flavor)
84         self.assertEqual(1, len(settings.port_settings))
85         self.assertEqual('foo-port', settings.port_settings[0].name)
86         self.assertEqual('bar-net', settings.port_settings[0].network_name)
87         self.assertEqual(0, len(settings.security_group_names))
88         self.assertEqual(0, len(settings.floating_ip_settings))
89         self.assertIsNone(settings.sudo_user)
90         self.assertEqual(900, settings.vm_boot_timeout)
91         self.assertEqual(300, settings.vm_delete_timeout)
92         self.assertEqual(180, settings.ssh_connect_timeout)
93         self.assertIsNone(settings.availability_zone)
94
95     def test_config_with_name_flavor_port_only(self):
96         port_settings = PortSettings(name='foo-port', network_name='bar-net')
97         settings = VmInstanceSettings(
98             **{'name': 'foo', 'flavor': 'bar', 'ports': [port_settings]})
99         self.assertEqual('foo', settings.name)
100         self.assertEqual('bar', settings.flavor)
101         self.assertEqual(1, len(settings.port_settings))
102         self.assertEqual('foo-port', settings.port_settings[0].name)
103         self.assertEqual('bar-net', settings.port_settings[0].network_name)
104         self.assertEqual(0, len(settings.security_group_names))
105         self.assertEqual(0, len(settings.floating_ip_settings))
106         self.assertIsNone(settings.sudo_user)
107         self.assertEqual(900, settings.vm_boot_timeout)
108         self.assertEqual(300, settings.vm_delete_timeout)
109         self.assertEqual(180, settings.ssh_connect_timeout)
110         self.assertIsNone(settings.availability_zone)
111
112     def test_all(self):
113         port_settings = PortSettings(name='foo-port', network_name='bar-net')
114         fip_settings = FloatingIpSettings(name='foo-fip', port_name='bar-port',
115                                           router_name='foo-bar-router')
116
117         settings = VmInstanceSettings(name='foo', flavor='bar',
118                                       port_settings=[port_settings],
119                                       security_group_names=['sec_grp_1'],
120                                       floating_ip_settings=[fip_settings],
121                                       sudo_user='joe', vm_boot_timeout=999,
122                                       vm_delete_timeout=333,
123                                       ssh_connect_timeout=111,
124                                       availability_zone='server name')
125         self.assertEqual('foo', settings.name)
126         self.assertEqual('bar', settings.flavor)
127         self.assertEqual(1, len(settings.port_settings))
128         self.assertEqual('foo-port', settings.port_settings[0].name)
129         self.assertEqual('bar-net', settings.port_settings[0].network_name)
130         self.assertEqual(1, len(settings.security_group_names))
131         self.assertEqual('sec_grp_1', settings.security_group_names[0])
132         self.assertEqual(1, len(settings.floating_ip_settings))
133         self.assertEqual('foo-fip', settings.floating_ip_settings[0].name)
134         self.assertEqual('bar-port',
135                          settings.floating_ip_settings[0].port_name)
136         self.assertEqual('foo-bar-router',
137                          settings.floating_ip_settings[0].router_name)
138         self.assertEqual('joe', settings.sudo_user)
139         self.assertEqual(999, settings.vm_boot_timeout)
140         self.assertEqual(333, settings.vm_delete_timeout)
141         self.assertEqual(111, settings.ssh_connect_timeout)
142         self.assertEqual('server name', settings.availability_zone)
143
144     def test_config_all(self):
145         port_settings = PortSettings(name='foo-port', network_name='bar-net')
146         fip_settings = FloatingIpSettings(name='foo-fip', port_name='bar-port',
147                                           router_name='foo-bar-router')
148
149         settings = VmInstanceSettings(
150             **{'name': 'foo', 'flavor': 'bar', 'ports': [port_settings],
151                'security_group_names': ['sec_grp_1'],
152                'floating_ips': [fip_settings], 'sudo_user': 'joe',
153                'vm_boot_timeout': 999, 'vm_delete_timeout': 333,
154                'ssh_connect_timeout': 111, 'availability_zone': 'server name'})
155         self.assertEqual('foo', settings.name)
156         self.assertEqual('bar', settings.flavor)
157         self.assertEqual(1, len(settings.port_settings))
158         self.assertEqual('foo-port', settings.port_settings[0].name)
159         self.assertEqual('bar-net', settings.port_settings[0].network_name)
160         self.assertEqual(1, len(settings.security_group_names))
161         self.assertEqual(1, len(settings.floating_ip_settings))
162         self.assertEqual('foo-fip', settings.floating_ip_settings[0].name)
163         self.assertEqual('bar-port',
164                          settings.floating_ip_settings[0].port_name)
165         self.assertEqual('foo-bar-router',
166                          settings.floating_ip_settings[0].router_name)
167         self.assertEqual('joe', settings.sudo_user)
168         self.assertEqual(999, settings.vm_boot_timeout)
169         self.assertEqual(333, settings.vm_delete_timeout)
170         self.assertEqual(111, settings.ssh_connect_timeout)
171         self.assertEqual('server name', settings.availability_zone)
172
173
174 class FloatingIpSettingsUnitTests(unittest.TestCase):
175     """
176     Tests the construction of the FloatingIpSettings class
177     """
178
179     def test_no_params(self):
180         with self.assertRaises(FloatingIpSettingsError):
181             FloatingIpSettings()
182
183     def test_empty_config(self):
184         with self.assertRaises(FloatingIpSettingsError):
185             FloatingIpSettings(**dict())
186
187     def test_name_only(self):
188         with self.assertRaises(FloatingIpSettingsError):
189             FloatingIpSettings(name='foo')
190
191     def test_config_with_name_only(self):
192         with self.assertRaises(FloatingIpSettingsError):
193             FloatingIpSettings(**{'name': 'foo'})
194
195     def test_name_port_only(self):
196         with self.assertRaises(FloatingIpSettingsError):
197             FloatingIpSettings(name='foo', port_name='bar')
198
199     def test_config_with_name_port_only(self):
200         with self.assertRaises(FloatingIpSettingsError):
201             FloatingIpSettings(**{'name': 'foo', 'port_name': 'bar'})
202
203     def test_name_router_only(self):
204         with self.assertRaises(FloatingIpSettingsError):
205             FloatingIpSettings(name='foo', router_name='bar')
206
207     def test_config_with_name_router_only(self):
208         with self.assertRaises(FloatingIpSettingsError):
209             FloatingIpSettings(**{'name': 'foo', 'router_name': 'bar'})
210
211     def test_name_port_router_only(self):
212         settings = FloatingIpSettings(name='foo', port_name='foo-port',
213                                       router_name='bar-router')
214         self.assertEqual('foo', settings.name)
215         self.assertEqual('foo-port', settings.port_name)
216         self.assertEqual('bar-router', settings.router_name)
217         self.assertIsNone(settings.subnet_name)
218         self.assertTrue(settings.provisioning)
219
220     def test_config_with_name_port_router_only(self):
221         settings = FloatingIpSettings(
222             **{'name': 'foo', 'port_name': 'foo-port',
223                'router_name': 'bar-router'})
224         self.assertEqual('foo', settings.name)
225         self.assertEqual('foo-port', settings.port_name)
226         self.assertEqual('bar-router', settings.router_name)
227         self.assertIsNone(settings.subnet_name)
228         self.assertTrue(settings.provisioning)
229
230     def test_all(self):
231         settings = FloatingIpSettings(name='foo', port_name='foo-port',
232                                       router_name='bar-router',
233                                       subnet_name='bar-subnet',
234                                       provisioning=False)
235         self.assertEqual('foo', settings.name)
236         self.assertEqual('foo-port', settings.port_name)
237         self.assertEqual('bar-router', settings.router_name)
238         self.assertEqual('bar-subnet', settings.subnet_name)
239         self.assertFalse(settings.provisioning)
240
241     def test_config_all(self):
242         settings = FloatingIpSettings(
243             **{'name': 'foo', 'port_name': 'foo-port',
244                'router_name': 'bar-router', 'subnet_name': 'bar-subnet',
245                'provisioning': False})
246         self.assertEqual('foo', settings.name)
247         self.assertEqual('foo-port', settings.port_name)
248         self.assertEqual('bar-router', settings.router_name)
249         self.assertEqual('bar-subnet', settings.subnet_name)
250         self.assertFalse(settings.provisioning)
251
252
253 class SimpleHealthCheck(OSIntegrationTestCase):
254     """
255     Test for the CreateInstance class with a single NIC/Port with Floating IPs
256     """
257
258     def setUp(self):
259         """
260         Instantiates the CreateImage object that is responsible for downloading
261         and creating an OS image file
262         within OpenStack
263         """
264         super(self.__class__, self).__start__()
265
266         self.nova = nova_utils.nova_client(self.os_creds)
267         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
268         self.vm_inst_name = guid + '-inst'
269         self.port_1_name = guid + 'port-1'
270
271         # Initialize for tearDown()
272         self.image_creator = None
273         self.network_creator = None
274         self.flavor_creator = None
275         self.inst_creator = None
276
277         self.priv_net_config = openstack_tests.get_priv_net_config(
278             net_name=guid + '-priv-net', subnet_name=guid + '-priv-subnet')
279         self.port_settings = PortSettings(
280             name=self.port_1_name,
281             network_name=self.priv_net_config.network_settings.name)
282
283         # Create Image
284         # Set the default image settings, then set any custom parameters sent
285         # from the app
286         os_image_settings = openstack_tests.cirros_image_settings(
287             name=guid + '-image', image_metadata=self.image_metadata)
288
289         try:
290             self.image_creator = OpenStackImage(self.os_creds,
291                                                 os_image_settings)
292             self.image_creator.create()
293
294             # Create Network
295             self.network_creator = OpenStackNetwork(
296                 self.os_creds, self.priv_net_config.network_settings)
297             self.network_creator.create()
298
299             # Create Flavor
300             self.flavor_creator = OpenStackFlavor(
301                 self.admin_os_creds,
302                 FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
303                                vcpus=1, metadata=self.flavor_metadata))
304             self.flavor_creator.create()
305         except Exception as e:
306             self.tearDown()
307             raise e
308
309     def tearDown(self):
310         """
311         Cleans the created object
312         """
313         if self.inst_creator:
314             try:
315                 self.inst_creator.clean()
316             except Exception as e:
317                 logger.error(
318                     'Unexpected exception cleaning VM instance with message'
319                     ' - %s', e)
320
321         if self.network_creator:
322             try:
323                 self.network_creator.clean()
324             except Exception as e:
325                 logger.error(
326                     'Unexpected exception cleaning network with message - %s',
327                     e)
328
329         if self.flavor_creator:
330             try:
331                 self.flavor_creator.clean()
332             except Exception as e:
333                 logger.error(
334                     'Unexpected exception cleaning flavor with message - %s',
335                     e)
336
337         if self.image_creator and not self.image_creator.image_settings.exists:
338             try:
339                 self.image_creator.clean()
340             except Exception as e:
341                 logger.error(
342                     'Unexpected exception cleaning image with message - %s',
343                     e)
344
345         super(self.__class__, self).__clean__()
346
347     def test_check_vm_ip_dhcp(self):
348         """
349         Tests the creation of an OpenStack instance with a single port and
350         ensures that it's assigned IP address is the actual.
351         """
352         instance_settings = VmInstanceSettings(
353             name=self.vm_inst_name,
354             flavor=self.flavor_creator.flavor_settings.name,
355             port_settings=[self.port_settings])
356
357         self.inst_creator = OpenStackVmInstance(
358             self.os_creds, instance_settings,
359             self.image_creator.image_settings)
360         self.inst_creator.create()
361
362         ip = self.inst_creator.get_port_ip(self.port_settings.name)
363         self.assertIsNotNone(ip)
364
365         self.assertTrue(self.inst_creator.vm_active(block=True))
366
367         self.assertTrue(check_dhcp_lease(self.inst_creator, ip))
368
369
370 class CreateInstanceSimpleTests(OSIntegrationTestCase):
371     """
372     Simple instance creation tests without any other objects
373     """
374
375     def setUp(self):
376         """
377         Instantiates the CreateImage object that is responsible for downloading
378         and creating an OS image file
379         within OpenStack
380         """
381         super(self.__class__, self).__start__()
382
383         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
384         self.vm_inst_name = guid + '-inst'
385         self.nova = nova_utils.nova_client(self.os_creds)
386         os_image_settings = openstack_tests.cirros_image_settings(
387             name=guid + '-image', image_metadata=self.image_metadata)
388
389         net_config = openstack_tests.get_priv_net_config(
390             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
391             router_name=guid + '-pub-router', external_net=self.ext_net_name)
392
393         # Initialize for tearDown()
394         self.image_creator = None
395         self.flavor_creator = None
396
397         self.network_creator = None
398         self.inst_creator = None
399
400         try:
401             # Create Image
402             self.image_creator = OpenStackImage(self.os_creds,
403                                                 os_image_settings)
404             self.image_creator.create()
405
406             # Create Flavor
407             self.flavor_creator = OpenStackFlavor(
408                 self.admin_os_creds,
409                 FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
410                                vcpus=2, metadata=self.flavor_metadata))
411             self.flavor_creator.create()
412
413             # Create Network
414             self.network_creator = OpenStackNetwork(
415                 self.os_creds, net_config.network_settings)
416             self.network_creator.create()
417
418             self.port_settings = PortSettings(
419                 name=guid + '-port',
420                 network_name=net_config.network_settings.name)
421
422         except Exception as e:
423             self.tearDown()
424             raise e
425
426     def tearDown(self):
427         """
428         Cleans the created object
429         """
430         if self.inst_creator:
431             try:
432                 self.inst_creator.clean()
433             except Exception as e:
434                 logger.error(
435                     'Unexpected exception cleaning VM instance with message '
436                     '- %s', e)
437
438         if self.flavor_creator:
439             try:
440                 self.flavor_creator.clean()
441             except Exception as e:
442                 logger.error(
443                     'Unexpected exception cleaning flavor with message - %s',
444                     e)
445
446         if self.network_creator:
447             try:
448                 self.network_creator.clean()
449             except Exception as e:
450                 logger.error(
451                     'Unexpected exception cleaning network with message - %s',
452                     e)
453
454         if self.image_creator and not self.image_creator.image_settings.exists:
455             try:
456                 self.image_creator.clean()
457             except Exception as e:
458                 logger.error(
459                     'Unexpected exception cleaning image with message - %s', e)
460
461         super(self.__class__, self).__clean__()
462
463     def test_create_delete_instance(self):
464         """
465         Tests the creation of an OpenStack instance with a single port with a
466         static IP without a Floating IP.
467         """
468         instance_settings = VmInstanceSettings(
469             name=self.vm_inst_name,
470             flavor=self.flavor_creator.flavor_settings.name,
471             port_settings=[self.port_settings])
472
473         self.inst_creator = OpenStackVmInstance(
474             self.os_creds, instance_settings,
475             self.image_creator.image_settings)
476
477         vm_inst = self.inst_creator.create()
478         self.assertEqual(1, len(
479             nova_utils.get_servers_by_name(self.nova, instance_settings.name)))
480
481         # Delete instance
482         nova_utils.delete_vm_instance(self.nova, vm_inst)
483
484         self.assertTrue(self.inst_creator.vm_deleted(block=True))
485         self.assertEqual(0, len(
486             nova_utils.get_servers_by_name(self.nova, instance_settings.name)))
487
488         # Exception should not be thrown
489         self.inst_creator.clean()
490
491
492 class CreateInstanceSingleNetworkTests(OSIntegrationTestCase):
493     """
494     Test for the CreateInstance class with a single NIC/Port with Floating IPs
495     """
496
497     def setUp(self):
498         """
499         Instantiates the CreateImage object that is responsible for downloading
500         and creating an OS image file within OpenStack
501         """
502         super(self.__class__, self).__start__()
503
504         self.nova = nova_utils.nova_client(self.os_creds)
505         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
506         self.keypair_priv_filepath = 'tmp/' + guid
507         self.keypair_pub_filepath = self.keypair_priv_filepath + '.pub'
508         self.keypair_name = guid + '-kp'
509         self.vm_inst_name = guid + '-inst'
510         self.port_1_name = guid + 'port-1'
511         self.port_2_name = guid + 'port-2'
512         self.floating_ip_name = guid + 'fip1'
513
514         # Initialize for tearDown()
515         self.image_creator = None
516         self.network_creator = None
517         self.router_creator = None
518         self.flavor_creator = None
519         self.keypair_creator = None
520         self.sec_grp_creator = None
521         self.inst_creators = list()
522
523         self.pub_net_config = openstack_tests.get_pub_net_config(
524             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
525             router_name=guid + '-pub-router', external_net=self.ext_net_name)
526         os_image_settings = openstack_tests.cirros_image_settings(
527             name=guid + '-image', image_metadata=self.image_metadata)
528         try:
529             # Create Image
530             self.image_creator = OpenStackImage(self.os_creds,
531                                                 os_image_settings)
532             self.image_creator.create()
533
534             # Create Network
535             self.network_creator = OpenStackNetwork(
536                 self.os_creds, self.pub_net_config.network_settings)
537             self.network_creator.create()
538
539             # Create Router
540             self.router_creator = OpenStackRouter(
541                 self.os_creds, self.pub_net_config.router_settings)
542             self.router_creator.create()
543
544             # Create Flavor
545             self.flavor_creator = OpenStackFlavor(
546                 self.admin_os_creds,
547                 FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
548                                vcpus=2, metadata=self.flavor_metadata))
549             self.flavor_creator.create()
550
551             self.keypair_creator = OpenStackKeypair(
552                 self.os_creds, KeypairSettings(
553                     name=self.keypair_name,
554                     public_filepath=self.keypair_pub_filepath,
555                     private_filepath=self.keypair_priv_filepath))
556             self.keypair_creator.create()
557
558             sec_grp_name = guid + '-sec-grp'
559             rule1 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
560                                               direction=Direction.ingress,
561                                               protocol=Protocol.icmp)
562             rule2 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
563                                               direction=Direction.ingress,
564                                               protocol=Protocol.tcp,
565                                               port_range_min=22,
566                                               port_range_max=22)
567             self.sec_grp_creator = OpenStackSecurityGroup(
568                 self.os_creds,
569                 SecurityGroupSettings(name=sec_grp_name,
570                                       rule_settings=[rule1, rule2]))
571             self.sec_grp_creator.create()
572         except Exception as e:
573             self.tearDown()
574             raise e
575
576     def tearDown(self):
577         """
578         Cleans the created object
579         """
580         for inst_creator in self.inst_creators:
581             try:
582                 inst_creator.clean()
583             except Exception as e:
584                 logger.error(
585                     'Unexpected exception cleaning VM instance with message '
586                     '- %s', e)
587
588         if self.keypair_creator:
589             try:
590                 self.keypair_creator.clean()
591             except Exception as e:
592                 logger.error(
593                     'Unexpected exception cleaning keypair with message - %s',
594                     e)
595
596         if os.path.isfile(self.keypair_pub_filepath):
597             os.remove(self.keypair_pub_filepath)
598
599         if os.path.isfile(self.keypair_priv_filepath):
600             os.remove(self.keypair_priv_filepath)
601
602         if self.flavor_creator:
603             try:
604                 self.flavor_creator.clean()
605             except Exception as e:
606                 logger.error(
607                     'Unexpected exception cleaning flavor with message - %s',
608                     e)
609
610         if self.sec_grp_creator:
611             try:
612                 self.sec_grp_creator.clean()
613             except Exception as e:
614                 logger.error(
615                     'Unexpected exception cleaning security group with message'
616                     ' - %s', e)
617
618         if self.router_creator:
619             try:
620                 self.router_creator.clean()
621             except Exception as e:
622                 logger.error(
623                     'Unexpected exception cleaning router with message - %s',
624                     e)
625
626         if self.network_creator:
627             try:
628                 self.network_creator.clean()
629             except Exception as e:
630                 logger.error(
631                     'Unexpected exception cleaning network with message - %s',
632                     e)
633
634         if self.image_creator and not self.image_creator.image_settings.exists:
635             try:
636                 self.image_creator.clean()
637             except Exception as e:
638                 logger.error(
639                     'Unexpected exception cleaning image with message - %s', e)
640
641         super(self.__class__, self).__clean__()
642
643     def test_single_port_static(self):
644         """
645         Tests the creation of an OpenStack instance with a single port with a
646         static IP without a Floating IP.
647         """
648         ip_1 = '10.55.1.100'
649         sub_settings = self.pub_net_config.network_settings.subnet_settings
650         port_settings = PortSettings(
651             name=self.port_1_name,
652             network_name=self.pub_net_config.network_settings.name,
653             ip_addrs=[
654                 {'subnet_name': sub_settings[0].name, 'ip': ip_1}])
655
656         instance_settings = VmInstanceSettings(
657             name=self.vm_inst_name,
658             flavor=self.flavor_creator.flavor_settings.name,
659             port_settings=[port_settings],
660             floating_ip_settings=[FloatingIpSettings(
661                 name=self.floating_ip_name, port_name=self.port_1_name,
662                 router_name=self.pub_net_config.router_settings.name)])
663
664         inst_creator = OpenStackVmInstance(
665             self.os_creds, instance_settings,
666             self.image_creator.image_settings,
667             keypair_settings=self.keypair_creator.keypair_settings)
668         self.inst_creators.append(inst_creator)
669         vm_inst = inst_creator.create()
670
671         self.assertEqual(ip_1, inst_creator.get_port_ip(self.port_1_name))
672         self.assertTrue(inst_creator.vm_active(block=True))
673         self.assertEqual(vm_inst, inst_creator.get_vm_inst())
674
675     def test_ssh_client_fip_before_active(self):
676         """
677         Tests the ability to access a VM via SSH and a floating IP when it has
678         been assigned prior to being active.
679         """
680         port_settings = PortSettings(
681             name=self.port_1_name,
682             network_name=self.pub_net_config.network_settings.name)
683
684         instance_settings = VmInstanceSettings(
685             name=self.vm_inst_name,
686             flavor=self.flavor_creator.flavor_settings.name,
687             port_settings=[port_settings],
688             floating_ip_settings=[FloatingIpSettings(
689                 name=self.floating_ip_name, port_name=self.port_1_name,
690                 router_name=self.pub_net_config.router_settings.name)])
691
692         inst_creator = OpenStackVmInstance(
693             self.os_creds, instance_settings,
694             self.image_creator.image_settings,
695             keypair_settings=self.keypair_creator.keypair_settings)
696         self.inst_creators.append(inst_creator)
697         vm_inst = inst_creator.create()
698         self.assertIsNotNone(vm_inst)
699
700         self.assertTrue(inst_creator.vm_active(block=True))
701
702         ip = inst_creator.get_port_ip(port_settings.name)
703         self.assertTrue(check_dhcp_lease(inst_creator, ip))
704
705         inst_creator.add_security_group(
706             self.sec_grp_creator.get_security_group())
707         self.assertEqual(vm_inst, inst_creator.get_vm_inst())
708
709         self.assertTrue(validate_ssh_client(inst_creator))
710
711     def test_ssh_client_fip_after_active(self):
712         """
713         Tests the ability to access a VM via SSH and a floating IP when it has
714         been assigned prior to being active.
715         """
716         port_settings = PortSettings(
717             name=self.port_1_name,
718             network_name=self.pub_net_config.network_settings.name)
719
720         instance_settings = VmInstanceSettings(
721             name=self.vm_inst_name,
722             flavor=self.flavor_creator.flavor_settings.name,
723             port_settings=[port_settings],
724             floating_ip_settings=[FloatingIpSettings(
725                 name=self.floating_ip_name, port_name=self.port_1_name,
726                 router_name=self.pub_net_config.router_settings.name)])
727
728         inst_creator = OpenStackVmInstance(
729             self.os_creds, instance_settings,
730             self.image_creator.image_settings,
731             keypair_settings=self.keypair_creator.keypair_settings)
732         self.inst_creators.append(inst_creator)
733
734         # block=True will force the create() method to block until the
735         vm_inst = inst_creator.create(block=True)
736         self.assertIsNotNone(vm_inst)
737
738         self.assertTrue(inst_creator.vm_active(block=True))
739
740         ip = inst_creator.get_port_ip(port_settings.name)
741         self.assertTrue(check_dhcp_lease(inst_creator, ip))
742
743         inst_creator.add_security_group(
744             self.sec_grp_creator.get_security_group())
745         self.assertEqual(vm_inst, inst_creator.get_vm_inst())
746
747         self.assertTrue(validate_ssh_client(inst_creator))
748
749     def test_ssh_client_fip_second_creator(self):
750         """
751         Tests the ability to access a VM via SSH and a floating IP via a
752         creator that is identical to the original creator.
753         """
754         port_settings = PortSettings(
755             name=self.port_1_name,
756             network_name=self.pub_net_config.network_settings.name)
757
758         instance_settings = VmInstanceSettings(
759             name=self.vm_inst_name,
760             flavor=self.flavor_creator.flavor_settings.name,
761             port_settings=[port_settings],
762             floating_ip_settings=[FloatingIpSettings(
763                 name=self.floating_ip_name, port_name=self.port_1_name,
764                 router_name=self.pub_net_config.router_settings.name)])
765
766         inst_creator = OpenStackVmInstance(
767             self.os_creds, instance_settings,
768             self.image_creator.image_settings,
769             keypair_settings=self.keypair_creator.keypair_settings)
770         self.inst_creators.append(inst_creator)
771
772         # block=True will force the create() method to block until the
773         vm_inst = inst_creator.create(block=True)
774         self.assertIsNotNone(vm_inst)
775
776         self.assertTrue(inst_creator.vm_active(block=True))
777
778         ip = inst_creator.get_port_ip(port_settings.name)
779         self.assertTrue(check_dhcp_lease(inst_creator, ip))
780
781         inst_creator.add_security_group(
782             self.sec_grp_creator.get_security_group())
783         self.assertEqual(vm_inst, inst_creator.get_vm_inst())
784
785         self.assertTrue(validate_ssh_client(inst_creator))
786
787         inst_creator2 = OpenStackVmInstance(
788             self.os_creds, instance_settings,
789             self.image_creator.image_settings,
790             keypair_settings=self.keypair_creator.keypair_settings)
791         inst_creator2.create()
792         self.assertTrue(validate_ssh_client(inst_creator2))
793
794
795 class CreateInstancePortManipulationTests(OSIntegrationTestCase):
796     """
797     Test for the CreateInstance class with a single NIC/Port where mac and IP
798     values are manually set
799     """
800
801     def setUp(self):
802         """
803         Instantiates the CreateImage object that is responsible for downloading
804         and creating an OS image file within OpenStack
805         """
806         super(self.__class__, self).__start__()
807
808         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
809         self.vm_inst_name = guid + '-inst'
810         self.port_1_name = guid + 'port-1'
811         self.port_2_name = guid + 'port-2'
812         self.floating_ip_name = guid + 'fip1'
813
814         # Initialize for tearDown()
815         self.image_creator = None
816         self.network_creator = None
817         self.flavor_creator = None
818         self.inst_creator = None
819
820         self.net_config = openstack_tests.get_priv_net_config(
821             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
822             router_name=guid + '-pub-router', external_net=self.ext_net_name)
823         os_image_settings = openstack_tests.cirros_image_settings(
824             name=guid + '-image', image_metadata=self.image_metadata)
825
826         try:
827             # Create Image
828             self.image_creator = OpenStackImage(self.os_creds,
829                                                 os_image_settings)
830             self.image_creator.create()
831
832             # Create Network
833             self.network_creator = OpenStackNetwork(
834                 self.os_creds, self.net_config.network_settings)
835             self.network_creator.create()
836
837             # Create Flavor
838             self.flavor_creator = OpenStackFlavor(
839                 self.admin_os_creds,
840                 FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
841                                vcpus=2, metadata=self.flavor_metadata))
842             self.flavor_creator.create()
843         except Exception as e:
844             self.tearDown()
845             raise e
846
847     def tearDown(self):
848         """
849         Cleans the created object
850         """
851         if self.inst_creator:
852             try:
853                 self.inst_creator.clean()
854             except Exception as e:
855                 logger.error(
856                     'Unexpected exception cleaning VM instance with message '
857                     '- %s', e)
858
859         if self.flavor_creator:
860             try:
861                 self.flavor_creator.clean()
862             except Exception as e:
863                 logger.error(
864                     'Unexpected exception cleaning flavor with message - %s',
865                     e)
866
867         if self.network_creator:
868             try:
869                 self.network_creator.clean()
870             except Exception as e:
871                 logger.error(
872                     'Unexpected exception cleaning network with message - %s',
873                     e)
874
875         if self.image_creator and not self.image_creator.image_settings.exists:
876             try:
877                 self.image_creator.clean()
878             except Exception as e:
879                 logger.error(
880                     'Unexpected exception cleaning image with message - %s', e)
881
882         super(self.__class__, self).__clean__()
883
884     def test_set_custom_valid_ip_one_subnet(self):
885         """
886         Tests the creation of an OpenStack instance with a single port with a
887         static IP on a network with one subnet.
888         """
889         ip = '10.55.0.101'
890         sub_settings = self.net_config.network_settings.subnet_settings
891         port_settings = PortSettings(
892             name=self.port_1_name,
893             network_name=self.net_config.network_settings.name,
894             ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}])
895
896         instance_settings = VmInstanceSettings(
897             name=self.vm_inst_name,
898             flavor=self.flavor_creator.flavor_settings.name,
899             port_settings=[port_settings])
900
901         self.inst_creator = OpenStackVmInstance(
902             self.os_creds, instance_settings,
903             self.image_creator.image_settings)
904         self.inst_creator.create(block=True)
905
906         self.assertEqual(ip, self.inst_creator.get_port_ip(
907             self.port_1_name,
908             subnet_name=self.net_config.network_settings.subnet_settings[
909                 0].name))
910
911     def test_set_custom_invalid_ip_one_subnet(self):
912         """
913         Tests the creation of an OpenStack instance with a single port with a
914         static IP on a network with one subnet.
915         """
916         ip = '10.66.0.101'
917         sub_settings = self.net_config.network_settings.subnet_settings
918         port_settings = PortSettings(
919             name=self.port_1_name,
920             network_name=self.net_config.network_settings.name,
921             ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}])
922
923         instance_settings = VmInstanceSettings(
924             name=self.vm_inst_name,
925             flavor=self.flavor_creator.flavor_settings.name,
926             port_settings=[port_settings])
927
928         self.inst_creator = OpenStackVmInstance(
929             self.os_creds, instance_settings,
930             self.image_creator.image_settings)
931
932         with self.assertRaises(InvalidIpForSubnetClient):
933             self.inst_creator.create()
934
935     def test_set_custom_valid_mac(self):
936         """
937         Tests the creation of an OpenStack instance with a single port where
938         the MAC address is assigned.
939         """
940         mac_addr = '0a:1b:2c:3d:4e:5f'
941         port_settings = PortSettings(
942             name=self.port_1_name,
943             network_name=self.net_config.network_settings.name,
944             mac_address=mac_addr)
945
946         instance_settings = VmInstanceSettings(
947             name=self.vm_inst_name,
948             flavor=self.flavor_creator.flavor_settings.name,
949             port_settings=[port_settings])
950
951         self.inst_creator = OpenStackVmInstance(
952             self.os_creds, instance_settings,
953             self.image_creator.image_settings)
954         self.inst_creator.create(block=True)
955
956         self.assertEqual(mac_addr,
957                          self.inst_creator.get_port_mac(self.port_1_name))
958
959     def test_set_custom_invalid_mac(self):
960         """
961         Tests the creation of an OpenStack instance with a single port where an
962         invalid MAC address value is being
963         assigned. This should raise an Exception
964         """
965         port_settings = PortSettings(
966             name=self.port_1_name,
967             network_name=self.net_config.network_settings.name,
968             mac_address='foo')
969
970         instance_settings = VmInstanceSettings(
971             name=self.vm_inst_name,
972             flavor=self.flavor_creator.flavor_settings.name,
973             port_settings=[port_settings])
974
975         self.inst_creator = OpenStackVmInstance(
976             self.os_creds, instance_settings,
977             self.image_creator.image_settings)
978
979         with self.assertRaises(Exception):
980             self.inst_creator.create()
981
982     def test_set_custom_mac_and_ip(self):
983         """
984         Tests the creation of an OpenStack instance with a single port where
985         the IP and MAC address is assigned.
986         """
987         ip = '10.55.0.101'
988         mac_addr = '0a:1b:2c:3d:4e:5f'
989         sub_settings = self.net_config.network_settings.subnet_settings
990         port_settings = PortSettings(
991             name=self.port_1_name,
992             network_name=self.net_config.network_settings.name,
993             mac_address=mac_addr,
994             ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}])
995
996         instance_settings = VmInstanceSettings(
997             name=self.vm_inst_name,
998             flavor=self.flavor_creator.flavor_settings.name,
999             port_settings=[port_settings])
1000
1001         self.inst_creator = OpenStackVmInstance(
1002             self.os_creds, instance_settings,
1003             self.image_creator.image_settings)
1004         self.inst_creator.create(block=True)
1005
1006         self.assertEqual(ip, self.inst_creator.get_port_ip(
1007             self.port_1_name,
1008             subnet_name=self.net_config.network_settings.subnet_settings[
1009                 0].name))
1010         self.assertEqual(mac_addr,
1011                          self.inst_creator.get_port_mac(self.port_1_name))
1012
1013     def test_set_allowed_address_pairs(self):
1014         """
1015         Tests the creation of an OpenStack instance with a single port where
1016         max_allowed_address_pair is set.
1017         """
1018         ip = '10.55.0.101'
1019         mac_addr = '0a:1b:2c:3d:4e:5f'
1020         pair = {'ip_address': ip, 'mac_address': mac_addr}
1021         port_settings = PortSettings(
1022             name=self.port_1_name,
1023             network_name=self.net_config.network_settings.name,
1024             allowed_address_pairs=[pair])
1025
1026         instance_settings = VmInstanceSettings(
1027             name=self.vm_inst_name,
1028             flavor=self.flavor_creator.flavor_settings.name,
1029             port_settings=[port_settings])
1030
1031         self.inst_creator = OpenStackVmInstance(
1032             self.os_creds, instance_settings,
1033             self.image_creator.image_settings)
1034         self.inst_creator.create(block=True)
1035
1036         port = self.inst_creator.get_port_by_name(port_settings.name)
1037         self.assertIsNotNone(port)
1038         self.assertIsNotNone(port.allowed_address_pairs)
1039         self.assertEqual(1, len(port.allowed_address_pairs))
1040         validation_utils.objects_equivalent(pair,
1041                                             port.allowed_address_pairs[0])
1042
1043     def test_set_allowed_address_pairs_bad_mac(self):
1044         """
1045         Tests the creation of an OpenStack instance with a single port where
1046         max_allowed_address_pair is set with an invalid MAC address.
1047         """
1048         ip = '10.55.0.101'
1049         mac_addr = 'foo'
1050         pair = {'ip_address': ip, 'mac_address': mac_addr}
1051         pairs = set()
1052         pairs.add((ip, mac_addr))
1053         port_settings = PortSettings(
1054             name=self.port_1_name,
1055             network_name=self.net_config.network_settings.name,
1056             allowed_address_pairs=[pair])
1057
1058         instance_settings = VmInstanceSettings(
1059             name=self.vm_inst_name,
1060             flavor=self.flavor_creator.flavor_settings.name,
1061             port_settings=[port_settings])
1062
1063         self.inst_creator = OpenStackVmInstance(
1064             self.os_creds, instance_settings,
1065             self.image_creator.image_settings)
1066         with self.assertRaises(Exception):
1067             self.inst_creator.create()
1068
1069     def test_set_allowed_address_pairs_bad_ip(self):
1070         """
1071         Tests the creation of an OpenStack instance with a single port where
1072         max_allowed_address_pair is set with an invalid MAC address.
1073         """
1074         ip = 'foo'
1075         mac_addr = '0a:1b:2c:3d:4e:5f'
1076         pair = {'ip_address': ip, 'mac_address': mac_addr}
1077         pairs = set()
1078         pairs.add((ip, mac_addr))
1079         port_settings = PortSettings(
1080             name=self.port_1_name,
1081             network_name=self.net_config.network_settings.name,
1082             allowed_address_pairs=[pair])
1083
1084         instance_settings = VmInstanceSettings(
1085             name=self.vm_inst_name,
1086             flavor=self.flavor_creator.flavor_settings.name,
1087             port_settings=[port_settings])
1088
1089         self.inst_creator = OpenStackVmInstance(
1090             self.os_creds, instance_settings,
1091             self.image_creator.image_settings)
1092         with self.assertRaises(Exception):
1093             self.inst_creator.create()
1094
1095
1096 class CreateInstanceOnComputeHost(OSIntegrationTestCase):
1097     """
1098     Test for the CreateInstance where one VM is deployed to each compute node
1099     """
1100
1101     def setUp(self):
1102         """
1103         Instantiates the CreateImage object that is responsible for downloading
1104         and creating an OS image file within OpenStack
1105         """
1106         super(self.__class__, self).__start__()
1107
1108         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1109         self.vm_inst_name = guid + '-inst'
1110         self.port_base_name = guid + 'port'
1111
1112         # Initialize for tearDown()
1113         self.image_creator = None
1114         self.flavor_creator = None
1115         self.network_creator = None
1116         self.inst_creators = list()
1117
1118         self.priv_net_config = openstack_tests.get_priv_net_config(
1119             net_name=guid + '-priv-net', subnet_name=guid + '-priv-subnet')
1120
1121         os_image_settings = openstack_tests.cirros_image_settings(
1122             name=guid + '-image', image_metadata=self.image_metadata)
1123
1124         try:
1125             # Create Network
1126             self.network_creator = OpenStackNetwork(
1127                 self.admin_os_creds, self.priv_net_config.network_settings)
1128             self.network_creator.create()
1129
1130             # Create Flavor
1131             self.flavor_creator = OpenStackFlavor(
1132                 self.admin_os_creds,
1133                 FlavorSettings(name=guid + '-flavor-name', ram=512, disk=1,
1134                                vcpus=1, metadata=self.flavor_metadata))
1135             self.flavor_creator.create()
1136
1137             # Create Image
1138             self.image_creator = OpenStackImage(self.os_creds,
1139                                                 os_image_settings)
1140             self.image_creator.create()
1141
1142         except Exception as e:
1143             self.tearDown()
1144             raise e
1145
1146     def tearDown(self):
1147         """
1148         Cleans the created object
1149         """
1150         for inst_creator in self.inst_creators:
1151             try:
1152                 inst_creator.clean()
1153             except Exception as e:
1154                 logger.error(
1155                     'Unexpected exception cleaning VM instance with message '
1156                     '- %s', e)
1157
1158         if self.flavor_creator:
1159             try:
1160                 self.flavor_creator.clean()
1161             except Exception as e:
1162                 logger.error(
1163                     'Unexpected exception cleaning flavor with message - %s',
1164                     e)
1165
1166         if self.network_creator:
1167             try:
1168                 self.network_creator.clean()
1169             except Exception as e:
1170                 logger.error(
1171                     'Unexpected exception cleaning network with message - %s',
1172                     e)
1173
1174         if self.image_creator and not self.image_creator.image_settings.exists:
1175             try:
1176                 self.image_creator.clean()
1177             except Exception as e:
1178                 logger.error(
1179                     'Unexpected exception cleaning image with message - %s', e)
1180
1181         super(self.__class__, self).__clean__()
1182
1183     def test_deploy_vm_to_each_compute_node(self):
1184         """
1185         Tests the creation of OpenStack VM instances to each compute node.
1186         """
1187         from snaps.openstack.utils import nova_utils
1188         nova = nova_utils.nova_client(self.admin_os_creds)
1189         zone_hosts = nova_utils.get_availability_zone_hosts(nova)
1190
1191         # Create Instance on each server/zone
1192         ctr = 0
1193         for zone in zone_hosts:
1194             inst_name = self.vm_inst_name + '-' + zone
1195             ctr += 1
1196             port_settings = PortSettings(
1197                 name=self.port_base_name + '-' + str(ctr),
1198                 network_name=self.priv_net_config.network_settings.name)
1199
1200             instance_settings = VmInstanceSettings(
1201                 name=inst_name,
1202                 flavor=self.flavor_creator.flavor_settings.name,
1203                 availability_zone=zone,
1204                 port_settings=[port_settings])
1205             inst_creator = OpenStackVmInstance(
1206                 self.admin_os_creds, instance_settings,
1207                 self.image_creator.image_settings)
1208             self.inst_creators.append(inst_creator)
1209             inst_creator.create()
1210
1211         # Validate instances to ensure they've been deployed to the correct
1212         # server
1213         index = 0
1214         for zone in zone_hosts:
1215             creator = self.inst_creators[index]
1216             self.assertTrue(creator.vm_active(block=True))
1217             info = creator.get_vm_info()
1218             deployed_zone = info['OS-EXT-AZ:availability_zone']
1219             deployed_host = info['OS-EXT-SRV-ATTR:host']
1220             self.assertEqual(zone, deployed_zone + ':' + deployed_host)
1221             index += 1
1222
1223
1224 class CreateInstancePubPrivNetTests(OSIntegrationTestCase):
1225     """
1226     Test for the CreateInstance class with two NIC/Ports, eth0 with floating IP
1227     and eth1 w/o.
1228     These tests require a Centos image
1229     """
1230
1231     def setUp(self):
1232         """
1233         Instantiates the CreateImage object that is responsible for downloading
1234         and creating an OS image file within OpenStack
1235         """
1236         super(self.__class__, self).__start__()
1237
1238         self.nova = nova_utils.nova_client(self.os_creds)
1239
1240         # Initialize for tearDown()
1241         self.image_creator = None
1242         self.network_creators = list()
1243         self.router_creators = list()
1244         self.flavor_creator = None
1245         self.keypair_creator = None
1246         self.sec_grp_creator = None
1247         self.inst_creator = None
1248
1249         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1250         self.keypair_priv_filepath = 'tmp/' + self.guid
1251         self.keypair_pub_filepath = self.keypair_priv_filepath + '.pub'
1252         self.keypair_name = self.guid + '-kp'
1253         self.vm_inst_name = self.guid + '-inst'
1254         self.port_1_name = self.guid + '-port-1'
1255         self.port_2_name = self.guid + '-port-2'
1256         self.floating_ip_name = self.guid + 'fip1'
1257         self.priv_net_config = openstack_tests.get_priv_net_config(
1258             net_name=self.guid + '-priv-net',
1259             subnet_name=self.guid + '-priv-subnet',
1260             router_name=self.guid + '-priv-router',
1261             external_net=self.ext_net_name)
1262         self.pub_net_config = openstack_tests.get_pub_net_config(
1263             net_name=self.guid + '-pub-net',
1264             subnet_name=self.guid + '-pub-subnet',
1265             router_name=self.guid + '-pub-router',
1266             external_net=self.ext_net_name)
1267
1268         image_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1269         os_image_settings = openstack_tests.centos_image_settings(
1270             name=image_name, image_metadata=self.image_metadata)
1271
1272         try:
1273             # Create Image
1274             self.image_creator = OpenStackImage(self.os_creds,
1275                                                 os_image_settings)
1276             self.image_creator.create()
1277
1278             # First network is public
1279             self.network_creators.append(OpenStackNetwork(
1280                 self.os_creds, self.pub_net_config.network_settings))
1281             # Second network is private
1282             self.network_creators.append(OpenStackNetwork(
1283                 self.os_creds, self.priv_net_config.network_settings))
1284             for network_creator in self.network_creators:
1285                 network_creator.create()
1286
1287             self.router_creators.append(OpenStackRouter(
1288                 self.os_creds, self.pub_net_config.router_settings))
1289             self.router_creators.append(OpenStackRouter(
1290                 self.os_creds, self.priv_net_config.router_settings))
1291
1292             # Create Routers
1293             for router_creator in self.router_creators:
1294                 router_creator.create()
1295
1296             # Create Flavor
1297             self.flavor_creator = OpenStackFlavor(
1298                 self.admin_os_creds,
1299                 FlavorSettings(name=self.guid + '-flavor-name', ram=512,
1300                                disk=10, vcpus=2,
1301                                metadata=self.flavor_metadata))
1302             self.flavor_creator.create()
1303
1304             # Create Keypair
1305             self.keypair_creator = OpenStackKeypair(
1306                 self.os_creds, KeypairSettings(
1307                     name=self.keypair_name,
1308                     public_filepath=self.keypair_pub_filepath,
1309                     private_filepath=self.keypair_priv_filepath))
1310             self.keypair_creator.create()
1311
1312             sec_grp_name = self.guid + '-sec-grp'
1313             rule1 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
1314                                               direction=Direction.ingress,
1315                                               protocol=Protocol.icmp)
1316             rule2 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
1317                                               direction=Direction.ingress,
1318                                               protocol=Protocol.tcp,
1319                                               port_range_min=22,
1320                                               port_range_max=22)
1321             self.sec_grp_creator = OpenStackSecurityGroup(
1322                 self.os_creds,
1323                 SecurityGroupSettings(name=sec_grp_name,
1324                                       rule_settings=[rule1, rule2]))
1325             self.sec_grp_creator.create()
1326         except:
1327             self.tearDown()
1328             raise
1329
1330     def tearDown(self):
1331         """
1332         Cleans the created objects
1333         """
1334         if self.inst_creator:
1335             try:
1336                 self.inst_creator.clean()
1337             except Exception as e:
1338                 logger.error(
1339                     'Unexpected exception cleaning VM instance with message '
1340                     '- %s', e)
1341
1342         if self.keypair_creator:
1343             try:
1344                 self.keypair_creator.clean()
1345             except Exception as e:
1346                 logger.error(
1347                     'Unexpected exception cleaning keypair with message - %s',
1348                     e)
1349
1350         if os.path.isfile(self.keypair_pub_filepath):
1351             os.remove(self.keypair_pub_filepath)
1352
1353         if os.path.isfile(self.keypair_priv_filepath):
1354             os.remove(self.keypair_priv_filepath)
1355
1356         if self.flavor_creator:
1357             try:
1358                 self.flavor_creator.clean()
1359             except Exception as e:
1360                 logger.error(
1361                     'Unexpected exception cleaning flavor with message - %s',
1362                     e)
1363
1364         for router_creator in self.router_creators:
1365             try:
1366                 router_creator.clean()
1367             except Exception as e:
1368                 logger.error(
1369                     'Unexpected exception cleaning router with message - %s',
1370                     e)
1371
1372         for network_creator in self.network_creators:
1373             try:
1374                 network_creator.clean()
1375             except Exception as e:
1376                 logger.error(
1377                     'Unexpected exception cleaning network with message - %s',
1378                     e)
1379
1380         if self.sec_grp_creator:
1381             try:
1382                 self.sec_grp_creator.clean()
1383             except Exception as e:
1384                 logger.error(
1385                     'Unexpected exception cleaning security group with message'
1386                     ' - %s', e)
1387
1388         if self.image_creator and not self.image_creator.image_settings.exists:
1389             try:
1390                 self.image_creator.clean()
1391             except Exception as e:
1392                 logger.error(
1393                     'Unexpected exception cleaning image with message - %s', e)
1394
1395         super(self.__class__, self).__clean__()
1396
1397     def test_dual_ports_dhcp(self):
1398         """
1399         Tests the creation of an OpenStack instance with a dual ports/NICs with
1400         a DHCP assigned IP.
1401         NOTE: This test and any others that call ansible will most likely fail
1402         unless you do one of two things:
1403         1. Have a ~/.ansible.cfg (or alternate means) to
1404            set host_key_checking = False
1405         2. Set the following environment variable in your executing shell:
1406            ANSIBLE_HOST_KEY_CHECKING=False
1407         Should this not be performed, the creation of the host ssh key will
1408         cause your ansible calls to fail.
1409         """
1410         # Create ports/NICs for instance
1411         ports_settings = []
1412         ctr = 1
1413         for network_creator in self.network_creators:
1414             ports_settings.append(PortSettings(
1415                 name=self.guid + '-port-' + str(ctr),
1416                 network_name=network_creator.network_settings.name))
1417             ctr += 1
1418
1419         # Create instance
1420         instance_settings = VmInstanceSettings(
1421             name=self.vm_inst_name,
1422             flavor=self.flavor_creator.flavor_settings.name,
1423             port_settings=ports_settings,
1424             floating_ip_settings=[FloatingIpSettings(
1425                 name=self.floating_ip_name, port_name=self.port_1_name,
1426                 router_name=self.pub_net_config.router_settings.name)])
1427
1428         self.inst_creator = OpenStackVmInstance(
1429             self.os_creds, instance_settings,
1430             self.image_creator.image_settings,
1431             keypair_settings=self.keypair_creator.keypair_settings)
1432
1433         vm_inst = self.inst_creator.create(block=True)
1434
1435         self.assertEqual(vm_inst, self.inst_creator.get_vm_inst())
1436
1437         # Effectively blocks until VM has been properly activated
1438         self.assertTrue(self.inst_creator.vm_active(block=True))
1439
1440         ip = self.inst_creator.get_port_ip(ports_settings[0].name)
1441         self.assertTrue(check_dhcp_lease(self.inst_creator, ip))
1442
1443         # Add security group to VM
1444         self.inst_creator.add_security_group(
1445             self.sec_grp_creator.get_security_group())
1446
1447         # Effectively blocks until VM's ssh port has been opened
1448         self.assertTrue(self.inst_creator.vm_ssh_active(block=True))
1449
1450         self.assertEqual(0, self.inst_creator.config_nics())
1451
1452
1453 class InstanceSecurityGroupTests(OSIntegrationTestCase):
1454     """
1455     Tests that include, add, and remove security groups from VM instances
1456     """
1457
1458     def setUp(self):
1459         """
1460         Instantiates the CreateImage object that is responsible for downloading
1461         and creating an OS image file within OpenStack
1462         """
1463         super(self.__class__, self).__start__()
1464
1465         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1466         self.vm_inst_name = self.guid + '-inst'
1467         self.nova = nova_utils.nova_client(self.os_creds)
1468         os_image_settings = openstack_tests.cirros_image_settings(
1469             name=self.guid + '-image', image_metadata=self.image_metadata)
1470
1471         self.vm_inst_name = self.guid + '-inst'
1472         self.port_1_name = self.guid + 'port-1'
1473         self.port_2_name = self.guid + 'port-2'
1474         self.floating_ip_name = self.guid + 'fip1'
1475
1476         net_config = openstack_tests.get_priv_net_config(
1477             net_name=self.guid + '-pub-net',
1478             subnet_name=self.guid + '-pub-subnet',
1479             router_name=self.guid + '-pub-router',
1480             external_net=self.ext_net_name)
1481
1482         # Initialize for tearDown()
1483         self.image_creator = None
1484         self.flavor_creator = None
1485         self.network_creator = None
1486         self.router_creator = None
1487         self.inst_creator = None
1488         self.sec_grp_creators = list()
1489
1490         try:
1491             # Create Image
1492             self.image_creator = OpenStackImage(self.os_creds,
1493                                                 os_image_settings)
1494             self.image_creator.create()
1495
1496             # Create Network
1497             self.network_creator = OpenStackNetwork(
1498                 self.os_creds, net_config.network_settings)
1499             self.network_creator.create()
1500
1501             # Create Flavor
1502             self.flavor_creator = OpenStackFlavor(
1503                 self.admin_os_creds,
1504                 FlavorSettings(name=self.guid + '-flavor-name', ram=128,
1505                                disk=10, vcpus=2,
1506                                metadata=self.flavor_metadata))
1507             self.flavor_creator.create()
1508
1509             self.port_settings = PortSettings(
1510                 name=self.guid + '-port',
1511                 network_name=net_config.network_settings.name)
1512         except Exception as e:
1513             self.tearDown()
1514             raise e
1515
1516     def tearDown(self):
1517         """
1518         Cleans the created object
1519         """
1520         if self.inst_creator:
1521             try:
1522                 self.inst_creator.clean()
1523             except Exception as e:
1524                 logger.error(
1525                     'Unexpected exception cleaning VM instance with message -'
1526                     ' %s', e)
1527
1528         for sec_grp_creator in self.sec_grp_creators:
1529             try:
1530                 sec_grp_creator.clean()
1531             except Exception as e:
1532                 logger.error(
1533                     'Unexpected exception cleaning security group with message'
1534                     ' - %s', e)
1535
1536         if self.flavor_creator:
1537             try:
1538                 self.flavor_creator.clean()
1539             except Exception as e:
1540                 logger.error(
1541                     'Unexpected exception cleaning flavor with message - %s',
1542                     e)
1543
1544         if self.network_creator:
1545             try:
1546                 self.network_creator.clean()
1547             except Exception as e:
1548                 logger.error(
1549                     'Unexpected exception cleaning network with message - %s',
1550                     e)
1551
1552         if self.image_creator and not self.image_creator.image_settings.exists:
1553             try:
1554                 self.image_creator.clean()
1555             except Exception as e:
1556                 logger.error(
1557                     'Unexpected exception cleaning image with message - %s', e)
1558
1559         super(self.__class__, self).__clean__()
1560
1561     def test_add_security_group(self):
1562         """
1563         Tests the addition of a security group created after the instance.
1564         """
1565         # Create instance
1566         instance_settings = VmInstanceSettings(
1567             name=self.vm_inst_name,
1568             flavor=self.flavor_creator.flavor_settings.name,
1569             port_settings=[self.port_settings])
1570         self.inst_creator = OpenStackVmInstance(
1571             self.os_creds, instance_settings,
1572             self.image_creator.image_settings)
1573         vm_inst = self.inst_creator.create(block=True)
1574         self.assertIsNotNone(vm_inst)
1575
1576         # Create security group object to add to instance
1577         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1578                                                  description='hello group')
1579         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1580                                                  sec_grp_settings)
1581         sec_grp = sec_grp_creator.create()
1582         self.sec_grp_creators.append(sec_grp_creator)
1583
1584         # Check that group has not been added
1585         self.assertFalse(inst_has_sec_grp(
1586             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1587
1588         # Add security group to instance after activated
1589         self.inst_creator.add_security_group(sec_grp)
1590
1591         # Validate that security group has been added
1592         self.assertTrue(inst_has_sec_grp(
1593             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1594
1595     def test_add_invalid_security_group(self):
1596         """
1597         Tests the addition of a security group that no longer exists.
1598         """
1599         # Create instance
1600         instance_settings = VmInstanceSettings(
1601             name=self.vm_inst_name,
1602             flavor=self.flavor_creator.flavor_settings.name,
1603             port_settings=[self.port_settings])
1604         self.inst_creator = OpenStackVmInstance(
1605             self.os_creds, instance_settings,
1606             self.image_creator.image_settings)
1607         vm_inst = self.inst_creator.create(block=True)
1608         self.assertIsNotNone(vm_inst)
1609
1610         # Create security group object to add to instance
1611         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1612                                                  description='hello group')
1613         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1614                                                  sec_grp_settings)
1615         sec_grp = sec_grp_creator.create()
1616         sec_grp_creator.clean()
1617         self.sec_grp_creators.append(sec_grp_creator)
1618
1619         # Check that group has not been added
1620         self.assertFalse(inst_has_sec_grp(
1621             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1622
1623         # Add security group to instance after activated
1624         self.assertFalse(self.inst_creator.add_security_group(sec_grp))
1625
1626         # Validate that security group has been added
1627         self.assertFalse(inst_has_sec_grp(
1628             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1629
1630     def test_remove_security_group(self):
1631         """
1632         Tests the removal of a security group created before and added to the
1633         instance.
1634         """
1635         # Create security group object to add to instance
1636         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1637                                                  description='hello group')
1638         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1639                                                  sec_grp_settings)
1640         sec_grp = sec_grp_creator.create()
1641         self.sec_grp_creators.append(sec_grp_creator)
1642
1643         # Create instance
1644         instance_settings = VmInstanceSettings(
1645             name=self.vm_inst_name,
1646             flavor=self.flavor_creator.flavor_settings.name,
1647             security_group_names=[sec_grp_settings.name],
1648             port_settings=[self.port_settings])
1649         self.inst_creator = OpenStackVmInstance(
1650             self.os_creds, instance_settings,
1651             self.image_creator.image_settings)
1652         vm_inst = self.inst_creator.create(block=True)
1653         self.assertIsNotNone(vm_inst)
1654
1655         # Check that group has been added
1656         self.assertTrue(inst_has_sec_grp(
1657             self.nova, vm_inst, sec_grp_settings.name))
1658
1659         # Add security group to instance after activated
1660         self.assertTrue(self.inst_creator.remove_security_group(sec_grp))
1661
1662         # Validate that security group has been added
1663         self.assertFalse(inst_has_sec_grp(
1664             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1665
1666     def test_remove_security_group_never_added(self):
1667         """
1668         Tests the removal of a security group that was never added in the first
1669         place.
1670         """
1671         # Create security group object to add to instance
1672         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1673                                                  description='hello group')
1674         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1675                                                  sec_grp_settings)
1676         sec_grp = sec_grp_creator.create()
1677         self.sec_grp_creators.append(sec_grp_creator)
1678
1679         # Create instance
1680         instance_settings = VmInstanceSettings(
1681             name=self.vm_inst_name,
1682             flavor=self.flavor_creator.flavor_settings.name,
1683             port_settings=[self.port_settings])
1684         self.inst_creator = OpenStackVmInstance(
1685             self.os_creds, instance_settings,
1686             self.image_creator.image_settings)
1687         vm_inst = self.inst_creator.create(block=True)
1688         self.assertIsNotNone(vm_inst)
1689
1690         # Check that group has been added
1691         self.assertFalse(inst_has_sec_grp(
1692             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1693
1694         # Add security group to instance after activated
1695         self.assertFalse(self.inst_creator.remove_security_group(sec_grp))
1696
1697         # Validate that security group has been added
1698         self.assertFalse(inst_has_sec_grp(
1699             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1700
1701     def test_add_same_security_group(self):
1702         """
1703         Tests the addition of a security group created before add added to the
1704         instance.
1705         """
1706         # Create security group object to add to instance
1707         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1708                                                  description='hello group')
1709         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1710                                                  sec_grp_settings)
1711         sec_grp = sec_grp_creator.create()
1712         self.sec_grp_creators.append(sec_grp_creator)
1713
1714         # Create instance
1715         instance_settings = VmInstanceSettings(
1716             name=self.vm_inst_name,
1717             flavor=self.flavor_creator.flavor_settings.name,
1718             security_group_names=[sec_grp_settings.name],
1719             port_settings=[self.port_settings])
1720         self.inst_creator = OpenStackVmInstance(
1721             self.os_creds, instance_settings,
1722             self.image_creator.image_settings)
1723         vm_inst = self.inst_creator.create(block=True)
1724         self.assertIsNotNone(vm_inst)
1725
1726         # Check that group has been added
1727         self.assertTrue(inst_has_sec_grp(
1728             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1729
1730         # Add security group to instance after activated
1731         self.assertTrue(self.inst_creator.add_security_group(sec_grp))
1732
1733         # Validate that security group has been added
1734         self.assertTrue(inst_has_sec_grp(
1735             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1736
1737
1738 def inst_has_sec_grp(nova, vm_inst, sec_grp_name):
1739     """
1740     Returns true if instance has a security group of a given name
1741     :param nova: the nova client
1742     :param vm_inst: the VmInst domain object
1743     :param sec_grp_name: the name of the security group to validate
1744     :return: T/F
1745     """
1746     sec_grp_names = nova_utils.get_server_security_group_names(nova, vm_inst)
1747     for name in sec_grp_names:
1748         if sec_grp_name == name:
1749             return True
1750     return False
1751
1752
1753 def validate_ssh_client(instance_creator):
1754     """
1755     Returns True if instance_creator returns an SSH client that is valid
1756     :param instance_creator: the object responsible for creating the VM
1757                              instance
1758     :return: T/F
1759     """
1760     ssh_active = instance_creator.vm_ssh_active(block=True)
1761
1762     if ssh_active:
1763         ssh_client = instance_creator.ssh_client()
1764         if ssh_client:
1765             try:
1766                 out = ssh_client.exec_command('pwd')[1]
1767             finally:
1768                 ssh_client.close()
1769         else:
1770             return False
1771
1772         channel = out.channel
1773         in_buffer = channel.in_buffer
1774         pwd_out = in_buffer.read(1024)
1775         if not pwd_out or len(pwd_out) < 10:
1776             return False
1777         return True
1778
1779     return False
1780
1781
1782 class CreateInstanceFromThreePartImage(OSIntegrationTestCase):
1783     """
1784     Test for the CreateInstance class for creating an image from a 3-part image
1785     """
1786
1787     def setUp(self):
1788         """
1789         Instantiates the CreateImage object that is responsible for downloading
1790         and creating an OS image file within OpenStack
1791         """
1792         super(self.__class__, self).__start__()
1793
1794         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1795         self.image_name = guid
1796         self.vm_inst_name = guid + '-inst'
1797         self.nova = nova_utils.nova_client(self.os_creds)
1798
1799         net_config = openstack_tests.get_priv_net_config(
1800             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
1801             router_name=guid + '-pub-router', external_net=self.ext_net_name)
1802
1803         # Initialize for tearDown()
1804         self.image_creator = None
1805         self.network_creator = None
1806         self.flavor_creator = None
1807         self.inst_creator = None
1808
1809         try:
1810             if self.image_metadata and 'disk_file' in self.image_metadata:
1811                 metadata = self.image_metadata
1812             elif self.image_metadata and 'cirros' in self.image_metadata \
1813                     and 'disk_file' in self.image_metadata['cirros']:
1814                 metadata = self.image_metadata['cirros']
1815             else:
1816                 metadata = {
1817                     'disk_url': openstack_tests.CIRROS_DEFAULT_IMAGE_URL,
1818                     'kernel_url':
1819                         openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL,
1820                     'ramdisk_url':
1821                         openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL}
1822
1823             image_settings = openstack_tests.cirros_image_settings(
1824                 name=self.image_name,
1825                 image_metadata=metadata)
1826
1827             if not image_settings.ramdisk_image_settings or not \
1828                     image_settings.kernel_image_settings:
1829                 logger.warn(
1830                     '3 Part image will not be tested. Image metadata has '
1831                     'overridden this functionality')
1832
1833             self.image_creator = OpenStackImage(self.os_creds, image_settings)
1834             self.image_creator.create()
1835
1836             # Create Flavor
1837             self.flavor_creator = OpenStackFlavor(
1838                 self.admin_os_creds,
1839                 FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
1840                                vcpus=2, metadata=self.flavor_metadata))
1841             self.flavor_creator.create()
1842
1843             # Create Network
1844             self.network_creator = OpenStackNetwork(
1845                 self.os_creds, net_config.network_settings)
1846             self.network_creator.create()
1847
1848             self.port_settings = PortSettings(
1849                 name=guid + '-port',
1850                 network_name=net_config.network_settings.name)
1851         except Exception as e:
1852             self.tearDown()
1853             raise e
1854
1855     def tearDown(self):
1856         """
1857         Cleans the created object
1858         """
1859         if self.inst_creator:
1860             try:
1861                 self.inst_creator.clean()
1862             except Exception as e:
1863                 logger.error(
1864                     'Unexpected exception cleaning VM instance with message -'
1865                     ' %s', e)
1866
1867         if self.flavor_creator:
1868             try:
1869                 self.flavor_creator.clean()
1870             except Exception as e:
1871                 logger.error(
1872                     'Unexpected exception cleaning flavor with message - %s',
1873                     e)
1874
1875         if self.network_creator:
1876             try:
1877                 self.network_creator.clean()
1878             except Exception as e:
1879                 logger.error(
1880                     'Unexpected exception cleaning network with message - %s',
1881                     e)
1882
1883         if self.image_creator and not self.image_creator.image_settings.exists:
1884             try:
1885                 self.image_creator.clean()
1886             except Exception as e:
1887                 logger.error(
1888                     'Unexpected exception cleaning image with message - %s', e)
1889
1890         super(self.__class__, self).__clean__()
1891
1892     def test_create_instance_from_three_part_image(self):
1893         """
1894         Tests the creation of an OpenStack instance from a 3-part image.
1895         """
1896         instance_settings = VmInstanceSettings(
1897             name=self.vm_inst_name,
1898             flavor=self.flavor_creator.flavor_settings.name,
1899             port_settings=[self.port_settings])
1900
1901         # The last created image is the main image from which we create the
1902         # instance
1903         self.inst_creator = OpenStackVmInstance(
1904             self.os_creds, instance_settings,
1905             self.image_creator.image_settings)
1906
1907         vm_inst = self.inst_creator.create()
1908         self.assertIsNotNone(vm_inst)
1909         self.assertTrue(self.inst_creator.vm_active(block=True))
1910
1911
1912 class CreateInstanceMockOfflineTests(OSComponentTestCase):
1913     """
1914     Tests the custom image_metadata that can be set by clients for handling
1915     images differently than the default behavior of the existing tests
1916     primarily for offline testing
1917     """
1918
1919     def setUp(self):
1920         """
1921         Instantiates the CreateImage object that is responsible for downloading
1922         and creating an OS image file within OpenStack
1923         """
1924         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1925
1926         self.tmpDir = 'tmp/' + str(self.guid)
1927         if not os.path.exists(self.tmpDir):
1928             os.makedirs(self.tmpDir)
1929
1930         self.image_name = self.guid + '-image'
1931         self.vm_inst_name = self.guid + '-inst'
1932         self.port_1_name = self.guid + 'port-1'
1933
1934         # Initialize for tearDown()
1935         self.image_creator = None
1936         self.network_creator = None
1937         self.flavor_creator = None
1938         self.inst_creator = None
1939
1940         self.priv_net_config = openstack_tests.get_priv_net_config(
1941             net_name=self.guid + '-priv-net',
1942             subnet_name=self.guid + '-priv-subnet')
1943         self.port_settings = PortSettings(
1944             name=self.port_1_name,
1945             network_name=self.priv_net_config.network_settings.name)
1946
1947         try:
1948             # Download image file
1949             self.image_file = file_utils.download(
1950                 openstack_tests.CIRROS_DEFAULT_IMAGE_URL, self.tmpDir)
1951
1952             # Create Network
1953             self.network_creator = OpenStackNetwork(
1954                 self.os_creds, self.priv_net_config.network_settings)
1955             self.network_creator.create()
1956
1957             # Create Flavor
1958             self.flavor_creator = OpenStackFlavor(
1959                 self.os_creds,
1960                 FlavorSettings(
1961                     name=self.guid + '-flavor-name', ram=128, disk=10,
1962                     vcpus=1))
1963             self.flavor_creator.create()
1964         except Exception as e:
1965             self.tearDown()
1966             raise e
1967
1968     def tearDown(self):
1969         """
1970         Cleans the created object
1971         """
1972         if self.inst_creator:
1973             try:
1974                 self.inst_creator.clean()
1975             except Exception as e:
1976                 logger.error(
1977                     'Unexpected exception cleaning VM instance with message - '
1978                     '%s', e)
1979
1980         if self.network_creator:
1981             try:
1982                 self.network_creator.clean()
1983             except Exception as e:
1984                 logger.error(
1985                     'Unexpected exception cleaning network with message - %s',
1986                     e)
1987
1988         if self.flavor_creator:
1989             try:
1990                 self.flavor_creator.clean()
1991             except Exception as e:
1992                 logger.error(
1993                     'Unexpected exception cleaning flavor with message - %s',
1994                     e)
1995
1996         if self.image_creator:
1997             try:
1998                 self.image_creator.clean()
1999             except Exception as e:
2000                 logger.error(
2001                     'Unexpected exception cleaning image with message - %s', e)
2002
2003         if os.path.exists(self.tmpDir) and os.path.isdir(self.tmpDir):
2004             shutil.rmtree(self.tmpDir)
2005
2006     def test_inst_from_file_image_simple_flat(self):
2007         """
2008         Creates a VM instance from a locally sourced file image using simply
2009         the 'disk_file' attribute vs. using the 'config' option which
2010         completely overrides all image settings
2011         :return: 
2012         """
2013         metadata = {'disk_file': self.image_file.name}
2014
2015         os_image_settings = openstack_tests.cirros_image_settings(
2016             name=self.image_name, image_metadata=metadata)
2017         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2018         self.assertEqual(openstack_tests.CIRROS_USER,
2019                          os_image_settings.image_user)
2020         self.assertIsNone(os_image_settings.url)
2021         self.assertFalse(os_image_settings.exists)
2022         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2023                          os_image_settings.format)
2024
2025         self.assertIsNone(os_image_settings.kernel_image_settings)
2026         self.assertIsNone(os_image_settings.ramdisk_image_settings)
2027
2028         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2029         self.image_creator.create()
2030
2031         instance_settings = VmInstanceSettings(
2032             name=self.vm_inst_name,
2033             flavor=self.flavor_creator.flavor_settings.name,
2034             port_settings=[self.port_settings])
2035         self.inst_creator = OpenStackVmInstance(
2036             self.os_creds, instance_settings,
2037             self.image_creator.image_settings)
2038         self.inst_creator.create()
2039
2040         self.assertTrue(self.inst_creator.vm_active(block=True))
2041
2042     def test_inst_from_file_image_simple_nested(self):
2043         """
2044         Creates a VM instance from a locally sourced file image using simply
2045         the 'disk_file' attribute under 'cirros' vs. using the 'config' option
2046         which completely overrides all image settings
2047         :return: 
2048         """
2049         metadata = {'cirros': {'disk_file': self.image_file.name}}
2050
2051         os_image_settings = openstack_tests.cirros_image_settings(
2052             name=self.image_name, image_metadata=metadata)
2053         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2054         self.assertEqual(openstack_tests.CIRROS_USER,
2055                          os_image_settings.image_user)
2056         self.assertIsNone(os_image_settings.url)
2057         self.assertFalse(os_image_settings.exists)
2058         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2059                          os_image_settings.format)
2060
2061         self.assertIsNone(os_image_settings.kernel_image_settings)
2062         self.assertIsNone(os_image_settings.ramdisk_image_settings)
2063
2064         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2065         self.image_creator.create()
2066
2067         instance_settings = VmInstanceSettings(
2068             name=self.vm_inst_name,
2069             flavor=self.flavor_creator.flavor_settings.name,
2070             port_settings=[self.port_settings])
2071         self.inst_creator = OpenStackVmInstance(
2072             self.os_creds, instance_settings,
2073             self.image_creator.image_settings)
2074         self.inst_creator.create()
2075
2076         self.assertTrue(self.inst_creator.vm_active(block=True))
2077
2078     def test_inst_from_existing(self):
2079         """
2080         Creates a VM instance from a image creator that has been configured to
2081         use an existing image
2082         :return: 
2083         """
2084         os_image_settings = openstack_tests.cirros_image_settings(
2085             name=self.image_name)
2086         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2087         self.image_creator.create()
2088
2089         image_settings = self.image_creator.image_settings
2090         test_image_creator = OpenStackImage(
2091             self.os_creds,
2092             ImageSettings(name=image_settings.name,
2093                           image_user=image_settings.image_user,
2094                           exists=True))
2095         test_image_creator.create()
2096         self.assertEqual(self.image_creator.get_image().id,
2097                          test_image_creator.get_image().id)
2098
2099         instance_settings = VmInstanceSettings(
2100             name=self.vm_inst_name,
2101             flavor=self.flavor_creator.flavor_settings.name,
2102             port_settings=[self.port_settings])
2103         self.inst_creator = OpenStackVmInstance(
2104             self.os_creds, instance_settings,
2105             test_image_creator.image_settings)
2106         self.inst_creator.create()
2107
2108         self.assertTrue(self.inst_creator.vm_active(block=True))
2109
2110     def test_inst_from_file_image_complex(self):
2111         """
2112         Creates a VM instance from a locally sourced file image by overriding
2113         the default settings by using a dict() that can be read in by
2114         ImageSettings
2115         :return: 
2116         """
2117
2118         os_image_settings = openstack_tests.cirros_image_settings(
2119             name=self.image_name)
2120         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2121         self.image_creator.create()
2122
2123         metadata = {
2124             'cirros': {
2125                 'config': {
2126                     'name': os_image_settings.name,
2127                     'image_user': os_image_settings.image_user,
2128                     'exists': True}}}
2129         test_image_settings = openstack_tests.cirros_image_settings(
2130             image_metadata=metadata)
2131         test_image = OpenStackImage(self.os_creds, test_image_settings)
2132         test_image.create()
2133
2134         instance_settings = VmInstanceSettings(
2135             name=self.vm_inst_name,
2136             flavor=self.flavor_creator.flavor_settings.name,
2137             port_settings=[self.port_settings])
2138         self.inst_creator = OpenStackVmInstance(self.os_creds,
2139                                                 instance_settings,
2140                                                 test_image_settings)
2141         self.inst_creator.create()
2142
2143         self.assertTrue(self.inst_creator.vm_active(block=True))
2144
2145     def test_inst_from_file_3part_image_complex(self):
2146         """
2147         Creates a VM instance from a locally sourced file image by overriding
2148         the default settings by using a dict() that can be read in by
2149         ImageSettings
2150         :return: 
2151         """
2152
2153         kernel_file = file_utils.download(
2154             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2155         ramdisk_file = file_utils.download(
2156             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2157
2158         metadata = {
2159             'cirros': {
2160                 'config': {
2161                     'name': self.image_name,
2162                     'image_user': openstack_tests.CIRROS_USER,
2163                     'image_file': self.image_file.name,
2164                     'format': openstack_tests.DEFAULT_IMAGE_FORMAT,
2165                     'kernel_image_settings': {
2166                         'name': self.image_name + '-kernel',
2167                         'image_user': openstack_tests.CIRROS_USER,
2168                         'image_file': kernel_file.name,
2169                         'format': openstack_tests.DEFAULT_IMAGE_FORMAT},
2170                     'ramdisk_image_settings': {
2171                         'name': self.image_name + '-ramdisk',
2172                         'image_user': openstack_tests.CIRROS_USER,
2173                         'image_file': ramdisk_file.name,
2174                         'format': openstack_tests.DEFAULT_IMAGE_FORMAT}}}}
2175
2176         os_image_settings = openstack_tests.cirros_image_settings(
2177             name=self.image_name, image_metadata=metadata)
2178         self.assertEqual(self.image_name, os_image_settings.name)
2179         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2180         self.assertEqual(openstack_tests.CIRROS_USER,
2181                          os_image_settings.image_user)
2182         self.assertIsNone(os_image_settings.url)
2183         self.assertFalse(os_image_settings.exists)
2184         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2185                          os_image_settings.format)
2186
2187         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2188         self.assertEqual(self.image_name + '-kernel',
2189                          os_image_settings.kernel_image_settings.name)
2190         self.assertEqual(kernel_file.name,
2191                          os_image_settings.kernel_image_settings.image_file)
2192         self.assertEqual(openstack_tests.CIRROS_USER,
2193                          os_image_settings.kernel_image_settings.image_user)
2194         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2195         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2196         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2197                          os_image_settings.kernel_image_settings.format)
2198
2199         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2200         self.assertEqual(self.image_name + '-ramdisk',
2201                          os_image_settings.ramdisk_image_settings.name)
2202         self.assertEqual(ramdisk_file.name,
2203                          os_image_settings.ramdisk_image_settings.image_file)
2204         self.assertEqual(openstack_tests.CIRROS_USER,
2205                          os_image_settings.ramdisk_image_settings.image_user)
2206         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2207         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2208         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2209                          os_image_settings.ramdisk_image_settings.format)
2210
2211         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2212         self.image_creator.create()
2213
2214         instance_settings = VmInstanceSettings(
2215             name=self.vm_inst_name,
2216             flavor=self.flavor_creator.flavor_settings.name,
2217             port_settings=[self.port_settings])
2218         self.inst_creator = OpenStackVmInstance(
2219             self.os_creds, instance_settings,
2220             self.image_creator.image_settings)
2221         self.inst_creator.create()
2222
2223         self.assertTrue(self.inst_creator.vm_active(block=True))
2224
2225     def test_inst_from_file_3part_image_simple_flat(self):
2226         """
2227         Creates a VM instance from a 3-part image locally sourced from file
2228         images using simply the 'disk_file', 'kernel_file', and 'ramdisk_file'
2229         attributes vs. using the 'config' option which completely overrides all
2230         image settings
2231         :return: 
2232         """
2233         kernel_file = file_utils.download(
2234             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2235         ramdisk_file = file_utils.download(
2236             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2237
2238         metadata = {'disk_file': self.image_file.name,
2239                     'kernel_file': kernel_file.name,
2240                     'ramdisk_file': ramdisk_file.name}
2241
2242         os_image_settings = openstack_tests.cirros_image_settings(
2243             name=self.image_name, image_metadata=metadata)
2244
2245         self.assertEqual(self.image_name, os_image_settings.name)
2246         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2247         self.assertEqual(openstack_tests.CIRROS_USER,
2248                          os_image_settings.image_user)
2249         self.assertIsNone(os_image_settings.url)
2250         self.assertFalse(os_image_settings.exists)
2251         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2252                          os_image_settings.format)
2253
2254         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2255         self.assertEqual(self.image_name + '-kernel',
2256                          os_image_settings.kernel_image_settings.name)
2257         self.assertEqual(kernel_file.name,
2258                          os_image_settings.kernel_image_settings.image_file)
2259         self.assertEqual(openstack_tests.CIRROS_USER,
2260                          os_image_settings.kernel_image_settings.image_user)
2261         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2262         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2263         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2264                          os_image_settings.kernel_image_settings.format)
2265
2266         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2267         self.assertEqual(self.image_name + '-ramdisk',
2268                          os_image_settings.ramdisk_image_settings.name)
2269         self.assertEqual(ramdisk_file.name,
2270                          os_image_settings.ramdisk_image_settings.image_file)
2271         self.assertEqual(openstack_tests.CIRROS_USER,
2272                          os_image_settings.ramdisk_image_settings.image_user)
2273         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2274         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2275         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2276                          os_image_settings.ramdisk_image_settings.format)
2277
2278         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2279         self.image_creator.create()
2280
2281         self.assertIsNotNone(self.image_creator.get_kernel_image())
2282         self.assertIsNotNone(self.image_creator.get_ramdisk_image())
2283
2284         instance_settings = VmInstanceSettings(
2285             name=self.vm_inst_name,
2286             flavor=self.flavor_creator.flavor_settings.name,
2287             port_settings=[self.port_settings])
2288         self.inst_creator = OpenStackVmInstance(
2289             self.os_creds, instance_settings,
2290             self.image_creator.image_settings)
2291         self.inst_creator.create()
2292
2293         self.assertTrue(self.inst_creator.vm_active(block=True))
2294
2295     def test_inst_from_file_3part_image_simple_nested(self):
2296         """
2297         Creates a VM instance from a 3-part image locally sourced from file
2298         images using simply the 'disk_file', 'kernel_file', and 'ramdisk_file'
2299         attributes under 'cirros' vs. using the 'config' option which
2300         completely overrides all image settings
2301         :return: 
2302         """
2303         kernel_file = file_utils.download(
2304             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2305         ramdisk_file = file_utils.download(
2306             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2307
2308         metadata = {'cirros': {'disk_file': self.image_file.name,
2309                                'kernel_file': kernel_file.name,
2310                                'ramdisk_file': ramdisk_file.name}}
2311
2312         os_image_settings = openstack_tests.cirros_image_settings(
2313             name=self.image_name, image_metadata=metadata)
2314
2315         self.assertEqual(self.image_name, os_image_settings.name)
2316         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2317         self.assertEqual(openstack_tests.CIRROS_USER,
2318                          os_image_settings.image_user)
2319         self.assertIsNone(os_image_settings.url)
2320         self.assertFalse(os_image_settings.exists)
2321         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2322                          os_image_settings.format)
2323
2324         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2325         self.assertEqual(self.image_name + '-kernel',
2326                          os_image_settings.kernel_image_settings.name)
2327         self.assertEqual(kernel_file.name,
2328                          os_image_settings.kernel_image_settings.image_file)
2329         self.assertEqual(openstack_tests.CIRROS_USER,
2330                          os_image_settings.kernel_image_settings.image_user)
2331         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2332         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2333         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2334                          os_image_settings.kernel_image_settings.format)
2335
2336         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2337         self.assertEqual(self.image_name + '-ramdisk',
2338                          os_image_settings.ramdisk_image_settings.name)
2339         self.assertEqual(ramdisk_file.name,
2340                          os_image_settings.ramdisk_image_settings.image_file)
2341         self.assertEqual(openstack_tests.CIRROS_USER,
2342                          os_image_settings.ramdisk_image_settings.image_user)
2343         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2344         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2345         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2346                          os_image_settings.ramdisk_image_settings.format)
2347
2348         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2349         self.image_creator.create()
2350
2351         self.assertIsNotNone(self.image_creator.get_kernel_image())
2352         self.assertIsNotNone(self.image_creator.get_ramdisk_image())
2353
2354         instance_settings = VmInstanceSettings(
2355             name=self.vm_inst_name,
2356             flavor=self.flavor_creator.flavor_settings.name,
2357             port_settings=[self.port_settings])
2358         self.inst_creator = OpenStackVmInstance(
2359             self.os_creds, instance_settings,
2360             self.image_creator.image_settings)
2361         self.inst_creator.create()
2362
2363         self.assertTrue(self.inst_creator.vm_active(block=True))
2364
2365     def test_inst_from_file_3part_image_existing(self):
2366         """
2367         Creates a VM instance from a 3-part image that is existing
2368         :return: 
2369         """
2370         kernel_file = file_utils.download(
2371             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2372         ramdisk_file = file_utils.download(
2373             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2374
2375         metadata = {'cirros': {'disk_file': self.image_file.name,
2376                                'kernel_file': kernel_file.name,
2377                                'ramdisk_file': ramdisk_file.name}}
2378
2379         os_image_settings = openstack_tests.cirros_image_settings(
2380             name=self.image_name, image_metadata=metadata)
2381         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2382         self.image_creator.create()
2383
2384         image_settings = self.image_creator.image_settings
2385         test_image_creator = OpenStackImage(
2386             self.os_creds,
2387             ImageSettings(name=image_settings.name,
2388                           image_user=image_settings.image_user,
2389                           exists=True))
2390         test_image_creator.create()
2391         self.assertEqual(self.image_creator.get_image().id,
2392                          test_image_creator.get_image().id)
2393
2394         instance_settings = VmInstanceSettings(
2395             name=self.vm_inst_name,
2396             flavor=self.flavor_creator.flavor_settings.name,
2397             port_settings=[self.port_settings])
2398         self.inst_creator = OpenStackVmInstance(
2399             self.os_creds, instance_settings,
2400             test_image_creator.image_settings)
2401         self.inst_creator.create()
2402
2403         self.assertTrue(self.inst_creator.vm_active(block=True))
2404
2405
2406 def check_dhcp_lease(inst_creator, ip, timeout=160):
2407     """
2408     Returns true if the expected DHCP lease has been acquired
2409     :param inst_creator: the SNAPS OpenStackVmInstance object
2410     :param ip: the IP address to look for
2411     :param timeout: how long to query for IP address
2412     :return:
2413     """
2414     found = False
2415     start_time = time.time()
2416
2417     logger.info("Looking for IP %s in the console log" % ip)
2418     full_log = ''
2419     while timeout > time.time() - start_time:
2420         output = inst_creator.get_console_output()
2421         full_log = full_log + output
2422         if re.search(ip, output):
2423             logger.info('DHCP lease obtained logged in console')
2424             found = True
2425             break
2426
2427     if not found:
2428         logger.error('Full console output -\n' + full_log)
2429     else:
2430         logger.debug('Full console output -\n' + full_log)
2431
2432     return found