Merge "Enable tempest offline by use_custom_images=True"
[functest.git] / functest / opnfv_tests / openstack / vping / vping_base.py
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2015 All rights reserved
4 # This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 from datetime import datetime
11 import logging
12 import os
13 import time
14 import uuid
15
16 from functest.core import testcase
17 from functest.utils import functest_utils
18 from functest.utils.constants import CONST
19
20 from snaps.openstack import create_flavor
21 from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor
22 from snaps.openstack.create_network import NetworkSettings, SubnetSettings
23 from snaps.openstack.tests import openstack_tests
24 from snaps.openstack.utils import deploy_utils, nova_utils
25
26
27 class VPingBase(testcase.OSGCTestCase):
28
29     """
30     Base class for vPing tests that check connectivity between two VMs shared
31     internal network.
32     This class is responsible for creating the image, internal network.
33     """
34
35     def __init__(self, **kwargs):
36         super(VPingBase, self).__init__(**kwargs)
37
38         self.logger = logging.getLogger(self.__class__.__name__)
39
40         self.functest_repo = CONST.__getattribute__('dir_repo_functest')
41         self.guid = ''
42         if CONST.__getattribute__('vping_unique_names'):
43             self.guid = '-' + str(uuid.uuid4())
44
45         self.os_creds = openstack_tests.get_credentials(
46             os_env_file=CONST.__getattribute__('openstack_creds'))
47
48         self.repo = CONST.__getattribute__('dir_vping')
49
50         self.creators = list()
51         self.image_creator = None
52         self.network_creator = None
53         self.vm1_creator = None
54         self.vm2_creator = None
55
56         self.self_cleanup = CONST.__getattribute__('vping_cleanup_objects')
57
58         # Image constants
59         self.image_name =\
60             CONST.__getattribute__('vping_image_name') + self.guid
61
62         # VM constants
63         self.vm1_name = CONST.__getattribute__('vping_vm_name_1') + self.guid
64         self.vm2_name = CONST.__getattribute__('vping_vm_name_2') + self.guid
65         self.vm_boot_timeout = CONST.__getattribute__('vping_vm_boot_timeout')
66         self.vm_delete_timeout =\
67             CONST.__getattribute__('vping_vm_delete_timeout')
68         self.vm_ssh_connect_timeout = CONST.vping_vm_ssh_connect_timeout
69         self.ping_timeout = CONST.__getattribute__('vping_ping_timeout')
70         self.flavor_name = 'vping-flavor' + self.guid
71
72         # NEUTRON Private Network parameters
73         self.private_net_name =\
74             CONST.__getattribute__('vping_private_net_name') + self.guid
75         self.private_subnet_name =\
76             CONST.__getattribute__('vping_private_subnet_name') + self.guid
77         self.private_subnet_cidr =\
78             CONST.__getattribute__('vping_private_subnet_cidr')
79
80         scenario = functest_utils.get_scenario()
81
82         self.flavor_metadata = None
83         if 'ovs' in scenario or 'fdio' in scenario:
84             self.flavor_metadata = create_flavor.MEM_PAGE_SIZE_LARGE
85
86         self.cirros_image_config = None
87
88         # Move this configuration option up for all tests to leverage
89         if hasattr(CONST, 'snaps_images_cirros'):
90             self.cirros_image_config = CONST.__getattribute__(
91                 'snaps_images_cirros')
92
93     def run(self):
94         """
95         Begins the test execution which should originate from the subclass
96         """
97
98         if not os.path.exists(self.functest_repo):
99             raise Exception(
100                 "Functest repository not found '%s'" % self.functest_repo)
101
102         self.logger.info('Begin virtual environment setup')
103
104         self.start_time = time.time()
105         self.logger.info("vPing Start Time:'%s'" % (
106             datetime.fromtimestamp(self.start_time).strftime(
107                 '%Y-%m-%d %H:%M:%S')))
108
109         self.__delete_exist_vms()
110
111         image_base_name = self.image_name + '-' + str(self.guid)
112         os_image_settings = openstack_tests.cirros_image_settings(
113             image_base_name, image_metadata=self.cirros_image_config)
114         self.logger.info("Creating image with name: '%s'" % self.image_name)
115
116         self.image_creator = deploy_utils.create_image(
117             self.os_creds, os_image_settings)
118         self.creators.append(self.image_creator)
119
120         self.logger.info(
121             "Creating network with name: '%s'" % self.private_net_name)
122         self.network_creator = deploy_utils.create_network(
123             self.os_creds,
124             NetworkSettings(name=self.private_net_name,
125                             subnet_settings=[SubnetSettings(
126                                 name=self.private_subnet_name,
127                                 cidr=self.private_subnet_cidr)]))
128         self.creators.append(self.network_creator)
129
130         self.logger.info(
131             "Creating flavor with name: '%s'" % self.flavor_name)
132         flavor_creator = OpenStackFlavor(
133             self.os_creds,
134             FlavorSettings(name=self.flavor_name, ram=512, disk=1, vcpus=1,
135                            metadata=self.flavor_metadata))
136         flavor_creator.create()
137         self.creators.append(flavor_creator)
138
139     def _execute(self):
140         """
141         Method called by subclasses after environment has been setup
142         :return: the exit code
143         """
144         self.logger.info('Begin test execution')
145
146         test_ip = self.vm1_creator.get_port_ip(
147             self.vm1_creator.instance_settings.port_settings[0].name)
148
149         if self.vm1_creator.vm_active(
150                 block=True) and self.vm2_creator.vm_active(block=True):
151             result = self._do_vping(self.vm2_creator, test_ip)
152         else:
153             raise Exception('VMs never became active')
154
155         if result == testcase.TestCase.EX_RUN_ERROR:
156             return testcase.TestCase.EX_RUN_ERROR
157
158         self.stop_time = time.time()
159         self.result = 100
160         return testcase.TestCase.EX_OK
161
162     def _cleanup(self):
163         """
164         Cleanup all OpenStack objects. Should be called on completion
165         :return:
166         """
167         if self.self_cleanup:
168             for creator in reversed(self.creators):
169                 try:
170                     creator.clean()
171                 except Exception as e:
172                     self.logger.error('Unexpected error cleaning - %s', e)
173
174     def _do_vping(self, vm_creator, test_ip):
175         """
176         Method to be implemented by subclasses
177         Begins the real test after the OpenStack environment has been setup
178         :param vm_creator: the SNAPS VM instance creator object
179         :param test_ip: the IP to which the VM needs to issue the ping
180         :return: T/F
181         """
182         raise NotImplementedError('vping execution is not implemented')
183
184     def __delete_exist_vms(self):
185         """
186         Cleans any existing VMs using the same name.
187         """
188         nova_client = nova_utils.nova_client(self.os_creds)
189         servers = nova_client.servers.list()
190         for server in servers:
191             if server.name == self.vm1_name or server.name == self.vm2_name:
192                 self.logger.info("Deleting instance %s..." % server.name)
193                 server.delete()
194
195
196 class VPingMain(object):
197
198     def __init__(self, vping_cls):
199         self.vping = vping_cls()
200
201     def main(self, **kwargs):
202         try:
203             result = self.vping.run(**kwargs)
204             if result != VPingBase.EX_OK:
205                 return result
206             if kwargs['report']:
207                 return self.vping.publish_report()
208         except:
209             return VPingBase.EX_RUN_ERROR