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