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