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