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