Ensure library and tests close all necessary resources.
[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
750 class CreateInstancePortManipulationTests(OSIntegrationTestCase):
751     """
752     Test for the CreateInstance class with a single NIC/Port where mac and IP
753     values are manually set
754     """
755
756     def setUp(self):
757         """
758         Instantiates the CreateImage object that is responsible for downloading
759         and creating an OS image file within OpenStack
760         """
761         super(self.__class__, self).__start__()
762
763         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
764         self.vm_inst_name = guid + '-inst'
765         self.port_1_name = guid + 'port-1'
766         self.port_2_name = guid + 'port-2'
767         self.floating_ip_name = guid + 'fip1'
768
769         # Initialize for tearDown()
770         self.image_creator = None
771         self.network_creator = None
772         self.flavor_creator = None
773         self.inst_creator = None
774
775         self.net_config = openstack_tests.get_priv_net_config(
776             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
777             router_name=guid + '-pub-router', external_net=self.ext_net_name)
778         os_image_settings = openstack_tests.cirros_image_settings(
779             name=guid + '-image', image_metadata=self.image_metadata)
780
781         try:
782             # Create Image
783             self.image_creator = OpenStackImage(self.os_creds,
784                                                 os_image_settings)
785             self.image_creator.create()
786
787             # Create Network
788             self.network_creator = OpenStackNetwork(
789                 self.os_creds, self.net_config.network_settings)
790             self.network_creator.create()
791
792             # Create Flavor
793             self.flavor_creator = OpenStackFlavor(
794                 self.admin_os_creds,
795                 FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
796                                vcpus=2, metadata=self.flavor_metadata))
797             self.flavor_creator.create()
798         except Exception as e:
799             self.tearDown()
800             raise e
801
802     def tearDown(self):
803         """
804         Cleans the created object
805         """
806         if self.inst_creator:
807             try:
808                 self.inst_creator.clean()
809             except Exception as e:
810                 logger.error(
811                     'Unexpected exception cleaning VM instance with message '
812                     '- %s', e)
813
814         if self.flavor_creator:
815             try:
816                 self.flavor_creator.clean()
817             except Exception as e:
818                 logger.error(
819                     'Unexpected exception cleaning flavor with message - %s',
820                     e)
821
822         if self.network_creator:
823             try:
824                 self.network_creator.clean()
825             except Exception as e:
826                 logger.error(
827                     'Unexpected exception cleaning network with message - %s',
828                     e)
829
830         if self.image_creator and not self.image_creator.image_settings.exists:
831             try:
832                 self.image_creator.clean()
833             except Exception as e:
834                 logger.error(
835                     'Unexpected exception cleaning image with message - %s', e)
836
837         super(self.__class__, self).__clean__()
838
839     def test_set_custom_valid_ip_one_subnet(self):
840         """
841         Tests the creation of an OpenStack instance with a single port with a
842         static IP on a network with one subnet.
843         """
844         ip = '10.55.0.101'
845         sub_settings = self.net_config.network_settings.subnet_settings
846         port_settings = PortSettings(
847             name=self.port_1_name,
848             network_name=self.net_config.network_settings.name,
849             ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}])
850
851         instance_settings = VmInstanceSettings(
852             name=self.vm_inst_name,
853             flavor=self.flavor_creator.flavor_settings.name,
854             port_settings=[port_settings])
855
856         self.inst_creator = OpenStackVmInstance(
857             self.os_creds, instance_settings,
858             self.image_creator.image_settings)
859         self.inst_creator.create(block=True)
860
861         self.assertEqual(ip, self.inst_creator.get_port_ip(
862             self.port_1_name,
863             subnet_name=self.net_config.network_settings.subnet_settings[
864                 0].name))
865
866     def test_set_custom_invalid_ip_one_subnet(self):
867         """
868         Tests the creation of an OpenStack instance with a single port with a
869         static IP on a network with one subnet.
870         """
871         ip = '10.66.0.101'
872         sub_settings = self.net_config.network_settings.subnet_settings
873         port_settings = PortSettings(
874             name=self.port_1_name,
875             network_name=self.net_config.network_settings.name,
876             ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}])
877
878         instance_settings = VmInstanceSettings(
879             name=self.vm_inst_name,
880             flavor=self.flavor_creator.flavor_settings.name,
881             port_settings=[port_settings])
882
883         self.inst_creator = OpenStackVmInstance(
884             self.os_creds, instance_settings,
885             self.image_creator.image_settings)
886
887         with self.assertRaises(InvalidIpForSubnetClient):
888             self.inst_creator.create()
889
890     def test_set_custom_valid_mac(self):
891         """
892         Tests the creation of an OpenStack instance with a single port where
893         the MAC address is assigned.
894         """
895         mac_addr = '0a:1b:2c:3d:4e:5f'
896         port_settings = PortSettings(
897             name=self.port_1_name,
898             network_name=self.net_config.network_settings.name,
899             mac_address=mac_addr)
900
901         instance_settings = VmInstanceSettings(
902             name=self.vm_inst_name,
903             flavor=self.flavor_creator.flavor_settings.name,
904             port_settings=[port_settings])
905
906         self.inst_creator = OpenStackVmInstance(
907             self.os_creds, instance_settings,
908             self.image_creator.image_settings)
909         self.inst_creator.create(block=True)
910
911         self.assertEqual(mac_addr,
912                          self.inst_creator.get_port_mac(self.port_1_name))
913
914     def test_set_custom_invalid_mac(self):
915         """
916         Tests the creation of an OpenStack instance with a single port where an
917         invalid MAC address value is being
918         assigned. This should raise an Exception
919         """
920         port_settings = PortSettings(
921             name=self.port_1_name,
922             network_name=self.net_config.network_settings.name,
923             mac_address='foo')
924
925         instance_settings = VmInstanceSettings(
926             name=self.vm_inst_name,
927             flavor=self.flavor_creator.flavor_settings.name,
928             port_settings=[port_settings])
929
930         self.inst_creator = OpenStackVmInstance(
931             self.os_creds, instance_settings,
932             self.image_creator.image_settings)
933
934         with self.assertRaises(Exception):
935             self.inst_creator.create()
936
937     def test_set_custom_mac_and_ip(self):
938         """
939         Tests the creation of an OpenStack instance with a single port where
940         the IP and MAC address is assigned.
941         """
942         ip = '10.55.0.101'
943         mac_addr = '0a:1b:2c:3d:4e:5f'
944         sub_settings = self.net_config.network_settings.subnet_settings
945         port_settings = PortSettings(
946             name=self.port_1_name,
947             network_name=self.net_config.network_settings.name,
948             mac_address=mac_addr,
949             ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}])
950
951         instance_settings = VmInstanceSettings(
952             name=self.vm_inst_name,
953             flavor=self.flavor_creator.flavor_settings.name,
954             port_settings=[port_settings])
955
956         self.inst_creator = OpenStackVmInstance(
957             self.os_creds, instance_settings,
958             self.image_creator.image_settings)
959         self.inst_creator.create(block=True)
960
961         self.assertEqual(ip, self.inst_creator.get_port_ip(
962             self.port_1_name,
963             subnet_name=self.net_config.network_settings.subnet_settings[
964                 0].name))
965         self.assertEqual(mac_addr,
966                          self.inst_creator.get_port_mac(self.port_1_name))
967
968     def test_set_allowed_address_pairs(self):
969         """
970         Tests the creation of an OpenStack instance with a single port where
971         max_allowed_address_pair is set.
972         """
973         ip = '10.55.0.101'
974         mac_addr = '0a:1b:2c:3d:4e:5f'
975         pair = {'ip_address': ip, 'mac_address': mac_addr}
976         port_settings = PortSettings(
977             name=self.port_1_name,
978             network_name=self.net_config.network_settings.name,
979             allowed_address_pairs=[pair])
980
981         instance_settings = VmInstanceSettings(
982             name=self.vm_inst_name,
983             flavor=self.flavor_creator.flavor_settings.name,
984             port_settings=[port_settings])
985
986         self.inst_creator = OpenStackVmInstance(
987             self.os_creds, instance_settings,
988             self.image_creator.image_settings)
989         self.inst_creator.create(block=True)
990
991         port = self.inst_creator.get_port_by_name(port_settings.name)
992         self.assertIsNotNone(port)
993         self.assertIsNotNone(port.allowed_address_pairs)
994         self.assertEqual(1, len(port.allowed_address_pairs))
995         validation_utils.objects_equivalent(pair,
996                                             port.allowed_address_pairs[0])
997
998     def test_set_allowed_address_pairs_bad_mac(self):
999         """
1000         Tests the creation of an OpenStack instance with a single port where
1001         max_allowed_address_pair is set with an invalid MAC address.
1002         """
1003         ip = '10.55.0.101'
1004         mac_addr = 'foo'
1005         pair = {'ip_address': ip, 'mac_address': mac_addr}
1006         pairs = set()
1007         pairs.add((ip, mac_addr))
1008         port_settings = PortSettings(
1009             name=self.port_1_name,
1010             network_name=self.net_config.network_settings.name,
1011             allowed_address_pairs=[pair])
1012
1013         instance_settings = VmInstanceSettings(
1014             name=self.vm_inst_name,
1015             flavor=self.flavor_creator.flavor_settings.name,
1016             port_settings=[port_settings])
1017
1018         self.inst_creator = OpenStackVmInstance(
1019             self.os_creds, instance_settings,
1020             self.image_creator.image_settings)
1021         with self.assertRaises(Exception):
1022             self.inst_creator.create()
1023
1024     def test_set_allowed_address_pairs_bad_ip(self):
1025         """
1026         Tests the creation of an OpenStack instance with a single port where
1027         max_allowed_address_pair is set with an invalid MAC address.
1028         """
1029         ip = 'foo'
1030         mac_addr = '0a:1b:2c:3d:4e:5f'
1031         pair = {'ip_address': ip, 'mac_address': mac_addr}
1032         pairs = set()
1033         pairs.add((ip, mac_addr))
1034         port_settings = PortSettings(
1035             name=self.port_1_name,
1036             network_name=self.net_config.network_settings.name,
1037             allowed_address_pairs=[pair])
1038
1039         instance_settings = VmInstanceSettings(
1040             name=self.vm_inst_name,
1041             flavor=self.flavor_creator.flavor_settings.name,
1042             port_settings=[port_settings])
1043
1044         self.inst_creator = OpenStackVmInstance(
1045             self.os_creds, instance_settings,
1046             self.image_creator.image_settings)
1047         with self.assertRaises(Exception):
1048             self.inst_creator.create()
1049
1050
1051 class CreateInstanceOnComputeHost(OSIntegrationTestCase):
1052     """
1053     Test for the CreateInstance where one VM is deployed to each compute node
1054     """
1055
1056     def setUp(self):
1057         """
1058         Instantiates the CreateImage object that is responsible for downloading
1059         and creating an OS image file within OpenStack
1060         """
1061         super(self.__class__, self).__start__()
1062
1063         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1064         self.vm_inst_name = guid + '-inst'
1065         self.port_base_name = guid + 'port'
1066
1067         # Initialize for tearDown()
1068         self.image_creator = None
1069         self.flavor_creator = None
1070         self.network_creator = None
1071         self.inst_creators = list()
1072
1073         self.priv_net_config = openstack_tests.get_priv_net_config(
1074             net_name=guid + '-priv-net', subnet_name=guid + '-priv-subnet')
1075
1076         os_image_settings = openstack_tests.cirros_image_settings(
1077             name=guid + '-image', image_metadata=self.image_metadata)
1078
1079         try:
1080             # Create Network
1081             self.network_creator = OpenStackNetwork(
1082                 self.admin_os_creds, self.priv_net_config.network_settings)
1083             self.network_creator.create()
1084
1085             # Create Flavor
1086             self.flavor_creator = OpenStackFlavor(
1087                 self.admin_os_creds,
1088                 FlavorSettings(name=guid + '-flavor-name', ram=512, disk=1,
1089                                vcpus=1, metadata=self.flavor_metadata))
1090             self.flavor_creator.create()
1091
1092             # Create Image
1093             self.image_creator = OpenStackImage(self.os_creds,
1094                                                 os_image_settings)
1095             self.image_creator.create()
1096
1097         except Exception as e:
1098             self.tearDown()
1099             raise e
1100
1101     def tearDown(self):
1102         """
1103         Cleans the created object
1104         """
1105         for inst_creator in self.inst_creators:
1106             try:
1107                 inst_creator.clean()
1108             except Exception as e:
1109                 logger.error(
1110                     'Unexpected exception cleaning VM instance with message '
1111                     '- %s', e)
1112
1113         if self.flavor_creator:
1114             try:
1115                 self.flavor_creator.clean()
1116             except Exception as e:
1117                 logger.error(
1118                     'Unexpected exception cleaning flavor with message - %s',
1119                     e)
1120
1121         if self.network_creator:
1122             try:
1123                 self.network_creator.clean()
1124             except Exception as e:
1125                 logger.error(
1126                     'Unexpected exception cleaning network with message - %s',
1127                     e)
1128
1129         if self.image_creator and not self.image_creator.image_settings.exists:
1130             try:
1131                 self.image_creator.clean()
1132             except Exception as e:
1133                 logger.error(
1134                     'Unexpected exception cleaning image with message - %s', e)
1135
1136         super(self.__class__, self).__clean__()
1137
1138     def test_deploy_vm_to_each_compute_node(self):
1139         """
1140         Tests the creation of OpenStack VM instances to each compute node.
1141         """
1142         from snaps.openstack.utils import nova_utils
1143         nova = nova_utils.nova_client(self.admin_os_creds)
1144         zone_hosts = nova_utils.get_availability_zone_hosts(nova)
1145
1146         # Create Instance on each server/zone
1147         ctr = 0
1148         for zone in zone_hosts:
1149             inst_name = self.vm_inst_name + '-' + zone
1150             ctr += 1
1151             port_settings = PortSettings(
1152                 name=self.port_base_name + '-' + str(ctr),
1153                 network_name=self.priv_net_config.network_settings.name)
1154
1155             instance_settings = VmInstanceSettings(
1156                 name=inst_name,
1157                 flavor=self.flavor_creator.flavor_settings.name,
1158                 availability_zone=zone,
1159                 port_settings=[port_settings])
1160             inst_creator = OpenStackVmInstance(
1161                 self.admin_os_creds, instance_settings,
1162                 self.image_creator.image_settings)
1163             self.inst_creators.append(inst_creator)
1164             inst_creator.create()
1165
1166         # Validate instances to ensure they've been deployed to the correct
1167         # server
1168         index = 0
1169         for zone in zone_hosts:
1170             creator = self.inst_creators[index]
1171             self.assertTrue(creator.vm_active(block=True))
1172             info = creator.get_vm_info()
1173             deployed_zone = info['OS-EXT-AZ:availability_zone']
1174             deployed_host = info['OS-EXT-SRV-ATTR:host']
1175             self.assertEqual(zone, deployed_zone + ':' + deployed_host)
1176             index += 1
1177
1178
1179 class CreateInstancePubPrivNetTests(OSIntegrationTestCase):
1180     """
1181     Test for the CreateInstance class with two NIC/Ports, eth0 with floating IP
1182     and eth1 w/o.
1183     These tests require a Centos image
1184     """
1185
1186     def setUp(self):
1187         """
1188         Instantiates the CreateImage object that is responsible for downloading
1189         and creating an OS image file within OpenStack
1190         """
1191         super(self.__class__, self).__start__()
1192
1193         self.nova = nova_utils.nova_client(self.os_creds)
1194
1195         # Initialize for tearDown()
1196         self.image_creator = None
1197         self.network_creators = list()
1198         self.router_creators = list()
1199         self.flavor_creator = None
1200         self.keypair_creator = None
1201         self.sec_grp_creator = None
1202         self.inst_creator = None
1203
1204         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1205         self.keypair_priv_filepath = 'tmp/' + self.guid
1206         self.keypair_pub_filepath = self.keypair_priv_filepath + '.pub'
1207         self.keypair_name = self.guid + '-kp'
1208         self.vm_inst_name = self.guid + '-inst'
1209         self.port_1_name = self.guid + '-port-1'
1210         self.port_2_name = self.guid + '-port-2'
1211         self.floating_ip_name = self.guid + 'fip1'
1212         self.priv_net_config = openstack_tests.get_priv_net_config(
1213             net_name=self.guid + '-priv-net',
1214             subnet_name=self.guid + '-priv-subnet',
1215             router_name=self.guid + '-priv-router',
1216             external_net=self.ext_net_name)
1217         self.pub_net_config = openstack_tests.get_pub_net_config(
1218             net_name=self.guid + '-pub-net',
1219             subnet_name=self.guid + '-pub-subnet',
1220             router_name=self.guid + '-pub-router',
1221             external_net=self.ext_net_name)
1222
1223         image_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1224         os_image_settings = openstack_tests.centos_image_settings(
1225             name=image_name, image_metadata=self.image_metadata)
1226
1227         try:
1228             # Create Image
1229             self.image_creator = OpenStackImage(self.os_creds,
1230                                                 os_image_settings)
1231             self.image_creator.create()
1232
1233             # First network is public
1234             self.network_creators.append(OpenStackNetwork(
1235                 self.os_creds, self.pub_net_config.network_settings))
1236             # Second network is private
1237             self.network_creators.append(OpenStackNetwork(
1238                 self.os_creds, self.priv_net_config.network_settings))
1239             for network_creator in self.network_creators:
1240                 network_creator.create()
1241
1242             self.router_creators.append(OpenStackRouter(
1243                 self.os_creds, self.pub_net_config.router_settings))
1244             self.router_creators.append(OpenStackRouter(
1245                 self.os_creds, self.priv_net_config.router_settings))
1246
1247             # Create Routers
1248             for router_creator in self.router_creators:
1249                 router_creator.create()
1250
1251             # Create Flavor
1252             self.flavor_creator = OpenStackFlavor(
1253                 self.admin_os_creds,
1254                 FlavorSettings(name=self.guid + '-flavor-name', ram=512,
1255                                disk=10, vcpus=2,
1256                                metadata=self.flavor_metadata))
1257             self.flavor_creator.create()
1258
1259             # Create Keypair
1260             self.keypair_creator = OpenStackKeypair(
1261                 self.os_creds, KeypairSettings(
1262                     name=self.keypair_name,
1263                     public_filepath=self.keypair_pub_filepath,
1264                     private_filepath=self.keypair_priv_filepath))
1265             self.keypair_creator.create()
1266
1267             sec_grp_name = self.guid + '-sec-grp'
1268             rule1 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
1269                                               direction=Direction.ingress,
1270                                               protocol=Protocol.icmp)
1271             rule2 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
1272                                               direction=Direction.ingress,
1273                                               protocol=Protocol.tcp,
1274                                               port_range_min=22,
1275                                               port_range_max=22)
1276             self.sec_grp_creator = OpenStackSecurityGroup(
1277                 self.os_creds,
1278                 SecurityGroupSettings(name=sec_grp_name,
1279                                       rule_settings=[rule1, rule2]))
1280             self.sec_grp_creator.create()
1281         except:
1282             self.tearDown()
1283             raise
1284
1285     def tearDown(self):
1286         """
1287         Cleans the created objects
1288         """
1289         if self.inst_creator:
1290             try:
1291                 self.inst_creator.clean()
1292             except Exception as e:
1293                 logger.error(
1294                     'Unexpected exception cleaning VM instance with message '
1295                     '- %s', e)
1296
1297         if self.keypair_creator:
1298             try:
1299                 self.keypair_creator.clean()
1300             except Exception as e:
1301                 logger.error(
1302                     'Unexpected exception cleaning keypair with message - %s',
1303                     e)
1304
1305         if os.path.isfile(self.keypair_pub_filepath):
1306             os.remove(self.keypair_pub_filepath)
1307
1308         if os.path.isfile(self.keypair_priv_filepath):
1309             os.remove(self.keypair_priv_filepath)
1310
1311         if self.flavor_creator:
1312             try:
1313                 self.flavor_creator.clean()
1314             except Exception as e:
1315                 logger.error(
1316                     'Unexpected exception cleaning flavor with message - %s',
1317                     e)
1318
1319         for router_creator in self.router_creators:
1320             try:
1321                 router_creator.clean()
1322             except Exception as e:
1323                 logger.error(
1324                     'Unexpected exception cleaning router with message - %s',
1325                     e)
1326
1327         for network_creator in self.network_creators:
1328             try:
1329                 network_creator.clean()
1330             except Exception as e:
1331                 logger.error(
1332                     'Unexpected exception cleaning network with message - %s',
1333                     e)
1334
1335         if self.sec_grp_creator:
1336             try:
1337                 self.sec_grp_creator.clean()
1338             except Exception as e:
1339                 logger.error(
1340                     'Unexpected exception cleaning security group with message'
1341                     ' - %s', e)
1342
1343         if self.image_creator and not self.image_creator.image_settings.exists:
1344             try:
1345                 self.image_creator.clean()
1346             except Exception as e:
1347                 logger.error(
1348                     'Unexpected exception cleaning image with message - %s', e)
1349
1350         super(self.__class__, self).__clean__()
1351
1352     def test_dual_ports_dhcp(self):
1353         """
1354         Tests the creation of an OpenStack instance with a dual ports/NICs with
1355         a DHCP assigned IP.
1356         NOTE: This test and any others that call ansible will most likely fail
1357         unless you do one of two things:
1358         1. Have a ~/.ansible.cfg (or alternate means) to
1359            set host_key_checking = False
1360         2. Set the following environment variable in your executing shell:
1361            ANSIBLE_HOST_KEY_CHECKING=False
1362         Should this not be performed, the creation of the host ssh key will
1363         cause your ansible calls to fail.
1364         """
1365         # Create ports/NICs for instance
1366         ports_settings = []
1367         ctr = 1
1368         for network_creator in self.network_creators:
1369             ports_settings.append(PortSettings(
1370                 name=self.guid + '-port-' + str(ctr),
1371                 network_name=network_creator.network_settings.name))
1372             ctr += 1
1373
1374         # Create instance
1375         instance_settings = VmInstanceSettings(
1376             name=self.vm_inst_name,
1377             flavor=self.flavor_creator.flavor_settings.name,
1378             port_settings=ports_settings,
1379             floating_ip_settings=[FloatingIpSettings(
1380                 name=self.floating_ip_name, port_name=self.port_1_name,
1381                 router_name=self.pub_net_config.router_settings.name)])
1382
1383         self.inst_creator = OpenStackVmInstance(
1384             self.os_creds, instance_settings,
1385             self.image_creator.image_settings,
1386             keypair_settings=self.keypair_creator.keypair_settings)
1387
1388         vm_inst = self.inst_creator.create(block=True)
1389
1390         self.assertEqual(vm_inst, self.inst_creator.get_vm_inst())
1391
1392         # Effectively blocks until VM has been properly activated
1393         self.assertTrue(self.inst_creator.vm_active(block=True))
1394
1395         ip = self.inst_creator.get_port_ip(ports_settings[0].name)
1396         self.assertTrue(check_dhcp_lease(self.inst_creator, ip))
1397
1398         # Add security group to VM
1399         self.inst_creator.add_security_group(
1400             self.sec_grp_creator.get_security_group())
1401
1402         # Effectively blocks until VM's ssh port has been opened
1403         self.assertTrue(self.inst_creator.vm_ssh_active(block=True))
1404
1405         self.assertEqual(0, self.inst_creator.config_nics())
1406
1407
1408 class InstanceSecurityGroupTests(OSIntegrationTestCase):
1409     """
1410     Tests that include, add, and remove security groups from VM instances
1411     """
1412
1413     def setUp(self):
1414         """
1415         Instantiates the CreateImage object that is responsible for downloading
1416         and creating an OS image file within OpenStack
1417         """
1418         super(self.__class__, self).__start__()
1419
1420         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1421         self.vm_inst_name = self.guid + '-inst'
1422         self.nova = nova_utils.nova_client(self.os_creds)
1423         os_image_settings = openstack_tests.cirros_image_settings(
1424             name=self.guid + '-image', image_metadata=self.image_metadata)
1425
1426         self.vm_inst_name = self.guid + '-inst'
1427         self.port_1_name = self.guid + 'port-1'
1428         self.port_2_name = self.guid + 'port-2'
1429         self.floating_ip_name = self.guid + 'fip1'
1430
1431         net_config = openstack_tests.get_priv_net_config(
1432             net_name=self.guid + '-pub-net',
1433             subnet_name=self.guid + '-pub-subnet',
1434             router_name=self.guid + '-pub-router',
1435             external_net=self.ext_net_name)
1436
1437         # Initialize for tearDown()
1438         self.image_creator = None
1439         self.flavor_creator = None
1440         self.network_creator = None
1441         self.router_creator = None
1442         self.inst_creator = None
1443         self.sec_grp_creators = list()
1444
1445         try:
1446             # Create Image
1447             self.image_creator = OpenStackImage(self.os_creds,
1448                                                 os_image_settings)
1449             self.image_creator.create()
1450
1451             # Create Network
1452             self.network_creator = OpenStackNetwork(
1453                 self.os_creds, net_config.network_settings)
1454             self.network_creator.create()
1455
1456             # Create Flavor
1457             self.flavor_creator = OpenStackFlavor(
1458                 self.admin_os_creds,
1459                 FlavorSettings(name=self.guid + '-flavor-name', ram=128,
1460                                disk=10, vcpus=2,
1461                                metadata=self.flavor_metadata))
1462             self.flavor_creator.create()
1463
1464             self.port_settings = PortSettings(
1465                 name=self.guid + '-port',
1466                 network_name=net_config.network_settings.name)
1467         except Exception as e:
1468             self.tearDown()
1469             raise e
1470
1471     def tearDown(self):
1472         """
1473         Cleans the created object
1474         """
1475         if self.inst_creator:
1476             try:
1477                 self.inst_creator.clean()
1478             except Exception as e:
1479                 logger.error(
1480                     'Unexpected exception cleaning VM instance with message -'
1481                     ' %s', e)
1482
1483         for sec_grp_creator in self.sec_grp_creators:
1484             try:
1485                 sec_grp_creator.clean()
1486             except Exception as e:
1487                 logger.error(
1488                     'Unexpected exception cleaning security group with message'
1489                     ' - %s', e)
1490
1491         if self.flavor_creator:
1492             try:
1493                 self.flavor_creator.clean()
1494             except Exception as e:
1495                 logger.error(
1496                     'Unexpected exception cleaning flavor with message - %s',
1497                     e)
1498
1499         if self.network_creator:
1500             try:
1501                 self.network_creator.clean()
1502             except Exception as e:
1503                 logger.error(
1504                     'Unexpected exception cleaning network with message - %s',
1505                     e)
1506
1507         if self.image_creator and not self.image_creator.image_settings.exists:
1508             try:
1509                 self.image_creator.clean()
1510             except Exception as e:
1511                 logger.error(
1512                     'Unexpected exception cleaning image with message - %s', e)
1513
1514         super(self.__class__, self).__clean__()
1515
1516     def test_add_security_group(self):
1517         """
1518         Tests the addition of a security group created after the instance.
1519         """
1520         # Create instance
1521         instance_settings = VmInstanceSettings(
1522             name=self.vm_inst_name,
1523             flavor=self.flavor_creator.flavor_settings.name,
1524             port_settings=[self.port_settings])
1525         self.inst_creator = OpenStackVmInstance(
1526             self.os_creds, instance_settings,
1527             self.image_creator.image_settings)
1528         vm_inst = self.inst_creator.create(block=True)
1529         self.assertIsNotNone(vm_inst)
1530
1531         # Create security group object to add to instance
1532         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1533                                                  description='hello group')
1534         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1535                                                  sec_grp_settings)
1536         sec_grp = sec_grp_creator.create()
1537         self.sec_grp_creators.append(sec_grp_creator)
1538
1539         # Check that group has not been added
1540         self.assertFalse(inst_has_sec_grp(
1541             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1542
1543         # Add security group to instance after activated
1544         self.inst_creator.add_security_group(sec_grp)
1545
1546         # Validate that security group has been added
1547         self.assertTrue(inst_has_sec_grp(
1548             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1549
1550     def test_add_invalid_security_group(self):
1551         """
1552         Tests the addition of a security group that no longer exists.
1553         """
1554         # Create instance
1555         instance_settings = VmInstanceSettings(
1556             name=self.vm_inst_name,
1557             flavor=self.flavor_creator.flavor_settings.name,
1558             port_settings=[self.port_settings])
1559         self.inst_creator = OpenStackVmInstance(
1560             self.os_creds, instance_settings,
1561             self.image_creator.image_settings)
1562         vm_inst = self.inst_creator.create(block=True)
1563         self.assertIsNotNone(vm_inst)
1564
1565         # Create security group object to add to instance
1566         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1567                                                  description='hello group')
1568         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1569                                                  sec_grp_settings)
1570         sec_grp = sec_grp_creator.create()
1571         sec_grp_creator.clean()
1572         self.sec_grp_creators.append(sec_grp_creator)
1573
1574         # Check that group has not been added
1575         self.assertFalse(inst_has_sec_grp(
1576             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1577
1578         # Add security group to instance after activated
1579         self.assertFalse(self.inst_creator.add_security_group(sec_grp))
1580
1581         # Validate that security group has been added
1582         self.assertFalse(inst_has_sec_grp(
1583             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1584
1585     def test_remove_security_group(self):
1586         """
1587         Tests the removal of a security group created before and added to the
1588         instance.
1589         """
1590         # Create security group object to add to instance
1591         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1592                                                  description='hello group')
1593         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1594                                                  sec_grp_settings)
1595         sec_grp = sec_grp_creator.create()
1596         self.sec_grp_creators.append(sec_grp_creator)
1597
1598         # Create instance
1599         instance_settings = VmInstanceSettings(
1600             name=self.vm_inst_name,
1601             flavor=self.flavor_creator.flavor_settings.name,
1602             security_group_names=[sec_grp_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         # Check that group has been added
1611         self.assertTrue(inst_has_sec_grp(
1612             self.nova, vm_inst, sec_grp_settings.name))
1613
1614         # Add security group to instance after activated
1615         self.assertTrue(self.inst_creator.remove_security_group(sec_grp))
1616
1617         # Validate that security group has been added
1618         self.assertFalse(inst_has_sec_grp(
1619             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1620
1621     def test_remove_security_group_never_added(self):
1622         """
1623         Tests the removal of a security group that was never added in the first
1624         place.
1625         """
1626         # Create security group object to add to instance
1627         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1628                                                  description='hello group')
1629         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1630                                                  sec_grp_settings)
1631         sec_grp = sec_grp_creator.create()
1632         self.sec_grp_creators.append(sec_grp_creator)
1633
1634         # Create instance
1635         instance_settings = VmInstanceSettings(
1636             name=self.vm_inst_name,
1637             flavor=self.flavor_creator.flavor_settings.name,
1638             port_settings=[self.port_settings])
1639         self.inst_creator = OpenStackVmInstance(
1640             self.os_creds, instance_settings,
1641             self.image_creator.image_settings)
1642         vm_inst = self.inst_creator.create(block=True)
1643         self.assertIsNotNone(vm_inst)
1644
1645         # Check that group has been added
1646         self.assertFalse(inst_has_sec_grp(
1647             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1648
1649         # Add security group to instance after activated
1650         self.assertFalse(self.inst_creator.remove_security_group(sec_grp))
1651
1652         # Validate that security group has been added
1653         self.assertFalse(inst_has_sec_grp(
1654             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1655
1656     def test_add_same_security_group(self):
1657         """
1658         Tests the addition of a security group created before add added to the
1659         instance.
1660         """
1661         # Create security group object to add to instance
1662         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1663                                                  description='hello group')
1664         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1665                                                  sec_grp_settings)
1666         sec_grp = sec_grp_creator.create()
1667         self.sec_grp_creators.append(sec_grp_creator)
1668
1669         # Create instance
1670         instance_settings = VmInstanceSettings(
1671             name=self.vm_inst_name,
1672             flavor=self.flavor_creator.flavor_settings.name,
1673             security_group_names=[sec_grp_settings.name],
1674             port_settings=[self.port_settings])
1675         self.inst_creator = OpenStackVmInstance(
1676             self.os_creds, instance_settings,
1677             self.image_creator.image_settings)
1678         vm_inst = self.inst_creator.create(block=True)
1679         self.assertIsNotNone(vm_inst)
1680
1681         # Check that group has been added
1682         self.assertTrue(inst_has_sec_grp(
1683             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1684
1685         # Add security group to instance after activated
1686         self.assertTrue(self.inst_creator.add_security_group(sec_grp))
1687
1688         # Validate that security group has been added
1689         self.assertTrue(inst_has_sec_grp(
1690             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1691
1692
1693 def inst_has_sec_grp(nova, vm_inst, sec_grp_name):
1694     """
1695     Returns true if instance has a security group of a given name
1696     :param nova: the nova client
1697     :param vm_inst: the VmInst domain object
1698     :param sec_grp_name: the name of the security group to validate
1699     :return: T/F
1700     """
1701     sec_grp_names = nova_utils.get_server_security_group_names(nova, vm_inst)
1702     for name in sec_grp_names:
1703         if sec_grp_name == name:
1704             return True
1705     return False
1706
1707
1708 def validate_ssh_client(instance_creator):
1709     """
1710     Returns True if instance_creator returns an SSH client that is valid
1711     :param instance_creator: the object responsible for creating the VM
1712                              instance
1713     :return: T/F
1714     """
1715     ssh_active = instance_creator.vm_ssh_active(block=True)
1716
1717     if ssh_active:
1718         ssh_client = instance_creator.ssh_client()
1719         if ssh_client:
1720             try:
1721                 out = ssh_client.exec_command('pwd')[1]
1722             finally:
1723                 ssh_client.close()
1724         else:
1725             return False
1726
1727         channel = out.channel
1728         in_buffer = channel.in_buffer
1729         pwd_out = in_buffer.read(1024)
1730         if not pwd_out or len(pwd_out) < 10:
1731             return False
1732         return True
1733
1734     return False
1735
1736
1737 class CreateInstanceFromThreePartImage(OSIntegrationTestCase):
1738     """
1739     Test for the CreateInstance class for creating an image from a 3-part image
1740     """
1741
1742     def setUp(self):
1743         """
1744         Instantiates the CreateImage object that is responsible for downloading
1745         and creating an OS image file within OpenStack
1746         """
1747         super(self.__class__, self).__start__()
1748
1749         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1750         self.image_name = guid
1751         self.vm_inst_name = guid + '-inst'
1752         self.nova = nova_utils.nova_client(self.os_creds)
1753
1754         net_config = openstack_tests.get_priv_net_config(
1755             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
1756             router_name=guid + '-pub-router', external_net=self.ext_net_name)
1757
1758         # Initialize for tearDown()
1759         self.image_creator = None
1760         self.network_creator = None
1761         self.flavor_creator = None
1762         self.inst_creator = None
1763
1764         try:
1765             if self.image_metadata and 'disk_file' in self.image_metadata:
1766                 metadata = self.image_metadata
1767             elif self.image_metadata and 'cirros' in self.image_metadata \
1768                     and 'disk_file' in self.image_metadata['cirros']:
1769                 metadata = self.image_metadata['cirros']
1770             else:
1771                 metadata = {
1772                     'disk_url': openstack_tests.CIRROS_DEFAULT_IMAGE_URL,
1773                     'kernel_url':
1774                         openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL,
1775                     'ramdisk_url':
1776                         openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL}
1777
1778             image_settings = openstack_tests.cirros_image_settings(
1779                 name=self.image_name,
1780                 image_metadata=metadata)
1781
1782             if not image_settings.ramdisk_image_settings or not \
1783                     image_settings.kernel_image_settings:
1784                 logger.warn(
1785                     '3 Part image will not be tested. Image metadata has '
1786                     'overridden this functionality')
1787
1788             self.image_creator = OpenStackImage(self.os_creds, image_settings)
1789             self.image_creator.create()
1790
1791             # Create Flavor
1792             self.flavor_creator = OpenStackFlavor(
1793                 self.admin_os_creds,
1794                 FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
1795                                vcpus=2, metadata=self.flavor_metadata))
1796             self.flavor_creator.create()
1797
1798             # Create Network
1799             self.network_creator = OpenStackNetwork(
1800                 self.os_creds, net_config.network_settings)
1801             self.network_creator.create()
1802
1803             self.port_settings = PortSettings(
1804                 name=guid + '-port',
1805                 network_name=net_config.network_settings.name)
1806         except Exception as e:
1807             self.tearDown()
1808             raise e
1809
1810     def tearDown(self):
1811         """
1812         Cleans the created object
1813         """
1814         if self.inst_creator:
1815             try:
1816                 self.inst_creator.clean()
1817             except Exception as e:
1818                 logger.error(
1819                     'Unexpected exception cleaning VM instance with message -'
1820                     ' %s', e)
1821
1822         if self.flavor_creator:
1823             try:
1824                 self.flavor_creator.clean()
1825             except Exception as e:
1826                 logger.error(
1827                     'Unexpected exception cleaning flavor with message - %s',
1828                     e)
1829
1830         if self.network_creator:
1831             try:
1832                 self.network_creator.clean()
1833             except Exception as e:
1834                 logger.error(
1835                     'Unexpected exception cleaning network with message - %s',
1836                     e)
1837
1838         if self.image_creator and not self.image_creator.image_settings.exists:
1839             try:
1840                 self.image_creator.clean()
1841             except Exception as e:
1842                 logger.error(
1843                     'Unexpected exception cleaning image with message - %s', e)
1844
1845         super(self.__class__, self).__clean__()
1846
1847     def test_create_instance_from_three_part_image(self):
1848         """
1849         Tests the creation of an OpenStack instance from a 3-part image.
1850         """
1851         instance_settings = VmInstanceSettings(
1852             name=self.vm_inst_name,
1853             flavor=self.flavor_creator.flavor_settings.name,
1854             port_settings=[self.port_settings])
1855
1856         # The last created image is the main image from which we create the
1857         # instance
1858         self.inst_creator = OpenStackVmInstance(
1859             self.os_creds, instance_settings,
1860             self.image_creator.image_settings)
1861
1862         vm_inst = self.inst_creator.create()
1863         self.assertIsNotNone(vm_inst)
1864         self.assertTrue(self.inst_creator.vm_active(block=True))
1865
1866
1867 class CreateInstanceMockOfflineTests(OSComponentTestCase):
1868     """
1869     Tests the custom image_metadata that can be set by clients for handling
1870     images differently than the default behavior of the existing tests
1871     primarily for offline testing
1872     """
1873
1874     def setUp(self):
1875         """
1876         Instantiates the CreateImage object that is responsible for downloading
1877         and creating an OS image file within OpenStack
1878         """
1879         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1880
1881         self.tmpDir = 'tmp/' + str(self.guid)
1882         if not os.path.exists(self.tmpDir):
1883             os.makedirs(self.tmpDir)
1884
1885         self.image_name = self.guid + '-image'
1886         self.vm_inst_name = self.guid + '-inst'
1887         self.port_1_name = self.guid + 'port-1'
1888
1889         # Initialize for tearDown()
1890         self.image_creator = None
1891         self.network_creator = None
1892         self.flavor_creator = None
1893         self.inst_creator = None
1894
1895         self.priv_net_config = openstack_tests.get_priv_net_config(
1896             net_name=self.guid + '-priv-net',
1897             subnet_name=self.guid + '-priv-subnet')
1898         self.port_settings = PortSettings(
1899             name=self.port_1_name,
1900             network_name=self.priv_net_config.network_settings.name)
1901
1902         try:
1903             # Download image file
1904             self.image_file = file_utils.download(
1905                 openstack_tests.CIRROS_DEFAULT_IMAGE_URL, self.tmpDir)
1906
1907             # Create Network
1908             self.network_creator = OpenStackNetwork(
1909                 self.os_creds, self.priv_net_config.network_settings)
1910             self.network_creator.create()
1911
1912             # Create Flavor
1913             self.flavor_creator = OpenStackFlavor(
1914                 self.os_creds,
1915                 FlavorSettings(
1916                     name=self.guid + '-flavor-name', ram=128, disk=10,
1917                     vcpus=1))
1918             self.flavor_creator.create()
1919         except Exception as e:
1920             self.tearDown()
1921             raise e
1922
1923     def tearDown(self):
1924         """
1925         Cleans the created object
1926         """
1927         if self.inst_creator:
1928             try:
1929                 self.inst_creator.clean()
1930             except Exception as e:
1931                 logger.error(
1932                     'Unexpected exception cleaning VM instance with message - '
1933                     '%s', e)
1934
1935         if self.network_creator:
1936             try:
1937                 self.network_creator.clean()
1938             except Exception as e:
1939                 logger.error(
1940                     'Unexpected exception cleaning network with message - %s',
1941                     e)
1942
1943         if self.flavor_creator:
1944             try:
1945                 self.flavor_creator.clean()
1946             except Exception as e:
1947                 logger.error(
1948                     'Unexpected exception cleaning flavor with message - %s',
1949                     e)
1950
1951         if self.image_creator:
1952             try:
1953                 self.image_creator.clean()
1954             except Exception as e:
1955                 logger.error(
1956                     'Unexpected exception cleaning image with message - %s', e)
1957
1958         if os.path.exists(self.tmpDir) and os.path.isdir(self.tmpDir):
1959             shutil.rmtree(self.tmpDir)
1960
1961     def test_inst_from_file_image_simple_flat(self):
1962         """
1963         Creates a VM instance from a locally sourced file image using simply
1964         the 'disk_file' attribute vs. using the 'config' option which
1965         completely overrides all image settings
1966         :return: 
1967         """
1968         metadata = {'disk_file': self.image_file.name}
1969
1970         os_image_settings = openstack_tests.cirros_image_settings(
1971             name=self.image_name, image_metadata=metadata)
1972         self.assertEqual(self.image_file.name, os_image_settings.image_file)
1973         self.assertEqual(openstack_tests.CIRROS_USER,
1974                          os_image_settings.image_user)
1975         self.assertIsNone(os_image_settings.url)
1976         self.assertFalse(os_image_settings.exists)
1977         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
1978                          os_image_settings.format)
1979
1980         self.assertIsNone(os_image_settings.kernel_image_settings)
1981         self.assertIsNone(os_image_settings.ramdisk_image_settings)
1982
1983         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
1984         self.image_creator.create()
1985
1986         instance_settings = VmInstanceSettings(
1987             name=self.vm_inst_name,
1988             flavor=self.flavor_creator.flavor_settings.name,
1989             port_settings=[self.port_settings])
1990         self.inst_creator = OpenStackVmInstance(
1991             self.os_creds, instance_settings,
1992             self.image_creator.image_settings)
1993         self.inst_creator.create()
1994
1995         self.assertTrue(self.inst_creator.vm_active(block=True))
1996
1997     def test_inst_from_file_image_simple_nested(self):
1998         """
1999         Creates a VM instance from a locally sourced file image using simply
2000         the 'disk_file' attribute under 'cirros' vs. using the 'config' option
2001         which completely overrides all image settings
2002         :return: 
2003         """
2004         metadata = {'cirros': {'disk_file': self.image_file.name}}
2005
2006         os_image_settings = openstack_tests.cirros_image_settings(
2007             name=self.image_name, image_metadata=metadata)
2008         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2009         self.assertEqual(openstack_tests.CIRROS_USER,
2010                          os_image_settings.image_user)
2011         self.assertIsNone(os_image_settings.url)
2012         self.assertFalse(os_image_settings.exists)
2013         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2014                          os_image_settings.format)
2015
2016         self.assertIsNone(os_image_settings.kernel_image_settings)
2017         self.assertIsNone(os_image_settings.ramdisk_image_settings)
2018
2019         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2020         self.image_creator.create()
2021
2022         instance_settings = VmInstanceSettings(
2023             name=self.vm_inst_name,
2024             flavor=self.flavor_creator.flavor_settings.name,
2025             port_settings=[self.port_settings])
2026         self.inst_creator = OpenStackVmInstance(
2027             self.os_creds, instance_settings,
2028             self.image_creator.image_settings)
2029         self.inst_creator.create()
2030
2031         self.assertTrue(self.inst_creator.vm_active(block=True))
2032
2033     def test_inst_from_existing(self):
2034         """
2035         Creates a VM instance from a image creator that has been configured to
2036         use an existing image
2037         :return: 
2038         """
2039         os_image_settings = openstack_tests.cirros_image_settings(
2040             name=self.image_name)
2041         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2042         self.image_creator.create()
2043
2044         image_settings = self.image_creator.image_settings
2045         test_image_creator = OpenStackImage(
2046             self.os_creds,
2047             ImageSettings(name=image_settings.name,
2048                           image_user=image_settings.image_user,
2049                           exists=True))
2050         test_image_creator.create()
2051         self.assertEqual(self.image_creator.get_image().id,
2052                          test_image_creator.get_image().id)
2053
2054         instance_settings = VmInstanceSettings(
2055             name=self.vm_inst_name,
2056             flavor=self.flavor_creator.flavor_settings.name,
2057             port_settings=[self.port_settings])
2058         self.inst_creator = OpenStackVmInstance(
2059             self.os_creds, instance_settings,
2060             test_image_creator.image_settings)
2061         self.inst_creator.create()
2062
2063         self.assertTrue(self.inst_creator.vm_active(block=True))
2064
2065     def test_inst_from_file_image_complex(self):
2066         """
2067         Creates a VM instance from a locally sourced file image by overriding
2068         the default settings by using a dict() that can be read in by
2069         ImageSettings
2070         :return: 
2071         """
2072
2073         os_image_settings = openstack_tests.cirros_image_settings(
2074             name=self.image_name)
2075         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2076         self.image_creator.create()
2077
2078         metadata = {
2079             'cirros': {
2080                 'config': {
2081                     'name': os_image_settings.name,
2082                     'image_user': os_image_settings.image_user,
2083                     'exists': True}}}
2084         test_image_settings = openstack_tests.cirros_image_settings(
2085             image_metadata=metadata)
2086         test_image = OpenStackImage(self.os_creds, test_image_settings)
2087         test_image.create()
2088
2089         instance_settings = VmInstanceSettings(
2090             name=self.vm_inst_name,
2091             flavor=self.flavor_creator.flavor_settings.name,
2092             port_settings=[self.port_settings])
2093         self.inst_creator = OpenStackVmInstance(self.os_creds,
2094                                                 instance_settings,
2095                                                 test_image_settings)
2096         self.inst_creator.create()
2097
2098         self.assertTrue(self.inst_creator.vm_active(block=True))
2099
2100     def test_inst_from_file_3part_image_complex(self):
2101         """
2102         Creates a VM instance from a locally sourced file image by overriding
2103         the default settings by using a dict() that can be read in by
2104         ImageSettings
2105         :return: 
2106         """
2107
2108         kernel_file = file_utils.download(
2109             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2110         ramdisk_file = file_utils.download(
2111             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2112
2113         metadata = {
2114             'cirros': {
2115                 'config': {
2116                     'name': self.image_name,
2117                     'image_user': openstack_tests.CIRROS_USER,
2118                     'image_file': self.image_file.name,
2119                     'format': openstack_tests.DEFAULT_IMAGE_FORMAT,
2120                     'kernel_image_settings': {
2121                         'name': self.image_name + '-kernel',
2122                         'image_user': openstack_tests.CIRROS_USER,
2123                         'image_file': kernel_file.name,
2124                         'format': openstack_tests.DEFAULT_IMAGE_FORMAT},
2125                     'ramdisk_image_settings': {
2126                         'name': self.image_name + '-ramdisk',
2127                         'image_user': openstack_tests.CIRROS_USER,
2128                         'image_file': ramdisk_file.name,
2129                         'format': openstack_tests.DEFAULT_IMAGE_FORMAT}}}}
2130
2131         os_image_settings = openstack_tests.cirros_image_settings(
2132             name=self.image_name, image_metadata=metadata)
2133         self.assertEqual(self.image_name, os_image_settings.name)
2134         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2135         self.assertEqual(openstack_tests.CIRROS_USER,
2136                          os_image_settings.image_user)
2137         self.assertIsNone(os_image_settings.url)
2138         self.assertFalse(os_image_settings.exists)
2139         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2140                          os_image_settings.format)
2141
2142         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2143         self.assertEqual(self.image_name + '-kernel',
2144                          os_image_settings.kernel_image_settings.name)
2145         self.assertEqual(kernel_file.name,
2146                          os_image_settings.kernel_image_settings.image_file)
2147         self.assertEqual(openstack_tests.CIRROS_USER,
2148                          os_image_settings.kernel_image_settings.image_user)
2149         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2150         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2151         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2152                          os_image_settings.kernel_image_settings.format)
2153
2154         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2155         self.assertEqual(self.image_name + '-ramdisk',
2156                          os_image_settings.ramdisk_image_settings.name)
2157         self.assertEqual(ramdisk_file.name,
2158                          os_image_settings.ramdisk_image_settings.image_file)
2159         self.assertEqual(openstack_tests.CIRROS_USER,
2160                          os_image_settings.ramdisk_image_settings.image_user)
2161         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2162         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2163         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2164                          os_image_settings.ramdisk_image_settings.format)
2165
2166         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2167         self.image_creator.create()
2168
2169         instance_settings = VmInstanceSettings(
2170             name=self.vm_inst_name,
2171             flavor=self.flavor_creator.flavor_settings.name,
2172             port_settings=[self.port_settings])
2173         self.inst_creator = OpenStackVmInstance(
2174             self.os_creds, instance_settings,
2175             self.image_creator.image_settings)
2176         self.inst_creator.create()
2177
2178         self.assertTrue(self.inst_creator.vm_active(block=True))
2179
2180     def test_inst_from_file_3part_image_simple_flat(self):
2181         """
2182         Creates a VM instance from a 3-part image locally sourced from file
2183         images using simply the 'disk_file', 'kernel_file', and 'ramdisk_file'
2184         attributes vs. using the 'config' option which completely overrides all
2185         image settings
2186         :return: 
2187         """
2188         kernel_file = file_utils.download(
2189             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2190         ramdisk_file = file_utils.download(
2191             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2192
2193         metadata = {'disk_file': self.image_file.name,
2194                     'kernel_file': kernel_file.name,
2195                     'ramdisk_file': ramdisk_file.name}
2196
2197         os_image_settings = openstack_tests.cirros_image_settings(
2198             name=self.image_name, image_metadata=metadata)
2199
2200         self.assertEqual(self.image_name, os_image_settings.name)
2201         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2202         self.assertEqual(openstack_tests.CIRROS_USER,
2203                          os_image_settings.image_user)
2204         self.assertIsNone(os_image_settings.url)
2205         self.assertFalse(os_image_settings.exists)
2206         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2207                          os_image_settings.format)
2208
2209         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2210         self.assertEqual(self.image_name + '-kernel',
2211                          os_image_settings.kernel_image_settings.name)
2212         self.assertEqual(kernel_file.name,
2213                          os_image_settings.kernel_image_settings.image_file)
2214         self.assertEqual(openstack_tests.CIRROS_USER,
2215                          os_image_settings.kernel_image_settings.image_user)
2216         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2217         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2218         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2219                          os_image_settings.kernel_image_settings.format)
2220
2221         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2222         self.assertEqual(self.image_name + '-ramdisk',
2223                          os_image_settings.ramdisk_image_settings.name)
2224         self.assertEqual(ramdisk_file.name,
2225                          os_image_settings.ramdisk_image_settings.image_file)
2226         self.assertEqual(openstack_tests.CIRROS_USER,
2227                          os_image_settings.ramdisk_image_settings.image_user)
2228         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2229         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2230         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2231                          os_image_settings.ramdisk_image_settings.format)
2232
2233         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2234         self.image_creator.create()
2235
2236         self.assertIsNotNone(self.image_creator.get_kernel_image())
2237         self.assertIsNotNone(self.image_creator.get_ramdisk_image())
2238
2239         instance_settings = VmInstanceSettings(
2240             name=self.vm_inst_name,
2241             flavor=self.flavor_creator.flavor_settings.name,
2242             port_settings=[self.port_settings])
2243         self.inst_creator = OpenStackVmInstance(
2244             self.os_creds, instance_settings,
2245             self.image_creator.image_settings)
2246         self.inst_creator.create()
2247
2248         self.assertTrue(self.inst_creator.vm_active(block=True))
2249
2250     def test_inst_from_file_3part_image_simple_nested(self):
2251         """
2252         Creates a VM instance from a 3-part image locally sourced from file
2253         images using simply the 'disk_file', 'kernel_file', and 'ramdisk_file'
2254         attributes under 'cirros' vs. using the 'config' option which
2255         completely overrides all image settings
2256         :return: 
2257         """
2258         kernel_file = file_utils.download(
2259             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2260         ramdisk_file = file_utils.download(
2261             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2262
2263         metadata = {'cirros': {'disk_file': self.image_file.name,
2264                                'kernel_file': kernel_file.name,
2265                                'ramdisk_file': ramdisk_file.name}}
2266
2267         os_image_settings = openstack_tests.cirros_image_settings(
2268             name=self.image_name, image_metadata=metadata)
2269
2270         self.assertEqual(self.image_name, os_image_settings.name)
2271         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2272         self.assertEqual(openstack_tests.CIRROS_USER,
2273                          os_image_settings.image_user)
2274         self.assertIsNone(os_image_settings.url)
2275         self.assertFalse(os_image_settings.exists)
2276         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2277                          os_image_settings.format)
2278
2279         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2280         self.assertEqual(self.image_name + '-kernel',
2281                          os_image_settings.kernel_image_settings.name)
2282         self.assertEqual(kernel_file.name,
2283                          os_image_settings.kernel_image_settings.image_file)
2284         self.assertEqual(openstack_tests.CIRROS_USER,
2285                          os_image_settings.kernel_image_settings.image_user)
2286         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2287         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2288         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2289                          os_image_settings.kernel_image_settings.format)
2290
2291         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2292         self.assertEqual(self.image_name + '-ramdisk',
2293                          os_image_settings.ramdisk_image_settings.name)
2294         self.assertEqual(ramdisk_file.name,
2295                          os_image_settings.ramdisk_image_settings.image_file)
2296         self.assertEqual(openstack_tests.CIRROS_USER,
2297                          os_image_settings.ramdisk_image_settings.image_user)
2298         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2299         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2300         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2301                          os_image_settings.ramdisk_image_settings.format)
2302
2303         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2304         self.image_creator.create()
2305
2306         self.assertIsNotNone(self.image_creator.get_kernel_image())
2307         self.assertIsNotNone(self.image_creator.get_ramdisk_image())
2308
2309         instance_settings = VmInstanceSettings(
2310             name=self.vm_inst_name,
2311             flavor=self.flavor_creator.flavor_settings.name,
2312             port_settings=[self.port_settings])
2313         self.inst_creator = OpenStackVmInstance(
2314             self.os_creds, instance_settings,
2315             self.image_creator.image_settings)
2316         self.inst_creator.create()
2317
2318         self.assertTrue(self.inst_creator.vm_active(block=True))
2319
2320     def test_inst_from_file_3part_image_existing(self):
2321         """
2322         Creates a VM instance from a 3-part image that is existing
2323         :return: 
2324         """
2325         kernel_file = file_utils.download(
2326             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2327         ramdisk_file = file_utils.download(
2328             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2329
2330         metadata = {'cirros': {'disk_file': self.image_file.name,
2331                                'kernel_file': kernel_file.name,
2332                                'ramdisk_file': ramdisk_file.name}}
2333
2334         os_image_settings = openstack_tests.cirros_image_settings(
2335             name=self.image_name, image_metadata=metadata)
2336         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2337         self.image_creator.create()
2338
2339         image_settings = self.image_creator.image_settings
2340         test_image_creator = OpenStackImage(
2341             self.os_creds,
2342             ImageSettings(name=image_settings.name,
2343                           image_user=image_settings.image_user,
2344                           exists=True))
2345         test_image_creator.create()
2346         self.assertEqual(self.image_creator.get_image().id,
2347                          test_image_creator.get_image().id)
2348
2349         instance_settings = VmInstanceSettings(
2350             name=self.vm_inst_name,
2351             flavor=self.flavor_creator.flavor_settings.name,
2352             port_settings=[self.port_settings])
2353         self.inst_creator = OpenStackVmInstance(
2354             self.os_creds, instance_settings,
2355             test_image_creator.image_settings)
2356         self.inst_creator.create()
2357
2358         self.assertTrue(self.inst_creator.vm_active(block=True))
2359
2360
2361 def check_dhcp_lease(inst_creator, ip, timeout=160):
2362     """
2363     Returns true if the expected DHCP lease has been acquired
2364     :param inst_creator: the SNAPS OpenStackVmInstance object
2365     :param ip: the IP address to look for
2366     :param timeout: how long to query for IP address
2367     :return:
2368     """
2369     found = False
2370     start_time = time.time()
2371
2372     logger.info("Looking for IP %s in the console log" % ip)
2373     full_log = ''
2374     while timeout > time.time() - start_time:
2375         output = inst_creator.get_console_output()
2376         full_log = full_log + output
2377         if re.search(ip, output):
2378             logger.info('DHCP lease obtained logged in console')
2379             found = True
2380             break
2381
2382     if not found:
2383         logger.error('Full console output -\n' + full_log)
2384     else:
2385         logger.debug('Full console output -\n' + full_log)
2386
2387     return found