Refactoring of FlavorSettings to extend FlavorConfig
[snaps.git] / snaps / openstack / tests / create_instance_tests.py
1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 #                    and others.  All rights reserved.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 import logging
16 import re
17 import shutil
18 import time
19 import unittest
20 import uuid
21
22 import os
23 from neutronclient.common.exceptions import InvalidIpForSubnetClient
24 from novaclient.exceptions import BadRequest
25
26 from snaps import file_utils
27 from snaps.openstack import create_network, create_router
28 from snaps.config.flavor import FlavorConfig
29 from snaps.openstack.create_flavor import OpenStackFlavor
30 from snaps.config.image import ImageConfig
31 from snaps.openstack.create_image import OpenStackImage
32 from snaps.openstack.create_instance import (
33     VmInstanceSettings, OpenStackVmInstance, FloatingIpSettings,
34     VmInstanceSettingsError, FloatingIpSettingsError)
35 from snaps.openstack.create_keypairs import OpenStackKeypair, KeypairSettings
36 from snaps.openstack.create_network import (
37     OpenStackNetwork, PortSettings, NetworkSettings, SubnetSettings)
38 from snaps.openstack.create_router import OpenStackRouter, RouterSettings
39 from snaps.openstack.create_security_group import (
40     SecurityGroupSettings, OpenStackSecurityGroup, SecurityGroupRuleSettings,
41     Direction, Protocol)
42 from snaps.openstack.create_volume import OpenStackVolume, VolumeSettings
43 from snaps.openstack.tests import openstack_tests, validation_utils
44 from snaps.openstack.tests.os_source_file_test import (
45     OSIntegrationTestCase, OSComponentTestCase)
46 from snaps.openstack.utils import nova_utils
47
48 __author__ = 'spisarski'
49
50 VM_BOOT_TIMEOUT = 600
51
52 logger = logging.getLogger('create_instance_tests')
53
54
55 class VmInstanceSettingsUnitTests(unittest.TestCase):
56     """
57     Tests the construction of the VmInstanceSettings class
58     """
59
60     def test_no_params(self):
61         with self.assertRaises(VmInstanceSettingsError):
62             VmInstanceSettings()
63
64     def test_empty_config(self):
65         with self.assertRaises(VmInstanceSettingsError):
66             VmInstanceSettings(config=dict())
67
68     def test_name_only(self):
69         with self.assertRaises(VmInstanceSettingsError):
70             VmInstanceSettings(name='foo')
71
72     def test_config_with_name_only(self):
73         with self.assertRaises(VmInstanceSettingsError):
74             VmInstanceSettings(config={'name': 'foo'})
75
76     def test_name_flavor_only(self):
77         with self.assertRaises(VmInstanceSettingsError):
78             VmInstanceSettings(name='foo', flavor='bar')
79
80     def test_config_with_name_flavor_only(self):
81         with self.assertRaises(VmInstanceSettingsError):
82             VmInstanceSettings(config={'name': 'foo', 'flavor': 'bar'})
83
84     def test_name_flavor_port_only(self):
85         port_settings = PortSettings(name='foo-port', network_name='bar-net')
86         settings = VmInstanceSettings(name='foo', flavor='bar',
87                                       port_settings=[port_settings])
88         self.assertEqual('foo', settings.name)
89         self.assertEqual('bar', settings.flavor)
90         self.assertEqual(1, len(settings.port_settings))
91         self.assertEqual('foo-port', settings.port_settings[0].name)
92         self.assertEqual('bar-net', settings.port_settings[0].network_name)
93         self.assertEqual(0, len(settings.security_group_names))
94         self.assertEqual(0, len(settings.floating_ip_settings))
95         self.assertIsNone(settings.sudo_user)
96         self.assertEqual(900, settings.vm_boot_timeout)
97         self.assertEqual(300, settings.vm_delete_timeout)
98         self.assertEqual(180, settings.ssh_connect_timeout)
99         self.assertIsNone(settings.availability_zone)
100         self.assertIsNone(settings.volume_names)
101
102     def test_config_with_name_flavor_port_only(self):
103         port_settings = PortSettings(name='foo-port', network_name='bar-net')
104         settings = VmInstanceSettings(
105             **{'name': 'foo', 'flavor': 'bar', 'ports': [port_settings]})
106         self.assertEqual('foo', settings.name)
107         self.assertEqual('bar', settings.flavor)
108         self.assertEqual(1, len(settings.port_settings))
109         self.assertEqual('foo-port', settings.port_settings[0].name)
110         self.assertEqual('bar-net', settings.port_settings[0].network_name)
111         self.assertEqual(0, len(settings.security_group_names))
112         self.assertEqual(0, len(settings.floating_ip_settings))
113         self.assertIsNone(settings.sudo_user)
114         self.assertEqual(900, settings.vm_boot_timeout)
115         self.assertEqual(300, settings.vm_delete_timeout)
116         self.assertEqual(180, settings.ssh_connect_timeout)
117         self.assertIsNone(settings.availability_zone)
118         self.assertIsNone(settings.volume_names)
119
120     def test_all(self):
121         port_settings = PortSettings(name='foo-port', network_name='bar-net')
122         fip_settings = FloatingIpSettings(name='foo-fip', port_name='bar-port',
123                                           router_name='foo-bar-router')
124
125         settings = VmInstanceSettings(
126             name='foo', flavor='bar', port_settings=[port_settings],
127             security_group_names=['sec_grp_1'],
128             floating_ip_settings=[fip_settings], sudo_user='joe',
129             vm_boot_timeout=999, vm_delete_timeout=333,
130             ssh_connect_timeout=111, availability_zone='server name',
131             volume_names=['vol1'])
132         self.assertEqual('foo', settings.name)
133         self.assertEqual('bar', settings.flavor)
134         self.assertEqual(1, len(settings.port_settings))
135         self.assertEqual('foo-port', settings.port_settings[0].name)
136         self.assertEqual('bar-net', settings.port_settings[0].network_name)
137         self.assertEqual(1, len(settings.security_group_names))
138         self.assertEqual('sec_grp_1', settings.security_group_names[0])
139         self.assertEqual(1, len(settings.floating_ip_settings))
140         self.assertEqual('foo-fip', settings.floating_ip_settings[0].name)
141         self.assertEqual('bar-port',
142                          settings.floating_ip_settings[0].port_name)
143         self.assertEqual('foo-bar-router',
144                          settings.floating_ip_settings[0].router_name)
145         self.assertEqual('joe', settings.sudo_user)
146         self.assertEqual(999, settings.vm_boot_timeout)
147         self.assertEqual(333, settings.vm_delete_timeout)
148         self.assertEqual(111, settings.ssh_connect_timeout)
149         self.assertEqual('server name', settings.availability_zone)
150         self.assertEqual('vol1', settings.volume_names[0])
151
152     def test_config_all(self):
153         port_settings = PortSettings(name='foo-port', network_name='bar-net')
154         fip_settings = FloatingIpSettings(name='foo-fip', port_name='bar-port',
155                                           router_name='foo-bar-router')
156
157         settings = VmInstanceSettings(
158             **{'name': 'foo', 'flavor': 'bar', 'ports': [port_settings],
159                'security_group_names': ['sec_grp_1'],
160                'floating_ips': [fip_settings], 'sudo_user': 'joe',
161                'vm_boot_timeout': 999, 'vm_delete_timeout': 333,
162                'ssh_connect_timeout': 111, 'availability_zone': 'server name',
163                'volume_names': ['vol2']})
164         self.assertEqual('foo', settings.name)
165         self.assertEqual('bar', settings.flavor)
166         self.assertEqual(1, len(settings.port_settings))
167         self.assertEqual('foo-port', settings.port_settings[0].name)
168         self.assertEqual('bar-net', settings.port_settings[0].network_name)
169         self.assertEqual(1, len(settings.security_group_names))
170         self.assertEqual(1, len(settings.floating_ip_settings))
171         self.assertEqual('foo-fip', settings.floating_ip_settings[0].name)
172         self.assertEqual('bar-port',
173                          settings.floating_ip_settings[0].port_name)
174         self.assertEqual('foo-bar-router',
175                          settings.floating_ip_settings[0].router_name)
176         self.assertEqual('joe', settings.sudo_user)
177         self.assertEqual(999, settings.vm_boot_timeout)
178         self.assertEqual(333, settings.vm_delete_timeout)
179         self.assertEqual(111, settings.ssh_connect_timeout)
180         self.assertEqual('server name', settings.availability_zone)
181         self.assertEqual('vol2', settings.volume_names[0])
182
183
184 class FloatingIpSettingsUnitTests(unittest.TestCase):
185     """
186     Tests the construction of the FloatingIpSettings class
187     """
188
189     def test_no_params(self):
190         with self.assertRaises(FloatingIpSettingsError):
191             FloatingIpSettings()
192
193     def test_empty_config(self):
194         with self.assertRaises(FloatingIpSettingsError):
195             FloatingIpSettings(**dict())
196
197     def test_name_only(self):
198         with self.assertRaises(FloatingIpSettingsError):
199             FloatingIpSettings(name='foo')
200
201     def test_config_with_name_only(self):
202         with self.assertRaises(FloatingIpSettingsError):
203             FloatingIpSettings(**{'name': 'foo'})
204
205     def test_name_port_only(self):
206         with self.assertRaises(FloatingIpSettingsError):
207             FloatingIpSettings(name='foo', port_name='bar')
208
209     def test_config_with_name_port_only(self):
210         with self.assertRaises(FloatingIpSettingsError):
211             FloatingIpSettings(**{'name': 'foo', 'port_name': 'bar'})
212
213     def test_name_router_only(self):
214         with self.assertRaises(FloatingIpSettingsError):
215             FloatingIpSettings(name='foo', router_name='bar')
216
217     def test_config_with_name_router_only(self):
218         with self.assertRaises(FloatingIpSettingsError):
219             FloatingIpSettings(**{'name': 'foo', 'router_name': 'bar'})
220
221     def test_name_port_router_name_only(self):
222         settings = FloatingIpSettings(name='foo', port_name='foo-port',
223                                       router_name='bar-router')
224         self.assertEqual('foo', settings.name)
225         self.assertEqual('foo-port', settings.port_name)
226         self.assertIsNone(settings.port_id)
227         self.assertEqual('bar-router', settings.router_name)
228         self.assertIsNone(settings.subnet_name)
229         self.assertTrue(settings.provisioning)
230
231     def test_name_port_router_id_only(self):
232         settings = FloatingIpSettings(name='foo', port_id='foo-port',
233                                       router_name='bar-router')
234         self.assertEqual('foo', settings.name)
235         self.assertEqual('foo-port', settings.port_id)
236         self.assertIsNone(settings.port_name)
237         self.assertEqual('bar-router', settings.router_name)
238         self.assertIsNone(settings.subnet_name)
239         self.assertTrue(settings.provisioning)
240
241     def test_config_with_name_port_router_only(self):
242         settings = FloatingIpSettings(
243             **{'name': 'foo', 'port_name': 'foo-port',
244                'router_name': 'bar-router'})
245         self.assertEqual('foo', settings.name)
246         self.assertEqual('foo-port', settings.port_name)
247         self.assertIsNone(settings.port_id)
248         self.assertEqual('bar-router', settings.router_name)
249         self.assertIsNone(settings.subnet_name)
250         self.assertTrue(settings.provisioning)
251
252     def test_all(self):
253         settings = FloatingIpSettings(name='foo', port_name='foo-port',
254                                       router_name='bar-router',
255                                       subnet_name='bar-subnet',
256                                       provisioning=False)
257         self.assertEqual('foo', settings.name)
258         self.assertEqual('foo-port', settings.port_name)
259         self.assertIsNone(settings.port_id)
260         self.assertEqual('bar-router', settings.router_name)
261         self.assertEqual('bar-subnet', settings.subnet_name)
262         self.assertFalse(settings.provisioning)
263
264     def test_config_all(self):
265         settings = FloatingIpSettings(
266             **{'name': 'foo', 'port_name': 'foo-port',
267                'router_name': 'bar-router', 'subnet_name': 'bar-subnet',
268                'provisioning': False})
269         self.assertEqual('foo', settings.name)
270         self.assertEqual('foo-port', settings.port_name)
271         self.assertIsNone(settings.port_id)
272         self.assertEqual('bar-router', settings.router_name)
273         self.assertEqual('bar-subnet', settings.subnet_name)
274         self.assertFalse(settings.provisioning)
275
276
277 class SimpleHealthCheck(OSIntegrationTestCase):
278     """
279     Test for the CreateInstance class with a single NIC/Port with Floating IPs
280     """
281
282     def setUp(self):
283         """
284         Instantiates the CreateImage object that is responsible for downloading
285         and creating an OS image file
286         within OpenStack
287         """
288         super(self.__class__, self).__start__()
289
290         self.nova = nova_utils.nova_client(self.os_creds)
291         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
292         self.vm_inst_name = guid + '-inst'
293         self.port_1_name = guid + 'port-1'
294
295         # Initialize for tearDown()
296         self.image_creator = None
297         self.network_creator = None
298         self.flavor_creator = None
299         self.inst_creator = None
300
301         self.priv_net_config = openstack_tests.get_priv_net_config(
302             net_name=guid + '-priv-net', subnet_name=guid + '-priv-subnet')
303         self.port_settings = PortSettings(
304             name=self.port_1_name,
305             network_name=self.priv_net_config.network_settings.name)
306
307         # Create Image
308         # Set the default image settings, then set any custom parameters sent
309         # from the app
310         os_image_settings = openstack_tests.cirros_image_settings(
311             name=guid + '-image', image_metadata=self.image_metadata)
312
313         try:
314             self.image_creator = OpenStackImage(self.os_creds,
315                                                 os_image_settings)
316             self.image_creator.create()
317
318             # Create Network
319             self.network_creator = OpenStackNetwork(
320                 self.os_creds, self.priv_net_config.network_settings)
321             self.network_creator.create()
322
323             # Create Flavor
324             self.flavor_creator = OpenStackFlavor(
325                 self.admin_os_creds,
326                 FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10,
327                              vcpus=1, metadata=self.flavor_metadata))
328             self.flavor_creator.create()
329         except Exception as e:
330             self.tearDown()
331             raise e
332
333     def tearDown(self):
334         """
335         Cleans the created object
336         """
337         if self.inst_creator:
338             try:
339                 self.inst_creator.clean()
340             except Exception as e:
341                 logger.error(
342                     'Unexpected exception cleaning VM instance with message'
343                     ' - %s', e)
344
345         if self.network_creator:
346             try:
347                 self.network_creator.clean()
348             except Exception as e:
349                 logger.error(
350                     'Unexpected exception cleaning network with message - %s',
351                     e)
352
353         if self.flavor_creator:
354             try:
355                 self.flavor_creator.clean()
356             except Exception as e:
357                 logger.error(
358                     'Unexpected exception cleaning flavor with message - %s',
359                     e)
360
361         if self.image_creator and not self.image_creator.image_settings.exists:
362             try:
363                 self.image_creator.clean()
364             except Exception as e:
365                 logger.error(
366                     'Unexpected exception cleaning image with message - %s',
367                     e)
368
369         super(self.__class__, self).__clean__()
370
371     def test_check_vm_ip_dhcp(self):
372         """
373         Tests the creation of an OpenStack instance with a single port and
374         ensures that it's assigned IP address is the actual.
375         """
376         instance_settings = VmInstanceSettings(
377             name=self.vm_inst_name,
378             flavor=self.flavor_creator.flavor_settings.name,
379             port_settings=[self.port_settings])
380
381         self.inst_creator = OpenStackVmInstance(
382             self.os_creds, instance_settings,
383             self.image_creator.image_settings)
384         self.inst_creator.create()
385
386         ip = self.inst_creator.get_port_ip(self.port_settings.name)
387         self.assertIsNotNone(ip)
388
389         self.assertTrue(self.inst_creator.vm_active(block=True))
390
391         self.assertTrue(check_dhcp_lease(self.inst_creator, ip))
392
393
394 class CreateInstanceSimpleTests(OSIntegrationTestCase):
395     """
396     Simple instance creation tests without any other objects
397     """
398
399     def setUp(self):
400         """
401         Instantiates the CreateImage object that is responsible for downloading
402         and creating an OS image file
403         within OpenStack
404         """
405         super(self.__class__, self).__start__()
406
407         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
408         self.vm_inst_name = guid + '-inst'
409         self.nova = nova_utils.nova_client(self.os_creds)
410         os_image_settings = openstack_tests.cirros_image_settings(
411             name=guid + '-image', image_metadata=self.image_metadata)
412
413         net_config = openstack_tests.get_priv_net_config(
414             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
415             router_name=guid + '-pub-router', external_net=self.ext_net_name)
416
417         # Initialize for tearDown()
418         self.image_creator = None
419         self.flavor_creator = None
420
421         self.network_creator = None
422         self.inst_creator = None
423
424         try:
425             # Create Image
426             self.image_creator = OpenStackImage(self.os_creds,
427                                                 os_image_settings)
428             self.image_creator.create()
429
430             # Create Flavor
431             self.flavor_creator = OpenStackFlavor(
432                 self.admin_os_creds,
433                 FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10,
434                              vcpus=2, metadata=self.flavor_metadata))
435             self.flavor_creator.create()
436
437             # Create Network
438             self.network_creator = OpenStackNetwork(
439                 self.os_creds, net_config.network_settings)
440             self.network_creator.create()
441
442             self.port_settings = PortSettings(
443                 name=guid + '-port',
444                 network_name=net_config.network_settings.name)
445
446         except Exception as e:
447             self.tearDown()
448             raise e
449
450     def tearDown(self):
451         """
452         Cleans the created object
453         """
454         if self.inst_creator:
455             try:
456                 self.inst_creator.clean()
457             except Exception as e:
458                 logger.error(
459                     'Unexpected exception cleaning VM instance with message '
460                     '- %s', e)
461
462         if self.flavor_creator:
463             try:
464                 self.flavor_creator.clean()
465             except Exception as e:
466                 logger.error(
467                     'Unexpected exception cleaning flavor with message - %s',
468                     e)
469
470         if self.network_creator:
471             try:
472                 self.network_creator.clean()
473             except Exception as e:
474                 logger.error(
475                     'Unexpected exception cleaning network with message - %s',
476                     e)
477
478         if self.image_creator and not self.image_creator.image_settings.exists:
479             try:
480                 self.image_creator.clean()
481             except Exception as e:
482                 logger.error(
483                     'Unexpected exception cleaning image with message - %s', e)
484
485         super(self.__class__, self).__clean__()
486
487     def test_create_delete_instance(self):
488         """
489         Tests the creation of an OpenStack instance with a single port with a
490         static IP without a Floating IP.
491         """
492         instance_settings = VmInstanceSettings(
493             name=self.vm_inst_name,
494             flavor=self.flavor_creator.flavor_settings.name,
495             port_settings=[self.port_settings])
496
497         self.inst_creator = OpenStackVmInstance(
498             self.os_creds, instance_settings,
499             self.image_creator.image_settings)
500
501         vm_inst = self.inst_creator.create()
502         self.assertIsNotNone(nova_utils.get_server(
503             self.nova, vm_inst_settings=instance_settings))
504
505         # Delete instance
506         nova_utils.delete_vm_instance(self.nova, vm_inst)
507
508         self.assertTrue(self.inst_creator.vm_deleted(block=True))
509         self.assertIsNone(nova_utils.get_server(
510             self.nova, vm_inst_settings=instance_settings))
511
512         # Exception should not be thrown
513         self.inst_creator.clean()
514
515
516 class CreateInstanceSingleNetworkTests(OSIntegrationTestCase):
517     """
518     Test for the CreateInstance class with a single NIC/Port with Floating IPs
519     """
520
521     def setUp(self):
522         """
523         Instantiates the CreateImage object that is responsible for downloading
524         and creating an OS image file within OpenStack
525         """
526         super(self.__class__, self).__start__()
527
528         self.nova = nova_utils.nova_client(self.os_creds)
529         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
530         self.keypair_priv_filepath = 'tmp/' + guid
531         self.keypair_pub_filepath = self.keypair_priv_filepath + '.pub'
532         self.keypair_name = guid + '-kp'
533         self.vm_inst_name = guid + '-inst'
534         self.port_1_name = guid + 'port-1'
535         self.port_2_name = guid + 'port-2'
536         self.floating_ip_name = guid + 'fip1'
537
538         # Initialize for tearDown()
539         self.image_creator = None
540         self.network_creator = None
541         self.router_creator = None
542         self.flavor_creator = None
543         self.keypair_creator = None
544         self.sec_grp_creator = None
545         self.inst_creators = list()
546
547         self.pub_net_config = openstack_tests.get_pub_net_config(
548             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
549             router_name=guid + '-pub-router', external_net=self.ext_net_name)
550         os_image_settings = openstack_tests.cirros_image_settings(
551             name=guid + '-image', image_metadata=self.image_metadata)
552         try:
553             # Create Image
554             self.image_creator = OpenStackImage(self.os_creds,
555                                                 os_image_settings)
556             self.image_creator.create()
557
558             # Create Network
559             self.network_creator = OpenStackNetwork(
560                 self.os_creds, self.pub_net_config.network_settings)
561             self.network_creator.create()
562
563             # Create Router
564             self.router_creator = OpenStackRouter(
565                 self.os_creds, self.pub_net_config.router_settings)
566             self.router_creator.create()
567
568             # Create Flavor
569             self.flavor_creator = OpenStackFlavor(
570                 self.admin_os_creds,
571                 FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10,
572                              vcpus=2, metadata=self.flavor_metadata))
573             self.flavor_creator.create()
574
575             self.keypair_creator = OpenStackKeypair(
576                 self.os_creds, KeypairSettings(
577                     name=self.keypair_name,
578                     public_filepath=self.keypair_pub_filepath,
579                     private_filepath=self.keypair_priv_filepath))
580             self.keypair_creator.create()
581
582             sec_grp_name = guid + '-sec-grp'
583             rule1 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
584                                               direction=Direction.ingress,
585                                               protocol=Protocol.icmp)
586             rule2 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
587                                               direction=Direction.ingress,
588                                               protocol=Protocol.tcp,
589                                               port_range_min=22,
590                                               port_range_max=22)
591             self.sec_grp_creator = OpenStackSecurityGroup(
592                 self.os_creds,
593                 SecurityGroupSettings(name=sec_grp_name,
594                                       rule_settings=[rule1, rule2]))
595             self.sec_grp_creator.create()
596         except Exception as e:
597             self.tearDown()
598             raise e
599
600     def tearDown(self):
601         """
602         Cleans the created object
603         """
604         for inst_creator in self.inst_creators:
605             try:
606                 inst_creator.clean()
607             except Exception as e:
608                 logger.error(
609                     'Unexpected exception cleaning VM instance with message '
610                     '- %s', e)
611
612         if self.keypair_creator:
613             try:
614                 self.keypair_creator.clean()
615             except Exception as e:
616                 logger.error(
617                     'Unexpected exception cleaning keypair with message - %s',
618                     e)
619
620         if self.flavor_creator:
621             try:
622                 self.flavor_creator.clean()
623             except Exception as e:
624                 logger.error(
625                     'Unexpected exception cleaning flavor with message - %s',
626                     e)
627
628         if self.sec_grp_creator:
629             try:
630                 self.sec_grp_creator.clean()
631             except Exception as e:
632                 logger.error(
633                     'Unexpected exception cleaning security group with message'
634                     ' - %s', e)
635
636         if self.router_creator:
637             try:
638                 self.router_creator.clean()
639             except Exception as e:
640                 logger.error(
641                     'Unexpected exception cleaning router with message - %s',
642                     e)
643
644         if self.network_creator:
645             try:
646                 self.network_creator.clean()
647             except Exception as e:
648                 logger.error(
649                     'Unexpected exception cleaning network with message - %s',
650                     e)
651
652         if self.image_creator and not self.image_creator.image_settings.exists:
653             try:
654                 self.image_creator.clean()
655             except Exception as e:
656                 logger.error(
657                     'Unexpected exception cleaning image with message - %s', e)
658
659         super(self.__class__, self).__clean__()
660
661     def test_single_port_static(self):
662         """
663         Tests the creation of an OpenStack instance with a single port with a
664         static IP without a Floating IP.
665         """
666         ip_1 = '10.55.1.100'
667         sub_settings = self.pub_net_config.network_settings.subnet_settings
668         port_settings = PortSettings(
669             name=self.port_1_name,
670             network_name=self.pub_net_config.network_settings.name,
671             ip_addrs=[
672                 {'subnet_name': sub_settings[0].name, 'ip': ip_1}])
673
674         instance_settings = VmInstanceSettings(
675             name=self.vm_inst_name,
676             flavor=self.flavor_creator.flavor_settings.name,
677             port_settings=[port_settings],
678             floating_ip_settings=[FloatingIpSettings(
679                 name=self.floating_ip_name, port_name=self.port_1_name,
680                 router_name=self.pub_net_config.router_settings.name)])
681
682         inst_creator = OpenStackVmInstance(
683             self.os_creds, instance_settings,
684             self.image_creator.image_settings,
685             keypair_settings=self.keypair_creator.keypair_settings)
686         self.inst_creators.append(inst_creator)
687         vm_inst = inst_creator.create(block=True)
688
689         self.assertEqual(ip_1, inst_creator.get_port_ip(self.port_1_name))
690         self.assertTrue(inst_creator.vm_active(block=True))
691         self.assertEqual(vm_inst.id, inst_creator.get_vm_inst().id)
692
693     def test_ssh_client_fip_before_active(self):
694         """
695         Tests the ability to access a VM via SSH and a floating IP when it has
696         been assigned prior to being active.
697         """
698         port_settings = PortSettings(
699             name=self.port_1_name,
700             network_name=self.pub_net_config.network_settings.name)
701
702         instance_settings = VmInstanceSettings(
703             name=self.vm_inst_name,
704             flavor=self.flavor_creator.flavor_settings.name,
705             port_settings=[port_settings],
706             security_group_names=[self.sec_grp_creator.sec_grp_settings.name],
707             floating_ip_settings=[FloatingIpSettings(
708                 name=self.floating_ip_name, port_name=self.port_1_name,
709                 router_name=self.pub_net_config.router_settings.name)])
710
711         inst_creator = OpenStackVmInstance(
712             self.os_creds, instance_settings,
713             self.image_creator.image_settings,
714             keypair_settings=self.keypair_creator.keypair_settings)
715         self.inst_creators.append(inst_creator)
716         vm_inst = inst_creator.create()
717         self.assertIsNotNone(vm_inst)
718
719         self.assertTrue(inst_creator.vm_active(block=True))
720
721         ip = inst_creator.get_port_ip(port_settings.name)
722         self.assertTrue(check_dhcp_lease(inst_creator, ip))
723
724         self.assertEqual(vm_inst.id, inst_creator.get_vm_inst().id)
725
726         self.assertTrue(validate_ssh_client(inst_creator))
727
728     def test_ssh_client_fip_after_active(self):
729         """
730         Tests the ability to access a VM via SSH and a floating IP when it has
731         been assigned prior to being active.
732         """
733         port_settings = PortSettings(
734             name=self.port_1_name,
735             network_name=self.pub_net_config.network_settings.name)
736
737         instance_settings = VmInstanceSettings(
738             name=self.vm_inst_name,
739             flavor=self.flavor_creator.flavor_settings.name,
740             port_settings=[port_settings],
741             security_group_names=[self.sec_grp_creator.sec_grp_settings.name],
742             floating_ip_settings=[FloatingIpSettings(
743                 name=self.floating_ip_name, port_name=self.port_1_name,
744                 router_name=self.pub_net_config.router_settings.name)])
745
746         inst_creator = OpenStackVmInstance(
747             self.os_creds, instance_settings,
748             self.image_creator.image_settings,
749             keypair_settings=self.keypair_creator.keypair_settings)
750         self.inst_creators.append(inst_creator)
751
752         # block=True will force the create() method to block until the
753         vm_inst = inst_creator.create(block=True)
754         self.assertIsNotNone(vm_inst)
755
756         self.assertTrue(inst_creator.vm_active(block=True))
757
758         ip = inst_creator.get_port_ip(port_settings.name)
759         self.assertTrue(check_dhcp_lease(inst_creator, ip))
760
761         self.assertEqual(vm_inst.id, inst_creator.get_vm_inst().id)
762
763         self.assertTrue(validate_ssh_client(inst_creator))
764
765     def test_ssh_client_fip_second_creator(self):
766         """
767         Tests the ability to access a VM via SSH and a floating IP via a
768         creator that is identical to the original creator.
769         """
770         port_settings = PortSettings(
771             name=self.port_1_name,
772             network_name=self.pub_net_config.network_settings.name)
773
774         instance_settings = VmInstanceSettings(
775             name=self.vm_inst_name,
776             flavor=self.flavor_creator.flavor_settings.name,
777             port_settings=[port_settings],
778             security_group_names=[self.sec_grp_creator.sec_grp_settings.name],
779             floating_ip_settings=[FloatingIpSettings(
780                 name=self.floating_ip_name, port_name=self.port_1_name,
781                 router_name=self.pub_net_config.router_settings.name)])
782
783         inst_creator = OpenStackVmInstance(
784             self.os_creds, instance_settings,
785             self.image_creator.image_settings,
786             keypair_settings=self.keypair_creator.keypair_settings)
787         self.inst_creators.append(inst_creator)
788
789         # block=True will force the create() method to block until the
790         vm_inst = inst_creator.create(block=True)
791         self.assertIsNotNone(vm_inst)
792
793         self.assertTrue(inst_creator.vm_active(block=True))
794
795         ip = inst_creator.get_port_ip(port_settings.name)
796         self.assertTrue(check_dhcp_lease(inst_creator, ip))
797
798         self.assertEqual(vm_inst.id, inst_creator.get_vm_inst().id)
799
800         self.assertTrue(validate_ssh_client(inst_creator))
801
802         inst_creator2 = OpenStackVmInstance(
803             self.os_creds, instance_settings,
804             self.image_creator.image_settings,
805             keypair_settings=self.keypair_creator.keypair_settings)
806         inst_creator2.create()
807         self.assertTrue(validate_ssh_client(inst_creator2))
808
809
810 class CreateInstanceIPv6NetworkTests(OSIntegrationTestCase):
811     """
812     Test for the CreateInstance class with a single NIC/Port with Floating IPs
813     """
814
815     def setUp(self):
816         """
817         Instantiates the CreateImage object that is responsible for downloading
818         and creating an OS image file within OpenStack
819         """
820         super(self.__class__, self).__start__()
821
822         self.nova = nova_utils.nova_client(self.os_creds)
823         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
824         self.keypair_priv_filepath = 'tmp/' + self.guid
825         self.keypair_pub_filepath = self.keypair_priv_filepath + '.pub'
826         self.keypair_name = self.guid + '-kp'
827         self.vm_inst_name = self.guid + '-inst'
828         self.port1_name = self.guid + 'port1'
829         self.port2_name = self.guid + 'port2'
830
831         # Initialize for tearDown()
832         self.image_creator = None
833         self.network_creator = None
834         self.router_creator = None
835         self.flavor_creator = None
836         self.keypair_creator = None
837         self.sec_grp_creator = None
838         self.inst_creator = None
839
840         os_image_settings = openstack_tests.cirros_image_settings(
841             name=self.guid + '-image', image_metadata=self.image_metadata)
842         try:
843             self.image_creator = OpenStackImage(
844                 self.os_creds, os_image_settings)
845             self.image_creator.create()
846
847             self.flavor_creator = OpenStackFlavor(
848                 self.admin_os_creds,
849                 FlavorConfig(
850                     name=self.guid + '-flavor-name', ram=256, disk=10, vcpus=2,
851                     metadata=self.flavor_metadata))
852             self.flavor_creator.create()
853
854             self.keypair_creator = OpenStackKeypair(
855                 self.os_creds, KeypairSettings(
856                     name=self.keypair_name,
857                     public_filepath=self.keypair_pub_filepath,
858                     private_filepath=self.keypair_priv_filepath))
859             self.keypair_creator.create()
860
861             sec_grp_name = self.guid + '-sec-grp'
862             rule1 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
863                                               direction=Direction.ingress,
864                                               protocol=Protocol.icmp)
865             rule2 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
866                                               direction=Direction.ingress,
867                                               protocol=Protocol.tcp,
868                                               port_range_min=22,
869                                               port_range_max=22)
870             self.sec_grp_creator = OpenStackSecurityGroup(
871                 self.os_creds,
872                 SecurityGroupSettings(name=sec_grp_name,
873                                       rule_settings=[rule1, rule2]))
874             self.sec_grp_creator.create()
875         except Exception as e:
876             self.tearDown()
877             raise e
878
879     def tearDown(self):
880         """
881         Cleans the created object
882         """
883         if self.inst_creator:
884             try:
885                 self.inst_creator.clean()
886             except Exception as e:
887                 logger.error(
888                     'Unexpected exception cleaning VM instance with message '
889                     '- %s', e)
890
891         if self.keypair_creator:
892             try:
893                 self.keypair_creator.clean()
894             except Exception as e:
895                 logger.error(
896                     'Unexpected exception cleaning keypair with message - %s',
897                     e)
898
899         if self.flavor_creator:
900             try:
901                 self.flavor_creator.clean()
902             except Exception as e:
903                 logger.error(
904                     'Unexpected exception cleaning flavor with message - %s',
905                     e)
906
907         if self.sec_grp_creator:
908             try:
909                 self.sec_grp_creator.clean()
910             except Exception as e:
911                 logger.error(
912                     'Unexpected exception cleaning security group with message'
913                     ' - %s', e)
914
915         if self.router_creator:
916             try:
917                 self.router_creator.clean()
918             except Exception as e:
919                 logger.error(
920                     'Unexpected exception cleaning router with message - %s',
921                     e)
922
923         if self.network_creator:
924             try:
925                 self.network_creator.clean()
926             except Exception as e:
927                 logger.error(
928                     'Unexpected exception cleaning network with message - %s',
929                     e)
930
931         if self.image_creator and not self.image_creator.image_settings.exists:
932             try:
933                 self.image_creator.clean()
934             except Exception as e:
935                 logger.error(
936                     'Unexpected exception cleaning image with message - %s', e)
937
938         super(self.__class__, self).__clean__()
939
940     def test_v4fip_v6overlay(self):
941         """
942         Tests the ability to assign an IPv4 floating IP to an IPv6 overlay
943         network when the external network does not have an IPv6 subnet.
944         """
945         subnet_settings = SubnetSettings(
946             name=self.guid + '-subnet', cidr='1:1:0:0:0:0:0:0/64',
947             ip_version=6)
948         network_settings = NetworkSettings(
949             name=self.guid + '-net', subnet_settings=[subnet_settings])
950         router_settings = RouterSettings(
951             name=self.guid + '-router', external_gateway=self.ext_net_name,
952             internal_subnets=[subnet_settings.name])
953
954         # Create Network
955         self.network_creator = OpenStackNetwork(
956             self.os_creds, network_settings)
957         self.network_creator.create()
958
959         # Create Router
960         self.router_creator = OpenStackRouter(
961             self.os_creds, router_settings)
962         self.router_creator.create()
963
964         port_settings = PortSettings(
965             name=self.port1_name, network_name=network_settings.name)
966
967         instance_settings = VmInstanceSettings(
968             name=self.vm_inst_name,
969             flavor=self.flavor_creator.flavor_settings.name,
970             port_settings=[port_settings],
971             security_group_names=[self.sec_grp_creator.sec_grp_settings.name],
972             floating_ip_settings=[FloatingIpSettings(
973                 name='fip1', port_name=self.port1_name,
974                 router_name=router_settings.name)])
975
976         self.inst_creator = OpenStackVmInstance(
977             self.os_creds, instance_settings,
978             self.image_creator.image_settings,
979             keypair_settings=self.keypair_creator.keypair_settings)
980
981         with self.assertRaises(BadRequest):
982             self.inst_creator.create(block=True)
983
984     def test_fip_v4and6_overlay(self):
985         """
986         Tests the ability to assign an IPv4 floating IP to an IPv6 overlay
987         network when the external network does not have an IPv6 subnet.
988         """
989         subnet4_settings = SubnetSettings(
990             name=self.guid + '-subnet4', cidr='10.0.1.0/24',
991             ip_version=4)
992         subnet6_settings = SubnetSettings(
993             name=self.guid + '-subnet6', cidr='1:1:0:0:0:0:0:0/64',
994             ip_version=6)
995         network_settings = NetworkSettings(
996             name=self.guid + '-net',
997             subnet_settings=[subnet4_settings, subnet6_settings])
998         router_settings = RouterSettings(
999             name=self.guid + '-router', external_gateway=self.ext_net_name,
1000             internal_subnets=[subnet4_settings.name])
1001
1002         # Create Network
1003         self.network_creator = OpenStackNetwork(
1004             self.os_creds, network_settings)
1005         self.network_creator.create()
1006
1007         # Create Router
1008         self.router_creator = OpenStackRouter(
1009             self.os_creds, router_settings)
1010         self.router_creator.create()
1011
1012         port_settings = PortSettings(
1013             name=self.port1_name, network_name=network_settings.name)
1014
1015         instance_settings = VmInstanceSettings(
1016             name=self.vm_inst_name,
1017             flavor=self.flavor_creator.flavor_settings.name,
1018             port_settings=[port_settings],
1019             security_group_names=[self.sec_grp_creator.sec_grp_settings.name],
1020             floating_ip_settings=[FloatingIpSettings(
1021                 name='fip1', port_name=self.port1_name,
1022                 router_name=router_settings.name)])
1023
1024         self.inst_creator = OpenStackVmInstance(
1025             self.os_creds, instance_settings,
1026             self.image_creator.image_settings,
1027             keypair_settings=self.keypair_creator.keypair_settings)
1028
1029         self.inst_creator.create(block=True)
1030         ssh_client = self.inst_creator.ssh_client()
1031         self.assertIsNotNone(ssh_client)
1032
1033
1034 class CreateInstancePortManipulationTests(OSIntegrationTestCase):
1035     """
1036     Test for the CreateInstance class with a single NIC/Port where mac and IP
1037     values are manually set
1038     """
1039
1040     def setUp(self):
1041         """
1042         Instantiates the CreateImage object that is responsible for downloading
1043         and creating an OS image file within OpenStack
1044         """
1045         super(self.__class__, self).__start__()
1046
1047         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1048         self.vm_inst_name = guid + '-inst'
1049         self.port_1_name = guid + 'port-1'
1050         self.port_2_name = guid + 'port-2'
1051         self.floating_ip_name = guid + 'fip1'
1052
1053         # Initialize for tearDown()
1054         self.image_creator = None
1055         self.network_creator = None
1056         self.flavor_creator = None
1057         self.inst_creator = None
1058
1059         self.net_config = openstack_tests.get_priv_net_config(
1060             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
1061             router_name=guid + '-pub-router', external_net=self.ext_net_name)
1062         os_image_settings = openstack_tests.cirros_image_settings(
1063             name=guid + '-image', image_metadata=self.image_metadata)
1064
1065         try:
1066             # Create Image
1067             self.image_creator = OpenStackImage(self.os_creds,
1068                                                 os_image_settings)
1069             self.image_creator.create()
1070
1071             # Create Network
1072             self.network_creator = OpenStackNetwork(
1073                 self.os_creds, self.net_config.network_settings)
1074             self.network_creator.create()
1075
1076             # Create Flavor
1077             self.flavor_creator = OpenStackFlavor(
1078                 self.admin_os_creds,
1079                 FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10,
1080                              vcpus=2, metadata=self.flavor_metadata))
1081             self.flavor_creator.create()
1082         except Exception as e:
1083             self.tearDown()
1084             raise e
1085
1086     def tearDown(self):
1087         """
1088         Cleans the created object
1089         """
1090         if self.inst_creator:
1091             try:
1092                 self.inst_creator.clean()
1093             except Exception as e:
1094                 logger.error(
1095                     'Unexpected exception cleaning VM instance with message '
1096                     '- %s', e)
1097
1098         if self.flavor_creator:
1099             try:
1100                 self.flavor_creator.clean()
1101             except Exception as e:
1102                 logger.error(
1103                     'Unexpected exception cleaning flavor with message - %s',
1104                     e)
1105
1106         if self.network_creator:
1107             try:
1108                 self.network_creator.clean()
1109             except Exception as e:
1110                 logger.error(
1111                     'Unexpected exception cleaning network with message - %s',
1112                     e)
1113
1114         if self.image_creator and not self.image_creator.image_settings.exists:
1115             try:
1116                 self.image_creator.clean()
1117             except Exception as e:
1118                 logger.error(
1119                     'Unexpected exception cleaning image with message - %s', e)
1120
1121         super(self.__class__, self).__clean__()
1122
1123     def test_set_custom_valid_ip_one_subnet(self):
1124         """
1125         Tests the creation of an OpenStack instance with a single port with a
1126         static IP on a network with one subnet.
1127         """
1128         ip = '10.55.0.101'
1129         sub_settings = self.net_config.network_settings.subnet_settings
1130         port_settings = PortSettings(
1131             name=self.port_1_name,
1132             network_name=self.net_config.network_settings.name,
1133             ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}])
1134
1135         instance_settings = VmInstanceSettings(
1136             name=self.vm_inst_name,
1137             flavor=self.flavor_creator.flavor_settings.name,
1138             port_settings=[port_settings])
1139
1140         self.inst_creator = OpenStackVmInstance(
1141             self.os_creds, instance_settings,
1142             self.image_creator.image_settings)
1143         self.inst_creator.create(block=True)
1144
1145         self.assertEqual(ip, self.inst_creator.get_port_ip(
1146             self.port_1_name,
1147             subnet_name=self.net_config.network_settings.subnet_settings[
1148                 0].name))
1149
1150     def test_set_custom_invalid_ip_one_subnet(self):
1151         """
1152         Tests the creation of an OpenStack instance with a single port with a
1153         static IP on a network with one subnet.
1154         """
1155         ip = '10.66.0.101'
1156         sub_settings = self.net_config.network_settings.subnet_settings
1157         port_settings = PortSettings(
1158             name=self.port_1_name,
1159             network_name=self.net_config.network_settings.name,
1160             ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}])
1161
1162         instance_settings = VmInstanceSettings(
1163             name=self.vm_inst_name,
1164             flavor=self.flavor_creator.flavor_settings.name,
1165             port_settings=[port_settings])
1166
1167         self.inst_creator = OpenStackVmInstance(
1168             self.os_creds, instance_settings,
1169             self.image_creator.image_settings)
1170
1171         with self.assertRaises(InvalidIpForSubnetClient):
1172             self.inst_creator.create()
1173
1174     def test_set_custom_valid_mac(self):
1175         """
1176         Tests the creation of an OpenStack instance with a single port where
1177         the MAC address is assigned.
1178         """
1179         mac_addr = '0a:1b:2c:3d:4e:5f'
1180         port_settings = PortSettings(
1181             name=self.port_1_name,
1182             network_name=self.net_config.network_settings.name,
1183             mac_address=mac_addr)
1184
1185         instance_settings = VmInstanceSettings(
1186             name=self.vm_inst_name,
1187             flavor=self.flavor_creator.flavor_settings.name,
1188             port_settings=[port_settings])
1189
1190         self.inst_creator = OpenStackVmInstance(
1191             self.os_creds, instance_settings,
1192             self.image_creator.image_settings)
1193         self.inst_creator.create(block=True)
1194
1195         self.assertEqual(mac_addr,
1196                          self.inst_creator.get_port_mac(self.port_1_name))
1197
1198     def test_set_custom_invalid_mac(self):
1199         """
1200         Tests the creation of an OpenStack instance with a single port where an
1201         invalid MAC address value is being
1202         assigned. This should raise an Exception
1203         """
1204         port_settings = PortSettings(
1205             name=self.port_1_name,
1206             network_name=self.net_config.network_settings.name,
1207             mac_address='foo')
1208
1209         instance_settings = VmInstanceSettings(
1210             name=self.vm_inst_name,
1211             flavor=self.flavor_creator.flavor_settings.name,
1212             port_settings=[port_settings])
1213
1214         self.inst_creator = OpenStackVmInstance(
1215             self.os_creds, instance_settings,
1216             self.image_creator.image_settings)
1217
1218         with self.assertRaises(Exception):
1219             self.inst_creator.create()
1220
1221     def test_set_custom_mac_and_ip(self):
1222         """
1223         Tests the creation of an OpenStack instance with a single port where
1224         the IP and MAC address is assigned.
1225         """
1226         ip = '10.55.0.101'
1227         mac_addr = '0a:1b:2c:3d:4e:5f'
1228         sub_settings = self.net_config.network_settings.subnet_settings
1229         port_settings = PortSettings(
1230             name=self.port_1_name,
1231             network_name=self.net_config.network_settings.name,
1232             mac_address=mac_addr,
1233             ip_addrs=[{'subnet_name': sub_settings[0].name, 'ip': ip}])
1234
1235         instance_settings = VmInstanceSettings(
1236             name=self.vm_inst_name,
1237             flavor=self.flavor_creator.flavor_settings.name,
1238             port_settings=[port_settings])
1239
1240         self.inst_creator = OpenStackVmInstance(
1241             self.os_creds, instance_settings,
1242             self.image_creator.image_settings)
1243         self.inst_creator.create(block=True)
1244
1245         self.assertEqual(ip, self.inst_creator.get_port_ip(
1246             self.port_1_name,
1247             subnet_name=self.net_config.network_settings.subnet_settings[
1248                 0].name))
1249         self.assertEqual(mac_addr,
1250                          self.inst_creator.get_port_mac(self.port_1_name))
1251
1252     def test_set_allowed_address_pairs(self):
1253         """
1254         Tests the creation of an OpenStack instance with a single port where
1255         max_allowed_address_pair is set.
1256         """
1257         ip = '10.55.0.101'
1258         mac_addr = '0a:1b:2c:3d:4e:5f'
1259         pair = {'ip_address': ip, 'mac_address': mac_addr}
1260         port_settings = PortSettings(
1261             name=self.port_1_name,
1262             network_name=self.net_config.network_settings.name,
1263             allowed_address_pairs=[pair])
1264
1265         instance_settings = VmInstanceSettings(
1266             name=self.vm_inst_name,
1267             flavor=self.flavor_creator.flavor_settings.name,
1268             port_settings=[port_settings])
1269
1270         self.inst_creator = OpenStackVmInstance(
1271             self.os_creds, instance_settings,
1272             self.image_creator.image_settings)
1273         self.inst_creator.create(block=True)
1274
1275         port = self.inst_creator.get_port_by_name(port_settings.name)
1276         self.assertIsNotNone(port)
1277         self.assertIsNotNone(port.allowed_address_pairs)
1278         self.assertEqual(1, len(port.allowed_address_pairs))
1279         validation_utils.objects_equivalent(pair,
1280                                             port.allowed_address_pairs[0])
1281
1282     def test_set_allowed_address_pairs_bad_mac(self):
1283         """
1284         Tests the creation of an OpenStack instance with a single port where
1285         max_allowed_address_pair is set with an invalid MAC address.
1286         """
1287         ip = '10.55.0.101'
1288         mac_addr = 'foo'
1289         pair = {'ip_address': ip, 'mac_address': mac_addr}
1290         pairs = set()
1291         pairs.add((ip, mac_addr))
1292         port_settings = PortSettings(
1293             name=self.port_1_name,
1294             network_name=self.net_config.network_settings.name,
1295             allowed_address_pairs=[pair])
1296
1297         instance_settings = VmInstanceSettings(
1298             name=self.vm_inst_name,
1299             flavor=self.flavor_creator.flavor_settings.name,
1300             port_settings=[port_settings])
1301
1302         self.inst_creator = OpenStackVmInstance(
1303             self.os_creds, instance_settings,
1304             self.image_creator.image_settings)
1305         with self.assertRaises(Exception):
1306             self.inst_creator.create()
1307
1308     def test_set_allowed_address_pairs_bad_ip(self):
1309         """
1310         Tests the creation of an OpenStack instance with a single port where
1311         max_allowed_address_pair is set with an invalid MAC address.
1312         """
1313         ip = 'foo'
1314         mac_addr = '0a:1b:2c:3d:4e:5f'
1315         pair = {'ip_address': ip, 'mac_address': mac_addr}
1316         pairs = set()
1317         pairs.add((ip, mac_addr))
1318         port_settings = PortSettings(
1319             name=self.port_1_name,
1320             network_name=self.net_config.network_settings.name,
1321             allowed_address_pairs=[pair])
1322
1323         instance_settings = VmInstanceSettings(
1324             name=self.vm_inst_name,
1325             flavor=self.flavor_creator.flavor_settings.name,
1326             port_settings=[port_settings])
1327
1328         self.inst_creator = OpenStackVmInstance(
1329             self.os_creds, instance_settings,
1330             self.image_creator.image_settings)
1331         with self.assertRaises(Exception):
1332             self.inst_creator.create()
1333
1334
1335 class CreateInstanceOnComputeHost(OSIntegrationTestCase):
1336     """
1337     Test for the CreateInstance where one VM is deployed to each compute node
1338     """
1339
1340     def setUp(self):
1341         """
1342         Instantiates the CreateImage object that is responsible for downloading
1343         and creating an OS image file within OpenStack
1344         """
1345         super(self.__class__, self).__start__()
1346
1347         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1348         self.vm_inst_name = guid + '-inst'
1349         self.port_base_name = guid + 'port'
1350
1351         # Initialize for tearDown()
1352         self.image_creator = None
1353         self.flavor_creator = None
1354         self.network_creator = None
1355         self.inst_creators = list()
1356
1357         self.priv_net_config = openstack_tests.get_priv_net_config(
1358             net_name=guid + '-priv-net', subnet_name=guid + '-priv-subnet')
1359
1360         os_image_settings = openstack_tests.cirros_image_settings(
1361             name=guid + '-image', image_metadata=self.image_metadata)
1362
1363         try:
1364             # Create Network
1365             self.network_creator = OpenStackNetwork(
1366                 self.admin_os_creds, self.priv_net_config.network_settings)
1367             self.network_creator.create()
1368
1369             # Create Flavor
1370             self.flavor_creator = OpenStackFlavor(
1371                 self.admin_os_creds,
1372                 FlavorConfig(name=guid + '-flavor-name', ram=512, disk=1,
1373                              vcpus=1, metadata=self.flavor_metadata))
1374             self.flavor_creator.create()
1375
1376             # Create Image
1377             self.image_creator = OpenStackImage(self.os_creds,
1378                                                 os_image_settings)
1379             self.image_creator.create()
1380
1381         except Exception as e:
1382             self.tearDown()
1383             raise e
1384
1385     def tearDown(self):
1386         """
1387         Cleans the created object
1388         """
1389         for inst_creator in self.inst_creators:
1390             try:
1391                 inst_creator.clean()
1392             except Exception as e:
1393                 logger.error(
1394                     'Unexpected exception cleaning VM instance with message '
1395                     '- %s', e)
1396
1397         if self.flavor_creator:
1398             try:
1399                 self.flavor_creator.clean()
1400             except Exception as e:
1401                 logger.error(
1402                     'Unexpected exception cleaning flavor with message - %s',
1403                     e)
1404
1405         if self.network_creator:
1406             try:
1407                 self.network_creator.clean()
1408             except Exception as e:
1409                 logger.error(
1410                     'Unexpected exception cleaning network with message - %s',
1411                     e)
1412
1413         if self.image_creator and not self.image_creator.image_settings.exists:
1414             try:
1415                 self.image_creator.clean()
1416             except Exception as e:
1417                 logger.error(
1418                     'Unexpected exception cleaning image with message - %s', e)
1419
1420         super(self.__class__, self).__clean__()
1421
1422     def test_deploy_vm_to_each_compute_node(self):
1423         """
1424         Tests the creation of OpenStack VM instances to each compute node.
1425         """
1426         from snaps.openstack.utils import nova_utils
1427         nova = nova_utils.nova_client(self.admin_os_creds)
1428         zone_hosts = nova_utils.get_availability_zone_hosts(nova)
1429
1430         # Create Instance on each server/zone
1431         ctr = 0
1432         for zone in zone_hosts:
1433             inst_name = self.vm_inst_name + '-' + zone
1434             ctr += 1
1435             port_settings = PortSettings(
1436                 name=self.port_base_name + '-' + str(ctr),
1437                 network_name=self.priv_net_config.network_settings.name)
1438
1439             instance_settings = VmInstanceSettings(
1440                 name=inst_name,
1441                 flavor=self.flavor_creator.flavor_settings.name,
1442                 availability_zone=zone,
1443                 port_settings=[port_settings])
1444             inst_creator = OpenStackVmInstance(
1445                 self.admin_os_creds, instance_settings,
1446                 self.image_creator.image_settings)
1447             self.inst_creators.append(inst_creator)
1448             inst_creator.create()
1449
1450         # Validate instances to ensure they've been deployed to the correct
1451         # server
1452         index = 0
1453         for zone in zone_hosts:
1454             creator = self.inst_creators[index]
1455             self.assertTrue(creator.vm_active(block=True))
1456             info = creator.get_vm_info()
1457             deployed_zone = info['OS-EXT-AZ:availability_zone']
1458             deployed_host = info['OS-EXT-SRV-ATTR:host']
1459             self.assertEqual(zone, deployed_zone + ':' + deployed_host)
1460             index += 1
1461
1462
1463 class CreateInstancePubPrivNetTests(OSIntegrationTestCase):
1464     """
1465     Test for the CreateInstance class with two NIC/Ports, eth0 with floating IP
1466     and eth1 w/o.
1467     These tests require a Centos image
1468     """
1469
1470     def setUp(self):
1471         """
1472         Instantiates the CreateImage object that is responsible for downloading
1473         and creating an OS image file within OpenStack
1474         """
1475         super(self.__class__, self).__start__()
1476
1477         self.nova = nova_utils.nova_client(self.os_creds)
1478
1479         # Initialize for tearDown()
1480         self.image_creator = None
1481         self.network_creators = list()
1482         self.router_creators = list()
1483         self.flavor_creator = None
1484         self.keypair_creator = None
1485         self.sec_grp_creator = None
1486         self.inst_creator = None
1487
1488         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1489         self.keypair_priv_filepath = 'tmp/' + self.guid
1490         self.keypair_pub_filepath = self.keypair_priv_filepath + '.pub'
1491         self.keypair_name = self.guid + '-kp'
1492         self.vm_inst_name = self.guid + '-inst'
1493         self.port_1_name = self.guid + '-port-1'
1494         self.port_2_name = self.guid + '-port-2'
1495         self.floating_ip_name = self.guid + 'fip1'
1496         self.priv_net_config = openstack_tests.get_priv_net_config(
1497             net_name=self.guid + '-priv-net',
1498             subnet_name=self.guid + '-priv-subnet',
1499             router_name=self.guid + '-priv-router',
1500             external_net=self.ext_net_name)
1501         self.pub_net_config = openstack_tests.get_pub_net_config(
1502             net_name=self.guid + '-pub-net',
1503             subnet_name=self.guid + '-pub-subnet',
1504             router_name=self.guid + '-pub-router',
1505             external_net=self.ext_net_name)
1506
1507         image_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
1508         os_image_settings = openstack_tests.centos_image_settings(
1509             name=image_name, image_metadata=self.image_metadata)
1510
1511         try:
1512             # Create Image
1513             self.image_creator = OpenStackImage(self.os_creds,
1514                                                 os_image_settings)
1515             self.image_creator.create()
1516
1517             # First network is public
1518             self.network_creators.append(OpenStackNetwork(
1519                 self.os_creds, self.pub_net_config.network_settings))
1520             # Second network is private
1521             self.network_creators.append(OpenStackNetwork(
1522                 self.os_creds, self.priv_net_config.network_settings))
1523             for network_creator in self.network_creators:
1524                 network_creator.create()
1525
1526             self.router_creators.append(OpenStackRouter(
1527                 self.os_creds, self.pub_net_config.router_settings))
1528             self.router_creators.append(OpenStackRouter(
1529                 self.os_creds, self.priv_net_config.router_settings))
1530
1531             # Create Routers
1532             for router_creator in self.router_creators:
1533                 router_creator.create()
1534
1535             # Create Flavor
1536             self.flavor_creator = OpenStackFlavor(
1537                 self.admin_os_creds,
1538                 FlavorConfig(name=self.guid + '-flavor-name', ram=512,
1539                              disk=10, vcpus=2,
1540                              metadata=self.flavor_metadata))
1541             self.flavor_creator.create()
1542
1543             # Create Keypair
1544             self.keypair_creator = OpenStackKeypair(
1545                 self.os_creds, KeypairSettings(
1546                     name=self.keypair_name,
1547                     public_filepath=self.keypair_pub_filepath,
1548                     private_filepath=self.keypair_priv_filepath))
1549             self.keypair_creator.create()
1550
1551             sec_grp_name = self.guid + '-sec-grp'
1552             rule1 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
1553                                               direction=Direction.ingress,
1554                                               protocol=Protocol.icmp)
1555             rule2 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
1556                                               direction=Direction.ingress,
1557                                               protocol=Protocol.tcp,
1558                                               port_range_min=22,
1559                                               port_range_max=22)
1560             self.sec_grp_creator = OpenStackSecurityGroup(
1561                 self.os_creds,
1562                 SecurityGroupSettings(name=sec_grp_name,
1563                                       rule_settings=[rule1, rule2]))
1564             self.sec_grp_creator.create()
1565         except:
1566             self.tearDown()
1567             raise
1568
1569     def tearDown(self):
1570         """
1571         Cleans the created objects
1572         """
1573         if self.inst_creator:
1574             try:
1575                 self.inst_creator.clean()
1576             except Exception as e:
1577                 logger.error(
1578                     'Unexpected exception cleaning VM instance with message '
1579                     '- %s', e)
1580
1581         if self.keypair_creator:
1582             try:
1583                 self.keypair_creator.clean()
1584             except Exception as e:
1585                 logger.error(
1586                     'Unexpected exception cleaning keypair with message - %s',
1587                     e)
1588
1589         if self.flavor_creator:
1590             try:
1591                 self.flavor_creator.clean()
1592             except Exception as e:
1593                 logger.error(
1594                     'Unexpected exception cleaning flavor with message - %s',
1595                     e)
1596
1597         for router_creator in self.router_creators:
1598             try:
1599                 router_creator.clean()
1600             except Exception as e:
1601                 logger.error(
1602                     'Unexpected exception cleaning router with message - %s',
1603                     e)
1604
1605         for network_creator in self.network_creators:
1606             try:
1607                 network_creator.clean()
1608             except Exception as e:
1609                 logger.error(
1610                     'Unexpected exception cleaning network with message - %s',
1611                     e)
1612
1613         if self.sec_grp_creator:
1614             try:
1615                 self.sec_grp_creator.clean()
1616             except Exception as e:
1617                 logger.error(
1618                     'Unexpected exception cleaning security group with message'
1619                     ' - %s', e)
1620
1621         if self.image_creator and not self.image_creator.image_settings.exists:
1622             try:
1623                 self.image_creator.clean()
1624             except Exception as e:
1625                 logger.error(
1626                     'Unexpected exception cleaning image with message - %s', e)
1627
1628         super(self.__class__, self).__clean__()
1629
1630     def test_dual_ports_dhcp(self):
1631         """
1632         Tests the creation of an OpenStack instance with a dual ports/NICs with
1633         a DHCP assigned IP.
1634         NOTE: This test and any others that call ansible will most likely fail
1635         unless you do one of two things:
1636         1. Have a ~/.ansible.cfg (or alternate means) to
1637            set host_key_checking = False
1638         2. Set the following environment variable in your executing shell:
1639            ANSIBLE_HOST_KEY_CHECKING=False
1640         Should this not be performed, the creation of the host ssh key will
1641         cause your ansible calls to fail.
1642         """
1643         # Create ports/NICs for instance
1644         ports_settings = []
1645         ctr = 1
1646         for network_creator in self.network_creators:
1647             ports_settings.append(PortSettings(
1648                 name=self.guid + '-port-' + str(ctr),
1649                 network_name=network_creator.network_settings.name))
1650             ctr += 1
1651
1652         # Create instance
1653         instance_settings = VmInstanceSettings(
1654             name=self.vm_inst_name,
1655             flavor=self.flavor_creator.flavor_settings.name,
1656             port_settings=ports_settings,
1657             security_group_names=[self.sec_grp_creator.sec_grp_settings.name],
1658             floating_ip_settings=[FloatingIpSettings(
1659                 name=self.floating_ip_name, port_name=self.port_1_name,
1660                 router_name=self.pub_net_config.router_settings.name)])
1661
1662         self.inst_creator = OpenStackVmInstance(
1663             self.os_creds, instance_settings,
1664             self.image_creator.image_settings,
1665             keypair_settings=self.keypair_creator.keypair_settings)
1666
1667         vm_inst = self.inst_creator.create(block=True)
1668
1669         self.assertEqual(vm_inst.id, self.inst_creator.get_vm_inst().id)
1670
1671         # Effectively blocks until VM has been properly activated
1672         self.assertTrue(self.inst_creator.vm_active(block=True))
1673
1674         ip = self.inst_creator.get_port_ip(ports_settings[0].name)
1675         self.assertTrue(check_dhcp_lease(self.inst_creator, ip))
1676
1677         # Effectively blocks until VM's ssh port has been opened
1678         self.assertTrue(self.inst_creator.vm_ssh_active(block=True))
1679
1680         self.assertEqual(0, self.inst_creator.config_nics())
1681
1682
1683 class InstanceSecurityGroupTests(OSIntegrationTestCase):
1684     """
1685     Tests that include, add, and remove security groups from VM instances
1686     """
1687
1688     def setUp(self):
1689         """
1690         Instantiates the CreateImage object that is responsible for downloading
1691         and creating an OS image file within OpenStack
1692         """
1693         super(self.__class__, self).__start__()
1694
1695         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
1696         self.vm_inst_name = self.guid + '-inst'
1697         self.nova = nova_utils.nova_client(self.os_creds)
1698         os_image_settings = openstack_tests.cirros_image_settings(
1699             name=self.guid + '-image', image_metadata=self.image_metadata)
1700
1701         self.vm_inst_name = self.guid + '-inst'
1702         self.port_1_name = self.guid + 'port-1'
1703         self.port_2_name = self.guid + 'port-2'
1704         self.floating_ip_name = self.guid + 'fip1'
1705
1706         net_config = openstack_tests.get_priv_net_config(
1707             net_name=self.guid + '-pub-net',
1708             subnet_name=self.guid + '-pub-subnet',
1709             router_name=self.guid + '-pub-router',
1710             external_net=self.ext_net_name)
1711
1712         # Initialize for tearDown()
1713         self.image_creator = None
1714         self.flavor_creator = None
1715         self.network_creator = None
1716         self.router_creator = None
1717         self.inst_creator = None
1718         self.sec_grp_creators = list()
1719
1720         try:
1721             # Create Image
1722             self.image_creator = OpenStackImage(self.os_creds,
1723                                                 os_image_settings)
1724             self.image_creator.create()
1725
1726             # Create Network
1727             self.network_creator = OpenStackNetwork(
1728                 self.os_creds, net_config.network_settings)
1729             self.network_creator.create()
1730
1731             # Create Flavor
1732             self.flavor_creator = OpenStackFlavor(
1733                 self.admin_os_creds,
1734                 FlavorConfig(name=self.guid + '-flavor-name', ram=256,
1735                              disk=10, vcpus=2,
1736                              metadata=self.flavor_metadata))
1737             self.flavor_creator.create()
1738
1739             self.port_settings = PortSettings(
1740                 name=self.guid + '-port',
1741                 network_name=net_config.network_settings.name)
1742         except Exception as e:
1743             self.tearDown()
1744             raise e
1745
1746     def tearDown(self):
1747         """
1748         Cleans the created object
1749         """
1750         if self.inst_creator:
1751             try:
1752                 self.inst_creator.clean()
1753             except Exception as e:
1754                 logger.error(
1755                     'Unexpected exception cleaning VM instance with message -'
1756                     ' %s', e)
1757
1758         for sec_grp_creator in self.sec_grp_creators:
1759             try:
1760                 sec_grp_creator.clean()
1761             except Exception as e:
1762                 logger.error(
1763                     'Unexpected exception cleaning security group with message'
1764                     ' - %s', e)
1765
1766         if self.flavor_creator:
1767             try:
1768                 self.flavor_creator.clean()
1769             except Exception as e:
1770                 logger.error(
1771                     'Unexpected exception cleaning flavor with message - %s',
1772                     e)
1773
1774         if self.network_creator:
1775             try:
1776                 self.network_creator.clean()
1777             except Exception as e:
1778                 logger.error(
1779                     'Unexpected exception cleaning network with message - %s',
1780                     e)
1781
1782         if self.image_creator and not self.image_creator.image_settings.exists:
1783             try:
1784                 self.image_creator.clean()
1785             except Exception as e:
1786                 logger.error(
1787                     'Unexpected exception cleaning image with message - %s', e)
1788
1789         super(self.__class__, self).__clean__()
1790
1791     def test_add_security_group(self):
1792         """
1793         Tests the addition of a security group created after the instance.
1794         """
1795         # Create instance
1796         instance_settings = VmInstanceSettings(
1797             name=self.vm_inst_name,
1798             flavor=self.flavor_creator.flavor_settings.name,
1799             port_settings=[self.port_settings])
1800         self.inst_creator = OpenStackVmInstance(
1801             self.os_creds, instance_settings,
1802             self.image_creator.image_settings)
1803         vm_inst = self.inst_creator.create(block=True)
1804         self.assertIsNotNone(vm_inst)
1805
1806         # Create security group object to add to instance
1807         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1808                                                  description='hello group')
1809         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1810                                                  sec_grp_settings)
1811         sec_grp = sec_grp_creator.create()
1812         self.sec_grp_creators.append(sec_grp_creator)
1813
1814         # Check that group has not been added
1815         self.assertFalse(inst_has_sec_grp(
1816             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1817
1818         # Add security group to instance after activated
1819         self.inst_creator.add_security_group(sec_grp)
1820
1821         # Validate that security group has been added
1822         self.assertTrue(inst_has_sec_grp(
1823             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1824
1825     def test_add_invalid_security_group(self):
1826         """
1827         Tests the addition of a security group that no longer exists.
1828         """
1829         # Create instance
1830         instance_settings = VmInstanceSettings(
1831             name=self.vm_inst_name,
1832             flavor=self.flavor_creator.flavor_settings.name,
1833             port_settings=[self.port_settings])
1834         self.inst_creator = OpenStackVmInstance(
1835             self.os_creds, instance_settings,
1836             self.image_creator.image_settings)
1837         vm_inst = self.inst_creator.create(block=True)
1838         self.assertIsNotNone(vm_inst)
1839
1840         # Create security group object to add to instance
1841         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1842                                                  description='hello group')
1843         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1844                                                  sec_grp_settings)
1845         sec_grp = sec_grp_creator.create()
1846         sec_grp_creator.clean()
1847         self.sec_grp_creators.append(sec_grp_creator)
1848
1849         # Check that group has not been added
1850         self.assertFalse(inst_has_sec_grp(
1851             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1852
1853         # Add security group to instance after activated
1854         self.assertFalse(self.inst_creator.add_security_group(sec_grp))
1855
1856         # Validate that security group has been added
1857         self.assertFalse(inst_has_sec_grp(
1858             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1859
1860     def test_remove_security_group(self):
1861         """
1862         Tests the removal of a security group created before and added to the
1863         instance.
1864         """
1865         # Create security group object to add to instance
1866         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1867                                                  description='hello group')
1868         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1869                                                  sec_grp_settings)
1870         sec_grp = sec_grp_creator.create()
1871         self.sec_grp_creators.append(sec_grp_creator)
1872
1873         # Create instance
1874         instance_settings = VmInstanceSettings(
1875             name=self.vm_inst_name,
1876             flavor=self.flavor_creator.flavor_settings.name,
1877             security_group_names=[sec_grp_settings.name],
1878             port_settings=[self.port_settings])
1879         self.inst_creator = OpenStackVmInstance(
1880             self.os_creds, instance_settings,
1881             self.image_creator.image_settings)
1882         vm_inst = self.inst_creator.create(block=True)
1883         self.assertIsNotNone(vm_inst)
1884
1885         # Check that group has been added
1886         self.assertTrue(inst_has_sec_grp(
1887             self.nova, vm_inst, sec_grp_settings.name))
1888
1889         # Add security group to instance after activated
1890         self.assertTrue(self.inst_creator.remove_security_group(sec_grp))
1891
1892         # Validate that security group has been added
1893         self.assertFalse(inst_has_sec_grp(
1894             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1895
1896     def test_remove_security_group_never_added(self):
1897         """
1898         Tests the removal of a security group that was never added in the first
1899         place.
1900         """
1901         # Create security group object to add to instance
1902         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1903                                                  description='hello group')
1904         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1905                                                  sec_grp_settings)
1906         sec_grp = sec_grp_creator.create()
1907         self.sec_grp_creators.append(sec_grp_creator)
1908
1909         # Create instance
1910         instance_settings = VmInstanceSettings(
1911             name=self.vm_inst_name,
1912             flavor=self.flavor_creator.flavor_settings.name,
1913             port_settings=[self.port_settings])
1914         self.inst_creator = OpenStackVmInstance(
1915             self.os_creds, instance_settings,
1916             self.image_creator.image_settings)
1917         vm_inst = self.inst_creator.create(block=True)
1918         self.assertIsNotNone(vm_inst)
1919
1920         # Check that group has been added
1921         self.assertFalse(inst_has_sec_grp(
1922             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1923
1924         # Add security group to instance after activated
1925         self.assertFalse(self.inst_creator.remove_security_group(sec_grp))
1926
1927         # Validate that security group has been added
1928         self.assertFalse(inst_has_sec_grp(
1929             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1930
1931     def test_add_same_security_group(self):
1932         """
1933         Tests the addition of a security group created before add added to the
1934         instance.
1935         """
1936         # Create security group object to add to instance
1937         sec_grp_settings = SecurityGroupSettings(name=self.guid + '-name',
1938                                                  description='hello group')
1939         sec_grp_creator = OpenStackSecurityGroup(self.os_creds,
1940                                                  sec_grp_settings)
1941         sec_grp = sec_grp_creator.create()
1942         self.sec_grp_creators.append(sec_grp_creator)
1943
1944         # Create instance
1945         instance_settings = VmInstanceSettings(
1946             name=self.vm_inst_name,
1947             flavor=self.flavor_creator.flavor_settings.name,
1948             security_group_names=[sec_grp_settings.name],
1949             port_settings=[self.port_settings])
1950         self.inst_creator = OpenStackVmInstance(
1951             self.os_creds, instance_settings,
1952             self.image_creator.image_settings)
1953         vm_inst = self.inst_creator.create(block=True)
1954         self.assertIsNotNone(vm_inst)
1955
1956         # Check that group has been added
1957         self.assertTrue(inst_has_sec_grp(
1958             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1959
1960         # Add security group to instance after activated
1961         self.assertTrue(self.inst_creator.add_security_group(sec_grp))
1962
1963         # Validate that security group has been added
1964         self.assertTrue(inst_has_sec_grp(
1965             self.nova, self.inst_creator.get_vm_inst(), sec_grp_settings.name))
1966
1967
1968 def inst_has_sec_grp(nova, vm_inst, sec_grp_name):
1969     """
1970     Returns true if instance has a security group of a given name
1971     :param nova: the nova client
1972     :param vm_inst: the VmInst domain object
1973     :param sec_grp_name: the name of the security group to validate
1974     :return: T/F
1975     """
1976     sec_grp_names = nova_utils.get_server_security_group_names(nova, vm_inst)
1977     for name in sec_grp_names:
1978         if sec_grp_name == name:
1979             return True
1980     return False
1981
1982
1983 def validate_ssh_client(instance_creator):
1984     """
1985     Returns True if instance_creator returns an SSH client that is valid
1986     :param instance_creator: the object responsible for creating the VM
1987                              instance
1988     :return: T/F
1989     """
1990     ssh_active = instance_creator.vm_ssh_active(block=True)
1991
1992     if ssh_active:
1993         ssh_client = instance_creator.ssh_client()
1994         if ssh_client:
1995             try:
1996                 out = ssh_client.exec_command('pwd')[1]
1997                 channel = out.channel
1998                 in_buffer = channel.in_buffer
1999                 pwd_out = in_buffer.read(1024)
2000                 if not pwd_out or len(pwd_out) < 10:
2001                     return False
2002                 return True
2003             finally:
2004                 ssh_client.close()
2005         else:
2006             return False
2007
2008     return False
2009
2010
2011 class CreateInstanceFromThreePartImage(OSIntegrationTestCase):
2012     """
2013     Test for the CreateInstance class for creating an image from a 3-part image
2014     """
2015
2016     def setUp(self):
2017         """
2018         Instantiates the CreateImage object that is responsible for downloading
2019         and creating an OS image file within OpenStack
2020         """
2021         super(self.__class__, self).__start__()
2022
2023         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
2024         self.image_name = guid
2025         self.vm_inst_name = guid + '-inst'
2026         self.nova = nova_utils.nova_client(self.os_creds)
2027
2028         net_config = openstack_tests.get_priv_net_config(
2029             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
2030             router_name=guid + '-pub-router', external_net=self.ext_net_name)
2031
2032         # Initialize for tearDown()
2033         self.image_creator = None
2034         self.network_creator = None
2035         self.flavor_creator = None
2036         self.inst_creator = None
2037
2038         try:
2039             if self.image_metadata and 'disk_file' in self.image_metadata:
2040                 metadata = self.image_metadata
2041             elif self.image_metadata and 'cirros' in self.image_metadata \
2042                     and 'disk_file' in self.image_metadata['cirros']:
2043                 metadata = self.image_metadata['cirros']
2044             else:
2045                 metadata = {
2046                     'disk_url': openstack_tests.CIRROS_DEFAULT_IMAGE_URL,
2047                     'kernel_url':
2048                         openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL,
2049                     'ramdisk_url':
2050                         openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL}
2051
2052             image_settings = openstack_tests.cirros_image_settings(
2053                 name=self.image_name,
2054                 image_metadata=metadata)
2055
2056             if not image_settings.ramdisk_image_settings or not \
2057                     image_settings.kernel_image_settings:
2058                 logger.warn(
2059                     '3 Part image will not be tested. Image metadata has '
2060                     'overridden this functionality')
2061
2062             self.image_creator = OpenStackImage(self.os_creds, image_settings)
2063             self.image_creator.create()
2064
2065             # Create Flavor
2066             self.flavor_creator = OpenStackFlavor(
2067                 self.admin_os_creds,
2068                 FlavorConfig(name=guid + '-flavor-name', ram=256, disk=10,
2069                              vcpus=2, metadata=self.flavor_metadata))
2070             self.flavor_creator.create()
2071
2072             # Create Network
2073             self.network_creator = OpenStackNetwork(
2074                 self.os_creds, net_config.network_settings)
2075             self.network_creator.create()
2076
2077             self.port_settings = PortSettings(
2078                 name=guid + '-port',
2079                 network_name=net_config.network_settings.name)
2080         except Exception as e:
2081             self.tearDown()
2082             raise e
2083
2084     def tearDown(self):
2085         """
2086         Cleans the created object
2087         """
2088         if self.inst_creator:
2089             try:
2090                 self.inst_creator.clean()
2091             except Exception as e:
2092                 logger.error(
2093                     'Unexpected exception cleaning VM instance with message -'
2094                     ' %s', e)
2095
2096         if self.flavor_creator:
2097             try:
2098                 self.flavor_creator.clean()
2099             except Exception as e:
2100                 logger.error(
2101                     'Unexpected exception cleaning flavor with message - %s',
2102                     e)
2103
2104         if self.network_creator:
2105             try:
2106                 self.network_creator.clean()
2107             except Exception as e:
2108                 logger.error(
2109                     'Unexpected exception cleaning network with message - %s',
2110                     e)
2111
2112         if self.image_creator and not self.image_creator.image_settings.exists:
2113             try:
2114                 self.image_creator.clean()
2115             except Exception as e:
2116                 logger.error(
2117                     'Unexpected exception cleaning image with message - %s', e)
2118
2119         super(self.__class__, self).__clean__()
2120
2121     def test_create_instance_from_three_part_image(self):
2122         """
2123         Tests the creation of an OpenStack instance from a 3-part image.
2124         """
2125         instance_settings = VmInstanceSettings(
2126             name=self.vm_inst_name,
2127             flavor=self.flavor_creator.flavor_settings.name,
2128             port_settings=[self.port_settings])
2129
2130         # The last created image is the main image from which we create the
2131         # instance
2132         self.inst_creator = OpenStackVmInstance(
2133             self.os_creds, instance_settings,
2134             self.image_creator.image_settings)
2135
2136         vm_inst = self.inst_creator.create()
2137         self.assertIsNotNone(vm_inst)
2138         self.assertTrue(self.inst_creator.vm_active(block=True))
2139
2140
2141 class CreateInstanceMockOfflineTests(OSComponentTestCase):
2142     """
2143     Tests the custom image_metadata that can be set by clients for handling
2144     images differently than the default behavior of the existing tests
2145     primarily for offline testing
2146     """
2147
2148     def setUp(self):
2149         """
2150         Instantiates the CreateImage object that is responsible for downloading
2151         and creating an OS image file within OpenStack
2152         """
2153         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
2154
2155         self.tmpDir = 'tmp/' + str(self.guid)
2156         if not os.path.exists(self.tmpDir):
2157             os.makedirs(self.tmpDir)
2158
2159         self.image_name = self.guid + '-image'
2160         self.vm_inst_name = self.guid + '-inst'
2161         self.port_1_name = self.guid + 'port-1'
2162
2163         # Initialize for tearDown()
2164         self.image_creator = None
2165         self.network_creator = None
2166         self.flavor_creator = None
2167         self.inst_creator = None
2168
2169         self.priv_net_config = openstack_tests.get_priv_net_config(
2170             net_name=self.guid + '-priv-net',
2171             subnet_name=self.guid + '-priv-subnet')
2172         self.port_settings = PortSettings(
2173             name=self.port_1_name,
2174             network_name=self.priv_net_config.network_settings.name)
2175
2176         try:
2177             # Download image file
2178             self.image_file = file_utils.download(
2179                 openstack_tests.CIRROS_DEFAULT_IMAGE_URL, self.tmpDir)
2180
2181             # Create Network
2182             self.network_creator = OpenStackNetwork(
2183                 self.os_creds, self.priv_net_config.network_settings)
2184             self.network_creator.create()
2185
2186             # Create Flavor
2187             self.flavor_creator = OpenStackFlavor(
2188                 self.os_creds,
2189                 FlavorConfig(
2190                     name=self.guid + '-flavor-name', ram=256, disk=10,
2191                     vcpus=1))
2192             self.flavor_creator.create()
2193         except Exception as e:
2194             self.tearDown()
2195             raise e
2196
2197     def tearDown(self):
2198         """
2199         Cleans the created object
2200         """
2201         if self.inst_creator:
2202             try:
2203                 self.inst_creator.clean()
2204             except Exception as e:
2205                 logger.error(
2206                     'Unexpected exception cleaning VM instance with message - '
2207                     '%s', e)
2208
2209         if self.network_creator:
2210             try:
2211                 self.network_creator.clean()
2212             except Exception as e:
2213                 logger.error(
2214                     'Unexpected exception cleaning network with message - %s',
2215                     e)
2216
2217         if self.flavor_creator:
2218             try:
2219                 self.flavor_creator.clean()
2220             except Exception as e:
2221                 logger.error(
2222                     'Unexpected exception cleaning flavor with message - %s',
2223                     e)
2224
2225         if self.image_creator:
2226             try:
2227                 self.image_creator.clean()
2228             except Exception as e:
2229                 logger.error(
2230                     'Unexpected exception cleaning image with message - %s', e)
2231
2232         if os.path.exists(self.tmpDir) and os.path.isdir(self.tmpDir):
2233             shutil.rmtree(self.tmpDir)
2234
2235     def test_inst_from_file_image_simple_flat(self):
2236         """
2237         Creates a VM instance from a locally sourced file image using simply
2238         the 'disk_file' attribute vs. using the 'config' option which
2239         completely overrides all image settings
2240         :return: 
2241         """
2242         metadata = {'disk_file': self.image_file.name}
2243
2244         os_image_settings = openstack_tests.cirros_image_settings(
2245             name=self.image_name, image_metadata=metadata)
2246         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2247         self.assertEqual(openstack_tests.CIRROS_USER,
2248                          os_image_settings.image_user)
2249         self.assertIsNone(os_image_settings.url)
2250         self.assertFalse(os_image_settings.exists)
2251         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2252                          os_image_settings.format)
2253
2254         self.assertIsNone(os_image_settings.kernel_image_settings)
2255         self.assertIsNone(os_image_settings.ramdisk_image_settings)
2256
2257         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2258         self.image_creator.create()
2259
2260         instance_settings = VmInstanceSettings(
2261             name=self.vm_inst_name,
2262             flavor=self.flavor_creator.flavor_settings.name,
2263             port_settings=[self.port_settings])
2264         self.inst_creator = OpenStackVmInstance(
2265             self.os_creds, instance_settings,
2266             self.image_creator.image_settings)
2267         self.inst_creator.create()
2268
2269         self.assertTrue(self.inst_creator.vm_active(block=True))
2270
2271     def test_inst_from_file_image_simple_nested(self):
2272         """
2273         Creates a VM instance from a locally sourced file image using simply
2274         the 'disk_file' attribute under 'cirros' vs. using the 'config' option
2275         which completely overrides all image settings
2276         :return: 
2277         """
2278         metadata = {'cirros': {'disk_file': self.image_file.name}}
2279
2280         os_image_settings = openstack_tests.cirros_image_settings(
2281             name=self.image_name, image_metadata=metadata)
2282         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2283         self.assertEqual(openstack_tests.CIRROS_USER,
2284                          os_image_settings.image_user)
2285         self.assertIsNone(os_image_settings.url)
2286         self.assertFalse(os_image_settings.exists)
2287         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2288                          os_image_settings.format)
2289
2290         self.assertIsNone(os_image_settings.kernel_image_settings)
2291         self.assertIsNone(os_image_settings.ramdisk_image_settings)
2292
2293         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2294         self.image_creator.create()
2295
2296         instance_settings = VmInstanceSettings(
2297             name=self.vm_inst_name,
2298             flavor=self.flavor_creator.flavor_settings.name,
2299             port_settings=[self.port_settings])
2300         self.inst_creator = OpenStackVmInstance(
2301             self.os_creds, instance_settings,
2302             self.image_creator.image_settings)
2303         self.inst_creator.create()
2304
2305         self.assertTrue(self.inst_creator.vm_active(block=True))
2306
2307     def test_inst_from_existing(self):
2308         """
2309         Creates a VM instance from a image creator that has been configured to
2310         use an existing image
2311         :return: 
2312         """
2313         os_image_settings = openstack_tests.cirros_image_settings(
2314             name=self.image_name)
2315         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2316         self.image_creator.create()
2317
2318         image_settings = self.image_creator.image_settings
2319         test_image_creator = OpenStackImage(
2320             self.os_creds,
2321             ImageConfig(
2322                 name=image_settings.name, image_user=image_settings.image_user,
2323                 exists=True))
2324         test_image_creator.create()
2325         self.assertEqual(self.image_creator.get_image().id,
2326                          test_image_creator.get_image().id)
2327
2328         instance_settings = VmInstanceSettings(
2329             name=self.vm_inst_name,
2330             flavor=self.flavor_creator.flavor_settings.name,
2331             port_settings=[self.port_settings])
2332         self.inst_creator = OpenStackVmInstance(
2333             self.os_creds, instance_settings,
2334             test_image_creator.image_settings)
2335         self.inst_creator.create()
2336
2337         self.assertTrue(self.inst_creator.vm_active(block=True))
2338
2339     def test_inst_from_file_image_complex(self):
2340         """
2341         Creates a VM instance from a locally sourced file image by overriding
2342         the default settings by using a dict() that can be read in by
2343         ImageSettings
2344         :return: 
2345         """
2346
2347         os_image_settings = openstack_tests.cirros_image_settings(
2348             name=self.image_name)
2349         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2350         self.image_creator.create()
2351
2352         metadata = {
2353             'cirros': {
2354                 'config': {
2355                     'name': os_image_settings.name,
2356                     'image_user': os_image_settings.image_user,
2357                     'exists': True}}}
2358         test_image_settings = openstack_tests.cirros_image_settings(
2359             image_metadata=metadata)
2360         test_image = OpenStackImage(self.os_creds, test_image_settings)
2361         test_image.create()
2362
2363         instance_settings = VmInstanceSettings(
2364             name=self.vm_inst_name,
2365             flavor=self.flavor_creator.flavor_settings.name,
2366             port_settings=[self.port_settings])
2367         self.inst_creator = OpenStackVmInstance(self.os_creds,
2368                                                 instance_settings,
2369                                                 test_image_settings)
2370         self.inst_creator.create()
2371
2372         self.assertTrue(self.inst_creator.vm_active(block=True))
2373
2374     def test_inst_from_file_3part_image_complex(self):
2375         """
2376         Creates a VM instance from a locally sourced file image by overriding
2377         the default settings by using a dict() that can be read in by
2378         ImageSettings
2379         :return: 
2380         """
2381
2382         kernel_file = file_utils.download(
2383             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2384         ramdisk_file = file_utils.download(
2385             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2386
2387         metadata = {
2388             'cirros': {
2389                 'config': {
2390                     'name': self.image_name,
2391                     'image_user': openstack_tests.CIRROS_USER,
2392                     'image_file': self.image_file.name,
2393                     'format': openstack_tests.DEFAULT_IMAGE_FORMAT,
2394                     'kernel_image_settings': {
2395                         'name': self.image_name + '-kernel',
2396                         'image_user': openstack_tests.CIRROS_USER,
2397                         'image_file': kernel_file.name,
2398                         'format': openstack_tests.DEFAULT_IMAGE_FORMAT},
2399                     'ramdisk_image_settings': {
2400                         'name': self.image_name + '-ramdisk',
2401                         'image_user': openstack_tests.CIRROS_USER,
2402                         'image_file': ramdisk_file.name,
2403                         'format': openstack_tests.DEFAULT_IMAGE_FORMAT}}}}
2404
2405         os_image_settings = openstack_tests.cirros_image_settings(
2406             name=self.image_name, image_metadata=metadata)
2407         self.assertEqual(self.image_name, os_image_settings.name)
2408         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2409         self.assertEqual(openstack_tests.CIRROS_USER,
2410                          os_image_settings.image_user)
2411         self.assertIsNone(os_image_settings.url)
2412         self.assertFalse(os_image_settings.exists)
2413         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2414                          os_image_settings.format)
2415
2416         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2417         self.assertEqual(self.image_name + '-kernel',
2418                          os_image_settings.kernel_image_settings.name)
2419         self.assertEqual(kernel_file.name,
2420                          os_image_settings.kernel_image_settings.image_file)
2421         self.assertEqual(openstack_tests.CIRROS_USER,
2422                          os_image_settings.kernel_image_settings.image_user)
2423         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2424         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2425         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2426                          os_image_settings.kernel_image_settings.format)
2427
2428         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2429         self.assertEqual(self.image_name + '-ramdisk',
2430                          os_image_settings.ramdisk_image_settings.name)
2431         self.assertEqual(ramdisk_file.name,
2432                          os_image_settings.ramdisk_image_settings.image_file)
2433         self.assertEqual(openstack_tests.CIRROS_USER,
2434                          os_image_settings.ramdisk_image_settings.image_user)
2435         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2436         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2437         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2438                          os_image_settings.ramdisk_image_settings.format)
2439
2440         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2441         self.image_creator.create()
2442
2443         instance_settings = VmInstanceSettings(
2444             name=self.vm_inst_name,
2445             flavor=self.flavor_creator.flavor_settings.name,
2446             port_settings=[self.port_settings])
2447         self.inst_creator = OpenStackVmInstance(
2448             self.os_creds, instance_settings,
2449             self.image_creator.image_settings)
2450         self.inst_creator.create()
2451
2452         self.assertTrue(self.inst_creator.vm_active(block=True))
2453
2454     def test_inst_from_file_3part_image_simple_flat(self):
2455         """
2456         Creates a VM instance from a 3-part image locally sourced from file
2457         images using simply the 'disk_file', 'kernel_file', and 'ramdisk_file'
2458         attributes vs. using the 'config' option which completely overrides all
2459         image settings
2460         :return: 
2461         """
2462         kernel_file = file_utils.download(
2463             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2464         ramdisk_file = file_utils.download(
2465             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2466
2467         metadata = {'disk_file': self.image_file.name,
2468                     'kernel_file': kernel_file.name,
2469                     'ramdisk_file': ramdisk_file.name}
2470
2471         os_image_settings = openstack_tests.cirros_image_settings(
2472             name=self.image_name, image_metadata=metadata)
2473
2474         self.assertEqual(self.image_name, os_image_settings.name)
2475         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2476         self.assertEqual(openstack_tests.CIRROS_USER,
2477                          os_image_settings.image_user)
2478         self.assertIsNone(os_image_settings.url)
2479         self.assertFalse(os_image_settings.exists)
2480         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2481                          os_image_settings.format)
2482
2483         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2484         self.assertEqual(self.image_name + '-kernel',
2485                          os_image_settings.kernel_image_settings.name)
2486         self.assertEqual(kernel_file.name,
2487                          os_image_settings.kernel_image_settings.image_file)
2488         self.assertEqual(openstack_tests.CIRROS_USER,
2489                          os_image_settings.kernel_image_settings.image_user)
2490         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2491         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2492         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2493                          os_image_settings.kernel_image_settings.format)
2494
2495         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2496         self.assertEqual(self.image_name + '-ramdisk',
2497                          os_image_settings.ramdisk_image_settings.name)
2498         self.assertEqual(ramdisk_file.name,
2499                          os_image_settings.ramdisk_image_settings.image_file)
2500         self.assertEqual(openstack_tests.CIRROS_USER,
2501                          os_image_settings.ramdisk_image_settings.image_user)
2502         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2503         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2504         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2505                          os_image_settings.ramdisk_image_settings.format)
2506
2507         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2508         self.image_creator.create()
2509
2510         self.assertIsNotNone(self.image_creator.get_kernel_image())
2511         self.assertIsNotNone(self.image_creator.get_ramdisk_image())
2512
2513         instance_settings = VmInstanceSettings(
2514             name=self.vm_inst_name,
2515             flavor=self.flavor_creator.flavor_settings.name,
2516             port_settings=[self.port_settings])
2517         self.inst_creator = OpenStackVmInstance(
2518             self.os_creds, instance_settings,
2519             self.image_creator.image_settings)
2520         self.inst_creator.create()
2521
2522         self.assertTrue(self.inst_creator.vm_active(block=True))
2523
2524     def test_inst_from_file_3part_image_simple_nested(self):
2525         """
2526         Creates a VM instance from a 3-part image locally sourced from file
2527         images using simply the 'disk_file', 'kernel_file', and 'ramdisk_file'
2528         attributes under 'cirros' vs. using the 'config' option which
2529         completely overrides all image settings
2530         :return: 
2531         """
2532         kernel_file = file_utils.download(
2533             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2534         ramdisk_file = file_utils.download(
2535             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2536
2537         metadata = {'cirros': {'disk_file': self.image_file.name,
2538                                'kernel_file': kernel_file.name,
2539                                'ramdisk_file': ramdisk_file.name}}
2540
2541         os_image_settings = openstack_tests.cirros_image_settings(
2542             name=self.image_name, image_metadata=metadata)
2543
2544         self.assertEqual(self.image_name, os_image_settings.name)
2545         self.assertEqual(self.image_file.name, os_image_settings.image_file)
2546         self.assertEqual(openstack_tests.CIRROS_USER,
2547                          os_image_settings.image_user)
2548         self.assertIsNone(os_image_settings.url)
2549         self.assertFalse(os_image_settings.exists)
2550         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2551                          os_image_settings.format)
2552
2553         self.assertIsNotNone(os_image_settings.kernel_image_settings)
2554         self.assertEqual(self.image_name + '-kernel',
2555                          os_image_settings.kernel_image_settings.name)
2556         self.assertEqual(kernel_file.name,
2557                          os_image_settings.kernel_image_settings.image_file)
2558         self.assertEqual(openstack_tests.CIRROS_USER,
2559                          os_image_settings.kernel_image_settings.image_user)
2560         self.assertIsNone(os_image_settings.kernel_image_settings.url)
2561         self.assertFalse(os_image_settings.kernel_image_settings.exists)
2562         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2563                          os_image_settings.kernel_image_settings.format)
2564
2565         self.assertIsNotNone(os_image_settings.ramdisk_image_settings)
2566         self.assertEqual(self.image_name + '-ramdisk',
2567                          os_image_settings.ramdisk_image_settings.name)
2568         self.assertEqual(ramdisk_file.name,
2569                          os_image_settings.ramdisk_image_settings.image_file)
2570         self.assertEqual(openstack_tests.CIRROS_USER,
2571                          os_image_settings.ramdisk_image_settings.image_user)
2572         self.assertIsNone(os_image_settings.ramdisk_image_settings.url)
2573         self.assertFalse(os_image_settings.ramdisk_image_settings.exists)
2574         self.assertEqual(openstack_tests.DEFAULT_IMAGE_FORMAT,
2575                          os_image_settings.ramdisk_image_settings.format)
2576
2577         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2578         self.image_creator.create()
2579
2580         self.assertIsNotNone(self.image_creator.get_kernel_image())
2581         self.assertIsNotNone(self.image_creator.get_ramdisk_image())
2582
2583         instance_settings = VmInstanceSettings(
2584             name=self.vm_inst_name,
2585             flavor=self.flavor_creator.flavor_settings.name,
2586             port_settings=[self.port_settings])
2587         self.inst_creator = OpenStackVmInstance(
2588             self.os_creds, instance_settings,
2589             self.image_creator.image_settings)
2590         self.inst_creator.create()
2591
2592         self.assertTrue(self.inst_creator.vm_active(block=True))
2593
2594     def test_inst_from_file_3part_image_existing(self):
2595         """
2596         Creates a VM instance from a 3-part image that is existing
2597         :return: 
2598         """
2599         kernel_file = file_utils.download(
2600             openstack_tests.CIRROS_DEFAULT_KERNEL_IMAGE_URL, self.tmpDir)
2601         ramdisk_file = file_utils.download(
2602             openstack_tests.CIRROS_DEFAULT_RAMDISK_IMAGE_URL, self.tmpDir)
2603
2604         metadata = {'cirros': {'disk_file': self.image_file.name,
2605                                'kernel_file': kernel_file.name,
2606                                'ramdisk_file': ramdisk_file.name}}
2607
2608         os_image_settings = openstack_tests.cirros_image_settings(
2609             name=self.image_name, image_metadata=metadata)
2610         self.image_creator = OpenStackImage(self.os_creds, os_image_settings)
2611         self.image_creator.create()
2612
2613         image_settings = self.image_creator.image_settings
2614         test_image_creator = OpenStackImage(
2615             self.os_creds,
2616             ImageConfig(
2617                 name=image_settings.name, image_user=image_settings.image_user,
2618                 exists=True))
2619         test_image_creator.create()
2620         self.assertEqual(self.image_creator.get_image().id,
2621                          test_image_creator.get_image().id)
2622
2623         instance_settings = VmInstanceSettings(
2624             name=self.vm_inst_name,
2625             flavor=self.flavor_creator.flavor_settings.name,
2626             port_settings=[self.port_settings])
2627         self.inst_creator = OpenStackVmInstance(
2628             self.os_creds, instance_settings,
2629             test_image_creator.image_settings)
2630         self.inst_creator.create()
2631
2632         self.assertTrue(self.inst_creator.vm_active(block=True))
2633
2634
2635 class CreateInstanceTwoNetTests(OSIntegrationTestCase):
2636     """
2637     Tests the ability of two VMs to communicate when attached to separate
2638     private networks that are tied together with a router.
2639     """
2640
2641     def setUp(self):
2642         """
2643         Instantiates the CreateImage object that is responsible for downloading
2644         and creating an OS image file within OpenStack
2645         """
2646         super(self.__class__, self).__start__()
2647
2648         cidr1 = '10.200.201.0/24'
2649         cidr2 = '10.200.202.0/24'
2650         static_gateway_ip1 = '10.200.201.1'
2651         static_gateway_ip2 = '10.200.202.1'
2652         self.ip1 = '10.200.201.5'
2653         self.ip2 = '10.200.202.5'
2654
2655         self.nova = nova_utils.nova_client(self.os_creds)
2656
2657         # Initialize for tearDown()
2658         self.image_creator = None
2659         self.network_creators = list()
2660         self.router_creator = None
2661         self.flavor_creator = None
2662         self.sec_grp_creator = None
2663         self.inst_creators = list()
2664
2665         self.guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
2666         self.vm_inst1_name = self.guid + '-inst1'
2667         self.vm_inst2_name = self.guid + '-inst2'
2668         self.port_1_name = self.guid + '-vm1-port'
2669         self.port_2_name = self.guid + '-vm2-port'
2670         self.net_config_1 = NetworkSettings(
2671             name=self.guid + '-net1',
2672             subnet_settings=[
2673                 create_network.SubnetSettings(
2674                     cidr=cidr1, name=self.guid + '-subnet1',
2675                     gateway_ip=static_gateway_ip1)])
2676         self.net_config_2 = NetworkSettings(
2677             name=self.guid + '-net2',
2678             subnet_settings=[
2679                 create_network.SubnetSettings(
2680                     cidr=cidr2, name=self.guid + '-subnet2',
2681                     gateway_ip=static_gateway_ip2)])
2682
2683         image_name = self.__class__.__name__ + '-' + str(uuid.uuid4())
2684         os_image_settings = openstack_tests.cirros_image_settings(
2685             name=image_name, image_metadata=self.image_metadata)
2686
2687         try:
2688             # Create Image
2689             self.image_creator = OpenStackImage(self.os_creds,
2690                                                 os_image_settings)
2691             self.image_creator.create()
2692
2693             # First network is public
2694             self.network_creators.append(OpenStackNetwork(
2695                 self.os_creds, self.net_config_1))
2696             # Second network is private
2697             self.network_creators.append(OpenStackNetwork(
2698                 self.os_creds, self.net_config_2))
2699             for network_creator in self.network_creators:
2700                 network_creator.create()
2701
2702             port_settings = [
2703                 create_network.PortSettings(
2704                     name=self.guid + '-router-port1',
2705                     ip_addrs=[{
2706                         'subnet_name':
2707                             self.net_config_1.subnet_settings[0].name,
2708                         'ip': static_gateway_ip1
2709                     }],
2710                     network_name=self.net_config_1.name,
2711                     project_name=self.os_creds.project_name),
2712                 create_network.PortSettings(
2713                     name=self.guid + '-router-port2',
2714                     ip_addrs=[{
2715                         'subnet_name':
2716                             self.net_config_2.subnet_settings[0].name,
2717                         'ip': static_gateway_ip2
2718                     }],
2719                     network_name=self.net_config_2.name,
2720                     project_name=self.os_creds.project_name)]
2721
2722             router_settings = RouterSettings(name=self.guid + '-pub-router',
2723                                              port_settings=port_settings)
2724             self.router_creator = create_router.OpenStackRouter(
2725                 self.os_creds, router_settings)
2726             self.router_creator.create()
2727
2728             # Create Flavor
2729             self.flavor_creator = OpenStackFlavor(
2730                 self.admin_os_creds,
2731                 FlavorConfig(name=self.guid + '-flavor-name', ram=512,
2732                              disk=10, vcpus=2,
2733                              metadata=self.flavor_metadata))
2734             self.flavor_creator.create()
2735
2736             sec_grp_name = self.guid + '-sec-grp'
2737             rule1 = SecurityGroupRuleSettings(sec_grp_name=sec_grp_name,
2738                                               direction=Direction.ingress,
2739                                               protocol=Protocol.icmp)
2740             self.sec_grp_creator = OpenStackSecurityGroup(
2741                 self.os_creds,
2742                 SecurityGroupSettings(name=sec_grp_name,
2743                                       rule_settings=[rule1]))
2744             self.sec_grp_creator.create()
2745         except:
2746             self.tearDown()
2747             raise
2748
2749     def tearDown(self):
2750         """
2751         Cleans the created objects
2752         """
2753         for inst_creator in self.inst_creators:
2754             try:
2755                 inst_creator.clean()
2756             except Exception as e:
2757                 logger.error(
2758                     'Unexpected exception cleaning VM instance with message '
2759                     '- %s', e)
2760
2761         if self.flavor_creator:
2762             try:
2763                 self.flavor_creator.clean()
2764             except Exception as e:
2765                 logger.error(
2766                     'Unexpected exception cleaning flavor with message - %s',
2767                     e)
2768
2769         if self.router_creator:
2770             try:
2771                 self.router_creator.clean()
2772             except Exception as e:
2773                 logger.error(
2774                     'Unexpected exception cleaning router with message - %s',
2775                     e)
2776
2777         for network_creator in self.network_creators:
2778             try:
2779                 network_creator.clean()
2780             except Exception as e:
2781                 logger.error(
2782                     'Unexpected exception cleaning network with message - %s',
2783                     e)
2784
2785         if self.sec_grp_creator:
2786             try:
2787                 self.sec_grp_creator.clean()
2788             except Exception as e:
2789                 logger.error(
2790                     'Unexpected exception cleaning security group with message'
2791                     ' - %s', e)
2792
2793         if self.image_creator and not self.image_creator.image_settings.exists:
2794             try:
2795                 self.image_creator.clean()
2796             except Exception as e:
2797                 logger.error(
2798                     'Unexpected exception cleaning image with message - %s', e)
2799
2800         super(self.__class__, self).__clean__()
2801
2802     def test_ping_via_router(self):
2803         """
2804         Tests the creation of two OpenStack instances with one port on
2805         different private networks wit a router in between to ensure that they
2806         can ping
2807         through
2808         """
2809         # Create ports/NICs for instance
2810         ports_settings = []
2811         ctr = 1
2812         for network_creator in self.network_creators:
2813             ports_settings.append(PortSettings(
2814                 name=self.guid + '-port-' + str(ctr),
2815                 network_name=network_creator.network_settings.name))
2816             ctr += 1
2817
2818         # Configure instances
2819         instance1_settings = VmInstanceSettings(
2820             name=self.vm_inst1_name,
2821             flavor=self.flavor_creator.flavor_settings.name,
2822             userdata=_get_ping_userdata(self.ip2),
2823             port_settings=[PortSettings(
2824                 name=self.port_1_name,
2825                 ip_addrs=[{
2826                     'subnet_name':
2827                         self.net_config_1.subnet_settings[0].name,
2828                     'ip': self.ip1
2829                 }],
2830                 network_name=self.network_creators[0].network_settings.name)])
2831         instance2_settings = VmInstanceSettings(
2832             name=self.vm_inst2_name,
2833             flavor=self.flavor_creator.flavor_settings.name,
2834             userdata=_get_ping_userdata(self.ip1),
2835             port_settings=[PortSettings(
2836                 name=self.port_2_name,
2837                 ip_addrs=[{
2838                     'subnet_name':
2839                         self.net_config_2.subnet_settings[0].name,
2840                     'ip': self.ip2
2841                 }],
2842                 network_name=self.network_creators[1].network_settings.name)])
2843
2844         # Create instances
2845         self.inst_creators.append(OpenStackVmInstance(
2846             self.os_creds, instance1_settings,
2847             self.image_creator.image_settings))
2848         self.inst_creators.append(OpenStackVmInstance(
2849             self.os_creds, instance2_settings,
2850             self.image_creator.image_settings))
2851
2852         for inst_creator in self.inst_creators:
2853             inst_creator.create(block=True)
2854
2855         # Check for DHCP lease
2856         self.assertTrue(check_dhcp_lease(self.inst_creators[0], self.ip1))
2857         self.assertTrue(check_dhcp_lease(self.inst_creators[1], self.ip2))
2858
2859         # Effectively blocks until VM has been properly activated
2860         self.assertTrue(check_ping(self.inst_creators[0]))
2861         self.assertTrue(check_ping(self.inst_creators[1]))
2862
2863
2864 class CreateInstanceVolumeTests(OSIntegrationTestCase):
2865     """
2866     Simple instance creation with an attached volume
2867     """
2868
2869     def setUp(self):
2870         """
2871         Instantiates the CreateImage object that is responsible for downloading
2872         and creating an OS image file
2873         within OpenStack
2874         """
2875         super(self.__class__, self).__start__()
2876
2877         guid = self.__class__.__name__ + '-' + str(uuid.uuid4())
2878         self.vm_inst_name = guid + '-inst'
2879         self.nova = nova_utils.nova_client(self.os_creds)
2880         os_image_settings = openstack_tests.cirros_image_settings(
2881             name=guid + '-image', image_metadata=self.image_metadata)
2882
2883         net_config = openstack_tests.get_priv_net_config(
2884             net_name=guid + '-pub-net', subnet_name=guid + '-pub-subnet',
2885             router_name=guid + '-pub-router', external_net=self.ext_net_name)
2886
2887         self.volume_settings1 = VolumeSettings(
2888             name=self.__class__.__name__ + '-' + str(guid) + '-1')
2889         self.volume_settings2 = VolumeSettings(
2890             name=self.__class__.__name__ + '-' + str(guid) + '-2')
2891
2892         # Initialize for tearDown()
2893         self.image_creator = None
2894         self.flavor_creator = None
2895
2896         self.network_creator = None
2897         self.inst_creator = None
2898         self.volume_creator1 = None
2899         self.volume_creator2 = None
2900
2901         try:
2902             # Create Image
2903             self.image_creator = OpenStackImage(self.os_creds,
2904                                                 os_image_settings)
2905             self.image_creator.create()
2906
2907             # Create Flavor
2908             self.flavor_creator = OpenStackFlavor(
2909                 self.admin_os_creds,
2910                 FlavorConfig(name=guid + '-flavor-name', ram=256, disk=1,
2911                              vcpus=2, metadata=self.flavor_metadata))
2912             self.flavor_creator.create()
2913
2914             # Create Network
2915             self.network_creator = OpenStackNetwork(
2916                 self.os_creds, net_config.network_settings)
2917             self.network_creator.create()
2918
2919             self.port_settings = PortSettings(
2920                 name=guid + '-port',
2921                 network_name=net_config.network_settings.name)
2922
2923             self.volume_creator1 = OpenStackVolume(
2924                 self.os_creds, self.volume_settings1)
2925             self.volume_creator1.create(block=True)
2926
2927             self.volume_creator2 = OpenStackVolume(
2928                 self.os_creds, self.volume_settings2)
2929             self.volume_creator2.create(block=True)
2930
2931         except Exception as e:
2932             self.tearDown()
2933             raise e
2934
2935     def tearDown(self):
2936         """
2937         Cleans the created object
2938         """
2939         if self.inst_creator:
2940             try:
2941                 self.inst_creator.clean()
2942             except Exception as e:
2943                 logger.error(
2944                     'Unexpected exception cleaning VM instance with message '
2945                     '- %s', e)
2946
2947         if self.flavor_creator:
2948             try:
2949                 self.flavor_creator.clean()
2950             except Exception as e:
2951                 logger.error(
2952                     'Unexpected exception cleaning flavor with message - %s',
2953                     e)
2954
2955         if self.network_creator:
2956             try:
2957                 self.network_creator.clean()
2958             except Exception as e:
2959                 logger.error(
2960                     'Unexpected exception cleaning network with message - %s',
2961                     e)
2962
2963         if self.volume_creator2:
2964             try:
2965                 self.volume_creator2.clean()
2966             except Exception as e:
2967                 logger.error(
2968                     'Unexpected exception cleaning volume with message - %s',
2969                     e)
2970
2971         if self.volume_creator1:
2972             try:
2973                 self.volume_creator1.clean()
2974             except Exception as e:
2975                 logger.error(
2976                     'Unexpected exception cleaning volume with message - %s',
2977                     e)
2978
2979         if self.image_creator and not self.image_creator.image_settings.exists:
2980             try:
2981                 self.image_creator.clean()
2982             except Exception as e:
2983                 logger.error(
2984                     'Unexpected exception cleaning image with message - %s', e)
2985
2986         super(self.__class__, self).__clean__()
2987
2988     def test_create_instance_with_one_volume(self):
2989         """
2990         Tests the creation of an OpenStack instance with a single volume.
2991         """
2992         instance_settings = VmInstanceSettings(
2993             name=self.vm_inst_name,
2994             flavor=self.flavor_creator.flavor_settings.name,
2995             port_settings=[self.port_settings],
2996             volume_names=[self.volume_settings1.name])
2997
2998         self.inst_creator = OpenStackVmInstance(
2999             self.os_creds, instance_settings,
3000             self.image_creator.image_settings)
3001
3002         vm_inst = self.inst_creator.create(block=True)
3003         self.assertIsNotNone(nova_utils.get_server(
3004             self.nova, vm_inst_settings=instance_settings))
3005
3006         self.assertIsNotNone(vm_inst)
3007         self.assertEqual(1, len(vm_inst.volume_ids))
3008         self.assertEqual(self.volume_creator1.get_volume().id,
3009                          vm_inst.volume_ids[0]['id'])
3010
3011     def test_create_instance_with_two_volumes(self):
3012         """
3013         Tests the creation of an OpenStack instance with a single volume.
3014         """
3015         instance_settings = VmInstanceSettings(
3016             name=self.vm_inst_name,
3017             flavor=self.flavor_creator.flavor_settings.name,
3018             port_settings=[self.port_settings],
3019             volume_names=[self.volume_settings1.name,
3020                           self.volume_settings2.name])
3021
3022         self.inst_creator = OpenStackVmInstance(
3023             self.os_creds, instance_settings,
3024             self.image_creator.image_settings)
3025
3026         vm_inst = self.inst_creator.create(block=True)
3027         self.assertIsNotNone(nova_utils.get_server(
3028             self.nova, vm_inst_settings=instance_settings))
3029
3030         self.assertIsNotNone(vm_inst)
3031         self.assertEqual(2, len(vm_inst.volume_ids))
3032         self.assertEqual(self.volume_creator1.get_volume().id,
3033                          vm_inst.volume_ids[0]['id'])
3034         self.assertEqual(self.volume_creator2.get_volume().id,
3035                          vm_inst.volume_ids[1]['id'])
3036
3037
3038 def check_dhcp_lease(inst_creator, ip, timeout=160):
3039     """
3040     Returns true if the expected DHCP lease has been acquired
3041     :param inst_creator: the SNAPS OpenStackVmInstance object
3042     :param ip: the IP address to look for
3043     :param timeout: how long to query for IP address
3044     :return:
3045     """
3046     found = False
3047     start_time = time.time()
3048
3049     logger.info("Looking for IP %s in the console log" % ip)
3050     full_log = ''
3051     while timeout > time.time() - start_time:
3052         output = inst_creator.get_console_output()
3053         full_log = full_log + output
3054         if re.search(ip, output):
3055             logger.info('DHCP lease obtained logged in console')
3056             found = True
3057             break
3058
3059     if not found:
3060         logger.error('Full console output -\n' + full_log)
3061     else:
3062         logger.debug('Full console output -\n' + full_log)
3063
3064     return found
3065
3066
3067 def _get_ping_userdata(test_ip):
3068     """
3069     Returns the post VM creation script to be added into the VM's userdata
3070     :param test_ip: the IP value to substitute into the script
3071     :return: the bash script contents
3072     """
3073     if test_ip:
3074         return ("#!/bin/sh\n\n"
3075                 "while true; do\n"
3076                 " ping -c 1 %s 2>&1 >/dev/null\n"
3077                 " RES=$?\n"
3078                 " if [ \"Z$RES\" = \"Z0\" ] ; then\n"
3079                 "  echo 'vPing OK'\n"
3080                 "  break\n"
3081                 " else\n"
3082                 "  echo 'vPing KO'\n"
3083                 " fi\n"
3084                 " sleep 1\n"
3085                 "done\n" % test_ip)
3086     return None
3087
3088
3089 def check_ping(vm_creator, timeout=160):
3090     """
3091     Check for VM for ping result
3092     """
3093     tries = 0
3094
3095     while tries < timeout:
3096         time.sleep(1)
3097         p_console = vm_creator.get_console_output()
3098         if "vPing OK" in p_console:
3099             return True
3100         elif "failed to read iid from metadata" in p_console or tries > 5:
3101             return False
3102         tries += 1
3103
3104     return False