Created domain class for ports.
[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         vm = 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.nova, vm, 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(self.nova, vm_inst, 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(self.nova, vm_inst, 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             vm = creator.get_os_vm_server_obj()
1171             deployed_zone = vm._info['OS-EXT-AZ:availability_zone']
1172             deployed_host = vm._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 Exception as e:
1280             self.tearDown()
1281             raise Exception(str(e))
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.nova, vm_inst, 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         # TODO - Refactor config_nics() to return a status that can be
1404         # validated here.
1405         self.inst_creator.config_nics()
1406
1407         # TODO - *** ADD VALIDATION HERE ***
1408         # TODO - Add validation that both floating IPs work
1409         # TODO - Add tests where only one NIC has a floating IP
1410         # TODO - Add tests where one attempts to place a floating IP on a
1411         # network/router without an external gateway
1412
1413
1414 class InstanceSecurityGroupTests(OSIntegrationTestCase):
1415     """
1416     Tests that include, add, and remove security groups from VM instances
1417     """
1418
1419     def setUp(self):
1420         """
1421         Instantiates the CreateImage object that is responsible for downloading
1422         and creating an OS image file within OpenStack
1423         """
1424         super(self.__class__, self).__start__()
1425
1426         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1427         self.vm_inst_name = self.guid + '-inst'
1428         self.nova = nova_utils.nova_client(self.os_creds)
1429         os_image_settings = openstack_tests.cirros_image_settings(
1430             name=self.guid + '-image', image_metadata=self.image_metadata)
1431
1432         self.vm_inst_name = self.guid + '-inst'
1433         self.port_1_name = self.guid + 'port-1'
1434         self.port_2_name = self.guid + 'port-2'
1435         self.floating_ip_name = self.guid + 'fip1'
1436
1437         net_config = openstack_tests.get_priv_net_config(
1438             net_name=self.guid + '-pub-net',
1439             subnet_name=self.guid + '-pub-subnet',
1440             router_name=self.guid + '-pub-router',
1441             external_net=self.ext_net_name)
1442
1443         # Initialize for tearDown()
1444         self.image_creator = None
1445         self.flavor_creator = None
1446         self.network_creator = None
1447         self.router_creator = None
1448         self.inst_creator = None
1449         self.sec_grp_creators = list()
1450
1451         try:
1452             # Create Image
1453             self.image_creator = OpenStackImage(self.os_creds,
1454                                                 os_image_settings)
1455             self.image_creator.create()
1456
1457             # Create Network
1458             self.network_creator = OpenStackNetwork(
1459                 self.os_creds, net_config.network_settings)
1460             self.network_creator.create()
1461
1462             # Create Flavor
1463             self.flavor_creator = OpenStackFlavor(
1464                 self.admin_os_creds,
1465                 FlavorSettings(name=self.guid + '-flavor-name', ram=128,
1466                                disk=10, vcpus=2,
1467                                metadata=self.flavor_metadata))
1468             self.flavor_creator.create()
1469
1470             self.port_settings = PortSettings(
1471                 name=self.guid + '-port',
1472                 network_name=net_config.network_settings.name)
1473         except Exception as e:
1474             self.tearDown()
1475             raise e
1476
1477     def tearDown(self):
1478         """
1479         Cleans the created object
1480         """
1481         if self.inst_creator:
1482             try:
1483                 self.inst_creator.clean()
1484             except Exception as e:
1485                 logger.error(
1486                     'Unexpected exception cleaning VM instance with message -'
1487                     ' %s', e)
1488
1489         for sec_grp_creator in self.sec_grp_creators:
1490             try:
1491                 sec_grp_creator.clean()
1492             except Exception as e:
1493                 logger.error(
1494                     'Unexpected exception cleaning security group with message'
1495                     ' - %s', e)
1496
1497         if self.flavor_creator:
1498             try:
1499                 self.flavor_creator.clean()
1500             except Exception as e:
1501                 logger.error(
1502                     'Unexpected exception cleaning flavor with message - %s',
1503                     e)
1504
1505         if self.network_creator:
1506             try:
1507                 self.network_creator.clean()
1508             except Exception as e:
1509                 logger.error(
1510                     'Unexpected exception cleaning network with message - %s',
1511                     e)
1512
1513         if self.image_creator and not self.image_creator.image_settings.exists:
1514             try:
1515                 self.image_creator.clean()
1516             except Exception as e:
1517                 logger.error(
1518                     'Unexpected exception cleaning image with message - %s', e)
1519
1520         super(self.__class__, self).__clean__()
1521
1522     def test_add_security_group(self):
1523         """
1524         Tests the addition of a security group created after the instance.
1525         """
1526         # Create instance
1527         instance_settings = VmInstanceSettings(
1528             name=self.vm_inst_name,
1529             flavor=self.flavor_creator.flavor_settings.name,
1530             port_settings=[self.port_settings])
1531         self.inst_creator = OpenStackVmInstance(
1532             self.os_creds, instance_settings,
1533             self.image_creator.image_settings)
1534         vm_inst = self.inst_creator.create(block=True)
1535         self.assertIsNotNone(vm_inst)
1536
1537         # Create security group object to add to instance
1538         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1539                                                  description='hello group')
1540         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1541                                                  sec_grp_settings)
1542         sec_grp = sec_grp_creator.create()
1543         self.sec_grp_creators.append(sec_grp_creator)
1544
1545         # Check that group has not been added
1546         self.assertFalse(inst_has_sec_grp(
1547             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1548
1549         # Add security group to instance after activated
1550         self.inst_creator.add_security_group(sec_grp)
1551
1552         # Validate that security group has been added
1553         self.assertTrue(inst_has_sec_grp(
1554             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1555
1556     def test_add_invalid_security_group(self):
1557         """
1558         Tests the addition of a security group that no longer exists.
1559         """
1560         # Create instance
1561         instance_settings = VmInstanceSettings(
1562             name=self.vm_inst_name,
1563             flavor=self.flavor_creator.flavor_settings.name,
1564             port_settings=[self.port_settings])
1565         self.inst_creator = OpenStackVmInstance(
1566             self.os_creds, instance_settings,
1567             self.image_creator.image_settings)
1568         vm_inst = self.inst_creator.create(block=True)
1569         self.assertIsNotNone(vm_inst)
1570
1571         # Create security group object to add to instance
1572         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1573                                                  description='hello group')
1574         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1575                                                  sec_grp_settings)
1576         sec_grp = sec_grp_creator.create()
1577         sec_grp_creator.clean()
1578         self.sec_grp_creators.append(sec_grp_creator)
1579
1580         # Check that group has not been added
1581         self.assertFalse(inst_has_sec_grp(
1582             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1583
1584         # Add security group to instance after activated
1585         self.assertFalse(self.inst_creator.add_security_group(sec_grp))
1586
1587         # Validate that security group has been added
1588         self.assertFalse(inst_has_sec_grp(
1589             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1590
1591     def test_remove_security_group(self):
1592         """
1593         Tests the removal of a security group created before and added to the
1594         instance.
1595         """
1596         # Create security group object to add to instance
1597         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1598                                                  description='hello group')
1599         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1600                                                  sec_grp_settings)
1601         sec_grp = sec_grp_creator.create()
1602         self.sec_grp_creators.append(sec_grp_creator)
1603
1604         # Create instance
1605         instance_settings = VmInstanceSettings(
1606             name=self.vm_inst_name,
1607             flavor=self.flavor_creator.flavor_settings.name,
1608             security_group_names=[sec_grp_settings.name],
1609             port_settings=[self.port_settings])
1610         self.inst_creator = OpenStackVmInstance(
1611             self.os_creds, instance_settings,
1612             self.image_creator.image_settings)
1613         vm_inst = self.inst_creator.create(block=True)
1614         self.assertIsNotNone(vm_inst)
1615
1616         # Check that group has been added
1617         self.assertTrue(inst_has_sec_grp(
1618             self.nova, vm_inst, sec_grp_settings.name))
1619
1620         # Add security group to instance after activated
1621         self.assertTrue(self.inst_creator.remove_security_group(sec_grp))
1622
1623         # Validate that security group has been added
1624         self.assertFalse(inst_has_sec_grp(
1625             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1626
1627     def test_remove_security_group_never_added(self):
1628         """
1629         Tests the removal of a security group that was never added in the first
1630         place.
1631         """
1632         # Create security group object to add to instance
1633         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1634                                                  description='hello group')
1635         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1636                                                  sec_grp_settings)
1637         sec_grp = sec_grp_creator.create()
1638         self.sec_grp_creators.append(sec_grp_creator)
1639
1640         # Create instance
1641         instance_settings = VmInstanceSettings(
1642             name=self.vm_inst_name,
1643             flavor=self.flavor_creator.flavor_settings.name,
1644             port_settings=[self.port_settings])
1645         self.inst_creator = OpenStackVmInstance(
1646             self.os_creds, instance_settings,
1647             self.image_creator.image_settings)
1648         vm_inst = self.inst_creator.create(block=True)
1649         self.assertIsNotNone(vm_inst)
1650
1651         # Check that group has been added
1652         self.assertFalse(inst_has_sec_grp(
1653             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1654
1655         # Add security group to instance after activated
1656         self.assertFalse(self.inst_creator.remove_security_group(sec_grp))
1657
1658         # Validate that security group has been added
1659         self.assertFalse(inst_has_sec_grp(
1660             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1661
1662     def test_add_same_security_group(self):
1663         """
1664         Tests the addition of a security group created before add added to the
1665         instance.
1666         """
1667         # Create security group object to add to instance
1668         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1669                                                  description='hello group')
1670         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1671                                                  sec_grp_settings)
1672         sec_grp = sec_grp_creator.create()
1673         self.sec_grp_creators.append(sec_grp_creator)
1674
1675         # Create instance
1676         instance_settings = VmInstanceSettings(
1677             name=self.vm_inst_name,
1678             flavor=self.flavor_creator.flavor_settings.name,
1679             security_group_names=[sec_grp_settings.name],
1680             port_settings=[self.port_settings])
1681         self.inst_creator = OpenStackVmInstance(
1682             self.os_creds, instance_settings,
1683             self.image_creator.image_settings)
1684         vm_inst = self.inst_creator.create(block=True)
1685         self.assertIsNotNone(vm_inst)
1686
1687         # Check that group has been added
1688         self.assertTrue(inst_has_sec_grp(
1689             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1690
1691         # Add security group to instance after activated
1692         self.assertTrue(self.inst_creator.add_security_group(sec_grp))
1693
1694         # Validate that security group has been added
1695         self.assertTrue(inst_has_sec_grp(
1696             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1697
1698
1699 def inst_has_sec_grp(nova, vm_inst, sec_grp_name):
1700     """
1701     Returns true if instance has a security group of a given name
1702     :param nova: the nova client
1703     :param vm_inst: the VmInst domain object
1704     :param sec_grp_name: the name of the security group to validate
1705     :return:
1706     """
1707     vm = nova_utils.get_latest_server_os_object(nova, vm_inst)
1708     if not hasattr(vm, 'security_groups'):
1709         return False
1710
1711     found = False
1712     for sec_grp_dict in vm.security_groups:
1713         if sec_grp_name in sec_grp_dict['name']:
1714             found = True
1715             break
1716     return found
1717
1718
1719 def validate_ssh_client(instance_creator):
1720     """
1721     Returns True if instance_creator returns an SSH client that is valid
1722     :param instance_creator: the object responsible for creating the VM
1723                              instance
1724     :return: T/F
1725     """
1726     ssh_active = instance_creator.vm_ssh_active(block=True)
1727
1728     if ssh_active:
1729         ssh_client = instance_creator.ssh_client()
1730         if ssh_client:
1731             out = ssh_client.exec_command('pwd')[1]
1732         else:
1733             return False
1734
1735         channel = out.channel
1736         in_buffer = channel.in_buffer
1737         pwd_out = in_buffer.read(1024)
1738         if not pwd_out or len(pwd_out) < 10:
1739             return False
1740         return True
1741
1742     return False
1743
1744
1745 class CreateInstanceFromThreePartImage(OSIntegrationTestCase):
1746     """
1747     Test for the CreateInstance class for creating an image from a 3-part image
1748     """
1749
1750     def setUp(self):
1751         """
1752         Instantiates the CreateImage object that is responsible for downloading
1753         and creating an OS image file within OpenStack
1754         """
1755         super(self.__class__, self).__start__()
1756
1757         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1758         self.image_name = guid
1759         self.vm_inst_name = guid + '-inst'
1760         self.nova = nova_utils.nova_client(self.os_creds)
1761
1762         net_config = openstack_tests.get_priv_net_config(
1763             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
1764             router_name=guid + '-pub-router', external_net=self.ext_net_name)
1765
1766         # Initialize for tearDown()
1767         self.image_creator = None
1768         self.network_creator = None
1769         self.flavor_creator = None
1770         self.inst_creator = None
1771
1772         try:
1773             if self.image_metadata and 'disk_file' in self.image_metadata:
1774                 metadata = self.image_metadata
1775             elif self.image_metadata and 'cirros' in self.image_metadata \
1776                     and 'disk_file' in self.image_metadata['cirros']:
1777                 metadata = self.image_metadata['cirros']
1778             else:
1779                 metadata = {
1780                     'disk_url': openstack_tests.CIRROS_DEFAULT_IMAGE_URL,
1781                     'kernel_url':
1782                         openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL,
1783                     'ramdisk_url':
1784                         openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL}
1785
1786             image_settings = openstack_tests.cirros_image_settings(
1787                 name=self.image_name,
1788                 image_metadata=metadata)
1789
1790             if not image_settings.ramdisk_image_settings or not \
1791                     image_settings.kernel_image_settings:
1792                 logger.warn(
1793                     '3 Part image will not be tested. Image metadata has '
1794                     'overridden this functionality')
1795
1796             self.image_creator = OpenStackImage(self.os_creds, image_settings)
1797             self.image_creator.create()
1798
1799             # Create Flavor
1800             self.flavor_creator = OpenStackFlavor(
1801                 self.admin_os_creds,
1802                 FlavorSettings(name=guid + '-flavor-name', ram=128, disk=10,
1803                                vcpus=2, metadata=self.flavor_metadata))
1804             self.flavor_creator.create()
1805
1806             # Create Network
1807             self.network_creator = OpenStackNetwork(
1808                 self.os_creds, net_config.network_settings)
1809             self.network_creator.create()
1810
1811             self.port_settings = PortSettings(
1812                 name=guid + '-port',
1813                 network_name=net_config.network_settings.name)
1814         except Exception as e:
1815             self.tearDown()
1816             raise e
1817
1818     def tearDown(self):
1819         """
1820         Cleans the created object
1821         """
1822         if self.inst_creator:
1823             try:
1824                 self.inst_creator.clean()
1825             except Exception as e:
1826                 logger.error(
1827                     'Unexpected exception cleaning VM instance with message -'
1828                     ' %s', e)
1829
1830         if self.flavor_creator:
1831             try:
1832                 self.flavor_creator.clean()
1833             except Exception as e:
1834                 logger.error(
1835                     'Unexpected exception cleaning flavor with message - %s',
1836                     e)
1837
1838         if self.network_creator:
1839             try:
1840                 self.network_creator.clean()
1841             except Exception as e:
1842                 logger.error(
1843                     'Unexpected exception cleaning network with message - %s',
1844                     e)
1845
1846         if self.image_creator and not self.image_creator.image_settings.exists:
1847             try:
1848                 self.image_creator.clean()
1849             except Exception as e:
1850                 logger.error(
1851                     'Unexpected exception cleaning image with message - %s', e)
1852
1853         super(self.__class__, self).__clean__()
1854
1855     def test_create_instance_from_three_part_image(self):
1856         """
1857         Tests the creation of an OpenStack instance from a 3-part image.
1858         """
1859         instance_settings = VmInstanceSettings(
1860             name=self.vm_inst_name,
1861             flavor=self.flavor_creator.flavor_settings.name,
1862             port_settings=[self.port_settings])
1863
1864         # The last created image is the main image from which we create the
1865         # instance
1866         self.inst_creator = OpenStackVmInstance(
1867             self.os_creds, instance_settings,
1868             self.image_creator.image_settings)
1869
1870         vm_inst = self.inst_creator.create()
1871         self.assertIsNotNone(vm_inst)
1872         self.assertTrue(self.inst_creator.vm_active(block=True))
1873
1874
1875 class CreateInstanceMockOfflineTests(OSComponentTestCase):
1876     """
1877     Tests the custom image_metadata that can be set by clients for handling
1878     images differently than the default behavior of the existing tests
1879     primarily for offline testing
1880     """
1881
1882     def setUp(self):
1883         """
1884         Instantiates the CreateImage object that is responsible for downloading
1885         and creating an OS image file within OpenStack
1886         """
1887         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1888
1889         self.tmpDir = 'tmp/' + str(self.guid)
1890         if not os.path.exists(self.tmpDir):
1891             os.makedirs(self.tmpDir)
1892
1893         self.image_name = self.guid + '-image'
1894         self.vm_inst_name = self.guid + '-inst'
1895         self.port_1_name = self.guid + 'port-1'
1896
1897         # Initialize for tearDown()
1898         self.image_creator = None
1899         self.network_creator = None
1900         self.flavor_creator = None
1901         self.inst_creator = None
1902
1903         self.priv_net_config = openstack_tests.get_priv_net_config(
1904             net_name=self.guid + '-priv-net',
1905             subnet_name=self.guid + '-priv-subnet')
1906         self.port_settings = PortSettings(
1907             name=self.port_1_name,
1908             network_name=self.priv_net_config.network_settings.name)
1909
1910         try:
1911             # Download image file
1912             self.image_file = file_utils.download(
1913                 openstack_tests.CIRROS_DEFAULT_IMAGE_URL, self.tmpDir)
1914
1915             # Create Network
1916             self.network_creator = OpenStackNetwork(
1917                 self.os_creds, self.priv_net_config.network_settings)
1918             self.network_creator.create()
1919
1920             # Create Flavor
1921             self.flavor_creator = OpenStackFlavor(
1922                 self.os_creds,
1923                 FlavorSettings(
1924                     name=self.guid + '-flavor-name', ram=128, disk=10,
1925                     vcpus=1))
1926             self.flavor_creator.create()
1927         except Exception as e:
1928             self.tearDown()
1929             raise e
1930
1931     def tearDown(self):
1932         """
1933         Cleans the created object
1934         """
1935         if self.inst_creator:
1936             try:
1937                 self.inst_creator.clean()
1938             except Exception as e:
1939                 logger.error(
1940                     'Unexpected exception cleaning VM instance with message - '
1941                     '%s', e)
1942
1943         if self.network_creator:
1944             try:
1945                 self.network_creator.clean()
1946             except Exception as e:
1947                 logger.error(
1948                     'Unexpected exception cleaning network with message - %s',
1949                     e)
1950
1951         if self.flavor_creator:
1952             try:
1953                 self.flavor_creator.clean()
1954             except Exception as e:
1955                 logger.error(
1956                     'Unexpected exception cleaning flavor with message - %s',
1957                     e)
1958
1959         if self.image_creator:
1960             try:
1961                 self.image_creator.clean()
1962             except Exception as e:
1963                 logger.error(
1964                     'Unexpected exception cleaning image with message - %s', e)
1965
1966         if os.path.exists(self.tmpDir) and os.path.isdir(self.tmpDir):
1967             shutil.rmtree(self.tmpDir)
1968
1969     def test_inst_from_file_image_simple_flat(self):
1970         """
1971         Creates a VM instance from a locally sourced file image using simply
1972         the 'disk_file' attribute vs. using the 'config' option which
1973         completely overrides all image settings
1974         :return: 
1975         """
1976         metadata = {'disk_file': self.image_file.name}
1977
1978         os_image_settings = openstack_tests.cirros_image_settings(
1979             name=self.image_name, image_metadata=metadata)
1980         self.assertEqual(self.image_file.name, os_image_settings.image_file)
1981         self.assertEqual(openstack_tests.CIRROS_USER,
1982                          os_image_settings.image_user)
1983         self.assertIsNone(os_image_settings.url)
1984         self.assertFalse(os_image_settings.exists)
1985         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
1986                          os_image_settings.format)
1987
1988         self.assertIsNone(os_image_settings.kernel_image_settings)
1989         self.assertIsNone(os_image_settings.ramdisk_image_settings)
1990
1991         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
1992         self.image_creator.create()
1993
1994         instance_settings = VmInstanceSettings(
1995             name=self.vm_inst_name,
1996             flavor=self.flavor_creator.flavor_settings.name,
1997             port_settings=[self.port_settings])
1998         self.inst_creator = OpenStackVmInstance(
1999             self.os_creds, instance_settings,
2000             self.image_creator.image_settings)
2001         self.inst_creator.create()
2002
2003         self.assertTrue(self.inst_creator.vm_active(block=True))
2004
2005     def test_inst_from_file_image_simple_nested(self):
2006         """
2007         Creates a VM instance from a locally sourced file image using simply
2008         the 'disk_file' attribute under 'cirros' vs. using the 'config' option
2009         which completely overrides all image settings
2010         :return: 
2011         """
2012         metadata = {'cirros': {'disk_file': self.image_file.name}}
2013
2014         os_image_settings = openstack_tests.cirros_image_settings(
2015             name=self.image_name, image_metadata=metadata)
2016         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2017         self.assertEqual(openstack_tests.CIRROS_USER,
2018                          os_image_settings.image_user)
2019         self.assertIsNone(os_image_settings.url)
2020         self.assertFalse(os_image_settings.exists)
2021         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2022                          os_image_settings.format)
2023
2024         self.assertIsNone(os_image_settings.kernel_image_settings)
2025         self.assertIsNone(os_image_settings.ramdisk_image_settings)
2026
2027         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2028         self.image_creator.create()
2029
2030         instance_settings = VmInstanceSettings(
2031             name=self.vm_inst_name,
2032             flavor=self.flavor_creator.flavor_settings.name,
2033             port_settings=[self.port_settings])
2034         self.inst_creator = OpenStackVmInstance(
2035             self.os_creds, instance_settings,
2036             self.image_creator.image_settings)
2037         self.inst_creator.create()
2038
2039         self.assertTrue(self.inst_creator.vm_active(block=True))
2040
2041     def test_inst_from_existing(self):
2042         """
2043         Creates a VM instance from a image creator that has been configured to
2044         use an existing image
2045         :return: 
2046         """
2047         os_image_settings = openstack_tests.cirros_image_settings(
2048             name=self.image_name)
2049         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2050         self.image_creator.create()
2051
2052         image_settings = self.image_creator.image_settings
2053         test_image_creator = OpenStackImage(
2054             self.os_creds,
2055             ImageSettings(name=image_settings.name,
2056                           image_user=image_settings.image_user,
2057                           exists=True))
2058         test_image_creator.create()
2059         self.assertEqual(self.image_creator.get_image().id,
2060                          test_image_creator.get_image().id)
2061
2062         instance_settings = VmInstanceSettings(
2063             name=self.vm_inst_name,
2064             flavor=self.flavor_creator.flavor_settings.name,
2065             port_settings=[self.port_settings])
2066         self.inst_creator = OpenStackVmInstance(
2067             self.os_creds, instance_settings,
2068             test_image_creator.image_settings)
2069         self.inst_creator.create()
2070
2071         self.assertTrue(self.inst_creator.vm_active(block=True))
2072
2073     def test_inst_from_file_image_complex(self):
2074         """
2075         Creates a VM instance from a locally sourced file image by overriding
2076         the default settings by using a dict() that can be read in by
2077         ImageSettings
2078         :return: 
2079         """
2080
2081         os_image_settings = openstack_tests.cirros_image_settings(
2082             name=self.image_name)
2083         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2084         self.image_creator.create()
2085
2086         metadata = {
2087             'cirros':
2088                 {'config':
2089                      {'name': os_image_settings.name,
2090                       'image_user': os_image_settings.image_user,
2091                       'exists': True}}}
2092         test_image_settings = openstack_tests.cirros_image_settings(
2093             image_metadata=metadata)
2094         test_image = OpenStackImage(self.os_creds, test_image_settings)
2095         test_image.create()
2096
2097         instance_settings = VmInstanceSettings(
2098             name=self.vm_inst_name,
2099             flavor=self.flavor_creator.flavor_settings.name,
2100             port_settings=[self.port_settings])
2101         self.inst_creator = OpenStackVmInstance(self.os_creds,
2102                                                 instance_settings,
2103                                                 test_image_settings)
2104         self.inst_creator.create()
2105
2106         self.assertTrue(self.inst_creator.vm_active(block=True))
2107
2108     def test_inst_from_file_3part_image_complex(self):
2109         """
2110         Creates a VM instance from a locally sourced file image by overriding
2111         the default settings by using a dict() that can be read in by
2112         ImageSettings
2113         :return: 
2114         """
2115
2116         kernel_file = file_utils.download(
2117             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2118         ramdisk_file = file_utils.download(
2119             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2120
2121         metadata = {
2122             'cirros':
2123                 {'config':
2124                      {'name': self.image_name,
2125                       'image_user': openstack_tests.CIRROS_USER,
2126                       'image_file': self.image_file.name,
2127                       'format': openstack_tests.DEFAULT_IMAGE_FORMAT,
2128                       'kernel_image_settings':
2129                           {'name': self.image_name + '-kernel',
2130                            'image_user': openstack_tests.CIRROS_USER,
2131                            'image_file': kernel_file.name,
2132                            'format': openstack_tests.DEFAULT_IMAGE_FORMAT},
2133                       'ramdisk_image_settings':
2134                           {'name': self.image_name + '-ramdisk',
2135                            'image_user': openstack_tests.CIRROS_USER,
2136                            'image_file': ramdisk_file.name,
2137                            'format': openstack_tests.DEFAULT_IMAGE_FORMAT}}}}
2138
2139         os_image_settings = openstack_tests.cirros_image_settings(
2140             name=self.image_name, image_metadata=metadata)
2141         self.assertEqual(self.image_name, os_image_settings.name)
2142         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2143         self.assertEqual(openstack_tests.CIRROS_USER,
2144                          os_image_settings.image_user)
2145         self.assertIsNone(os_image_settings.url)
2146         self.assertFalse(os_image_settings.exists)
2147         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2148                          os_image_settings.format)
2149
2150         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2151         self.assertEqual(self.image_name + '-kernel',
2152                          os_image_settings.kernel_image_settings.name)
2153         self.assertEqual(kernel_file.name,
2154                          os_image_settings.kernel_image_settings.image_file)
2155         self.assertEqual(openstack_tests.CIRROS_USER,
2156                          os_image_settings.kernel_image_settings.image_user)
2157         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2158         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2159         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2160                          os_image_settings.kernel_image_settings.format)
2161
2162         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2163         self.assertEqual(self.image_name + '-ramdisk',
2164                          os_image_settings.ramdisk_image_settings.name)
2165         self.assertEqual(ramdisk_file.name,
2166                          os_image_settings.ramdisk_image_settings.image_file)
2167         self.assertEqual(openstack_tests.CIRROS_USER,
2168                          os_image_settings.ramdisk_image_settings.image_user)
2169         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2170         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2171         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2172                          os_image_settings.ramdisk_image_settings.format)
2173
2174         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2175         self.image_creator.create()
2176
2177         instance_settings = VmInstanceSettings(
2178             name=self.vm_inst_name,
2179             flavor=self.flavor_creator.flavor_settings.name,
2180             port_settings=[self.port_settings])
2181         self.inst_creator = OpenStackVmInstance(
2182             self.os_creds, instance_settings,
2183             self.image_creator.image_settings)
2184         self.inst_creator.create()
2185
2186         self.assertTrue(self.inst_creator.vm_active(block=True))
2187
2188     def test_inst_from_file_3part_image_simple_flat(self):
2189         """
2190         Creates a VM instance from a 3-part image locally sourced from file
2191         images using simply the 'disk_file', 'kernel_file', and 'ramdisk_file'
2192         attributes vs. using the 'config' option which completely overrides all
2193         image settings
2194         :return: 
2195         """
2196         kernel_file = file_utils.download(
2197             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2198         ramdisk_file = file_utils.download(
2199             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2200
2201         metadata = {'disk_file': self.image_file.name,
2202                     'kernel_file': kernel_file.name,
2203                     'ramdisk_file': ramdisk_file.name}
2204
2205         os_image_settings = openstack_tests.cirros_image_settings(
2206             name=self.image_name, image_metadata=metadata)
2207
2208         self.assertEqual(self.image_name, os_image_settings.name)
2209         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2210         self.assertEqual(openstack_tests.CIRROS_USER,
2211                          os_image_settings.image_user)
2212         self.assertIsNone(os_image_settings.url)
2213         self.assertFalse(os_image_settings.exists)
2214         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2215                          os_image_settings.format)
2216
2217         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2218         self.assertEqual(self.image_name + '-kernel',
2219                          os_image_settings.kernel_image_settings.name)
2220         self.assertEqual(kernel_file.name,
2221                          os_image_settings.kernel_image_settings.image_file)
2222         self.assertEqual(openstack_tests.CIRROS_USER,
2223                          os_image_settings.kernel_image_settings.image_user)
2224         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2225         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2226         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2227                          os_image_settings.kernel_image_settings.format)
2228
2229         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2230         self.assertEqual(self.image_name + '-ramdisk',
2231                          os_image_settings.ramdisk_image_settings.name)
2232         self.assertEqual(ramdisk_file.name,
2233                          os_image_settings.ramdisk_image_settings.image_file)
2234         self.assertEqual(openstack_tests.CIRROS_USER,
2235                          os_image_settings.ramdisk_image_settings.image_user)
2236         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2237         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2238         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2239                          os_image_settings.ramdisk_image_settings.format)
2240
2241         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2242         self.image_creator.create()
2243
2244         self.assertIsNotNone(self.image_creator.get_kernel_image())
2245         self.assertIsNotNone(self.image_creator.get_ramdisk_image())
2246
2247         instance_settings = VmInstanceSettings(
2248             name=self.vm_inst_name,
2249             flavor=self.flavor_creator.flavor_settings.name,
2250             port_settings=[self.port_settings])
2251         self.inst_creator = OpenStackVmInstance(
2252             self.os_creds, instance_settings,
2253             self.image_creator.image_settings)
2254         self.inst_creator.create()
2255
2256         self.assertTrue(self.inst_creator.vm_active(block=True))
2257
2258     def test_inst_from_file_3part_image_simple_nested(self):
2259         """
2260         Creates a VM instance from a 3-part image locally sourced from file
2261         images using simply the 'disk_file', 'kernel_file', and 'ramdisk_file'
2262         attributes under 'cirros' vs. using the 'config' option which
2263         completely overrides all image settings
2264         :return: 
2265         """
2266         kernel_file = file_utils.download(
2267             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2268         ramdisk_file = file_utils.download(
2269             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2270
2271         metadata = {'cirros': {'disk_file': self.image_file.name,
2272                                'kernel_file': kernel_file.name,
2273                                'ramdisk_file': ramdisk_file.name}}
2274
2275         os_image_settings = openstack_tests.cirros_image_settings(
2276             name=self.image_name, image_metadata=metadata)
2277
2278         self.assertEqual(self.image_name, os_image_settings.name)
2279         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2280         self.assertEqual(openstack_tests.CIRROS_USER,
2281                          os_image_settings.image_user)
2282         self.assertIsNone(os_image_settings.url)
2283         self.assertFalse(os_image_settings.exists)
2284         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2285                          os_image_settings.format)
2286
2287         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2288         self.assertEqual(self.image_name + '-kernel',
2289                          os_image_settings.kernel_image_settings.name)
2290         self.assertEqual(kernel_file.name,
2291                          os_image_settings.kernel_image_settings.image_file)
2292         self.assertEqual(openstack_tests.CIRROS_USER,
2293                          os_image_settings.kernel_image_settings.image_user)
2294         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2295         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2296         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2297                          os_image_settings.kernel_image_settings.format)
2298
2299         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2300         self.assertEqual(self.image_name + '-ramdisk',
2301                          os_image_settings.ramdisk_image_settings.name)
2302         self.assertEqual(ramdisk_file.name,
2303                          os_image_settings.ramdisk_image_settings.image_file)
2304         self.assertEqual(openstack_tests.CIRROS_USER,
2305                          os_image_settings.ramdisk_image_settings.image_user)
2306         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2307         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2308         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2309                          os_image_settings.ramdisk_image_settings.format)
2310
2311         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2312         self.image_creator.create()
2313
2314         self.assertIsNotNone(self.image_creator.get_kernel_image())
2315         self.assertIsNotNone(self.image_creator.get_ramdisk_image())
2316
2317         instance_settings = VmInstanceSettings(
2318             name=self.vm_inst_name,
2319             flavor=self.flavor_creator.flavor_settings.name,
2320             port_settings=[self.port_settings])
2321         self.inst_creator = OpenStackVmInstance(
2322             self.os_creds, instance_settings,
2323             self.image_creator.image_settings)
2324         self.inst_creator.create()
2325
2326         self.assertTrue(self.inst_creator.vm_active(block=True))
2327
2328     def test_inst_from_file_3part_image_existing(self):
2329         """
2330         Creates a VM instance from a 3-part image that is existing
2331         :return: 
2332         """
2333         kernel_file = file_utils.download(
2334             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2335         ramdisk_file = file_utils.download(
2336             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2337
2338         metadata = {'cirros': {'disk_file': self.image_file.name,
2339                                'kernel_file': kernel_file.name,
2340                                'ramdisk_file': ramdisk_file.name}}
2341
2342         os_image_settings = openstack_tests.cirros_image_settings(
2343             name=self.image_name, image_metadata=metadata)
2344         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2345         self.image_creator.create()
2346
2347         image_settings = self.image_creator.image_settings
2348         test_image_creator = OpenStackImage(
2349             self.os_creds,
2350             ImageSettings(name=image_settings.name,
2351                           image_user=image_settings.image_user,
2352                           exists=True))
2353         test_image_creator.create()
2354         self.assertEqual(self.image_creator.get_image().id,
2355                          test_image_creator.get_image().id)
2356
2357         instance_settings = VmInstanceSettings(
2358             name=self.vm_inst_name,
2359             flavor=self.flavor_creator.flavor_settings.name,
2360             port_settings=[self.port_settings])
2361         self.inst_creator = OpenStackVmInstance(
2362             self.os_creds, instance_settings,
2363             test_image_creator.image_settings)
2364         self.inst_creator.create()
2365
2366         self.assertTrue(self.inst_creator.vm_active(block=True))
2367
2368
2369 def check_dhcp_lease(nova_client, vm_domain, ip, timeout=160):
2370     """
2371     Returns true if the expected DHCP lease has been acquired
2372     :param nova_client: the nova client
2373     :param vm_domain: the SNAPS VM instance domain object
2374     :param ip: the IP address to look for
2375     :param timeout: how long to query for IP address
2376     :return:
2377     """
2378     found = False
2379     start_time = time.time()
2380
2381     logger.info("Looking for IP %s in the console log" % ip)
2382     full_log = ''
2383     while timeout > time.time() - start_time:
2384         vm = nova_utils.get_latest_server_os_object(nova_client, vm_domain)
2385         output = vm.get_console_output()
2386         full_log = full_log + output
2387         if re.search(ip, output):
2388             logger.info('DHCP lease obtained logged in console')
2389             found = True
2390             break
2391
2392     if not found:
2393         logger.error('Full console output -\n' + full_log)
2394     else:
2395         logger.debug('Full console output -\n' + full_log)
2396
2397     return found