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