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