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