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