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