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