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