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