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