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