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