Add decorators in testcases for energy recording.
[functest.git] / functest / opnfv_tests / openstack / vping / vping_ssh.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
11 """vPingSSH testcase."""
12
13 # This 1st import is here simply for pep8 as the 'os' package import appears
14 # to be required for mock and the unit tests will fail without it
15 import os  # noqa # pylint: disable=unused-import
16 import time
17
18 from scp import SCPClient
19 import pkg_resources
20
21 from functest.core.testcase import TestCase
22 from functest.energy import energy
23 from functest.opnfv_tests.openstack.snaps import snaps_utils
24 from functest.opnfv_tests.openstack.vping import vping_base
25 from functest.utils.constants import CONST
26 from snaps.openstack.create_instance import FloatingIpSettings, \
27     VmInstanceSettings
28
29 from snaps.openstack.create_keypairs import KeypairSettings
30 from snaps.openstack.create_network import PortSettings
31 from snaps.openstack.create_router import RouterSettings
32 from snaps.openstack.create_security_group import Direction, Protocol, \
33     SecurityGroupSettings, SecurityGroupRuleSettings
34 from snaps.openstack.utils import deploy_utils
35
36
37 class VPingSSH(vping_base.VPingBase):
38     """
39     VPingSSH testcase implementation.
40
41     Class to execute the vPing test using a Floating IP to connect to one VM
42     to issue the ping command to the second
43     """
44
45     def __init__(self, **kwargs):
46         """Initialize testcase."""
47         if "case_name" not in kwargs:
48             kwargs["case_name"] = "vping_ssh"
49         super(VPingSSH, self).__init__(**kwargs)
50
51         self.kp_name = CONST.__getattribute__('vping_keypair_name') + self.guid
52         self.kp_priv_file = CONST.__getattribute__('vping_keypair_priv_file')
53         self.kp_pub_file = CONST.__getattribute__('vping_keypair_pub_file')
54         self.router_name = CONST.__getattribute__(
55             'vping_router_name') + self.guid
56         self.sg_name = CONST.__getattribute__('vping_sg_name') + self.guid
57         self.sg_desc = CONST.__getattribute__('vping_sg_desc')
58
59     @energy.enable_recording
60     def run(self):
61         """
62         Excecute VPingSSH testcase.
63
64         Sets up the OpenStack keypair, router, security group, and VM instance
65         objects then validates the ping.
66         :return: the exit code from the super.execute() method
67         """
68         try:
69             super(VPingSSH, self).run()
70
71             log = "Creating keypair with name: '%s'" % self.kp_name
72             self.logger.info(log)
73             kp_creator = deploy_utils.create_keypair(
74                 self.os_creds,
75                 KeypairSettings(name=self.kp_name,
76                                 private_filepath=self.kp_priv_file,
77                                 public_filepath=self.kp_pub_file))
78             self.creators.append(kp_creator)
79
80             # Creating router to external network
81             log = "Creating router with name: '%s'" % self.router_name
82             self.logger.info(log)
83             net_set = self.network_creator.network_settings
84             sub_set = [net_set.subnet_settings[0].name]
85             ext_net_name = snaps_utils.get_ext_net_name(self.os_creds)
86             router_creator = deploy_utils.create_router(
87                 self.os_creds,
88                 RouterSettings(
89                     name=self.router_name,
90                     external_gateway=ext_net_name,
91                     internal_subnets=sub_set))
92             self.creators.append(router_creator)
93
94             # Creating Instance 1
95             port1_settings = PortSettings(
96                 name=self.vm1_name + '-vPingPort',
97                 network_name=self.network_creator.network_settings.name)
98             instance1_settings = VmInstanceSettings(
99                 name=self.vm1_name, flavor=self.flavor_name,
100                 vm_boot_timeout=self.vm_boot_timeout,
101                 vm_delete_timeout=self.vm_delete_timeout,
102                 ssh_connect_timeout=self.vm_ssh_connect_timeout,
103                 port_settings=[port1_settings])
104
105             log = ("Creating VM 1 instance with name: '%s'"
106                    % instance1_settings.name)
107             self.logger.info(log)
108             self.vm1_creator = deploy_utils.create_vm_instance(
109                 self.os_creds,
110                 instance1_settings,
111                 self.image_creator.image_settings,
112                 keypair_creator=kp_creator)
113             self.creators.append(self.vm1_creator)
114
115             # Creating Instance 2
116             sg_creator = self.__create_security_group()
117             self.creators.append(sg_creator)
118
119             port2_settings = PortSettings(
120                 name=self.vm2_name + '-vPingPort',
121                 network_name=self.network_creator.network_settings.name)
122             instance2_settings = VmInstanceSettings(
123                 name=self.vm2_name, flavor=self.flavor_name,
124                 vm_boot_timeout=self.vm_boot_timeout,
125                 vm_delete_timeout=self.vm_delete_timeout,
126                 ssh_connect_timeout=self.vm_ssh_connect_timeout,
127                 port_settings=[port2_settings],
128                 security_group_names=[sg_creator.sec_grp_settings.name],
129                 floating_ip_settings=[FloatingIpSettings(
130                     name=self.vm2_name + '-FIPName',
131                     port_name=port2_settings.name,
132                     router_name=router_creator.router_settings.name)])
133
134             log = ("Creating VM 2 instance with name: '%s'"
135                    % instance2_settings.name)
136             self.logger.info(log)
137             self.vm2_creator = deploy_utils.create_vm_instance(
138                 self.os_creds,
139                 instance2_settings,
140                 self.image_creator.image_settings,
141                 keypair_creator=kp_creator)
142             self.creators.append(self.vm2_creator)
143
144             return self._execute()
145         except Exception as exc:  # pylint: disable=broad-except
146             self.logger.error('Unexpected error running test - ' + exc.message)
147             return TestCase.EX_RUN_ERROR
148         finally:
149             self._cleanup()
150
151     def _do_vping(self, vm_creator, test_ip):
152         """
153         Execute ping command.
154
155         Override from super
156         """
157         if vm_creator.vm_ssh_active(block=True):
158             ssh = vm_creator.ssh_client()
159             if not self._transfer_ping_script(ssh):
160                 return TestCase.EX_RUN_ERROR
161             return self._do_vping_ssh(ssh, test_ip)
162         else:
163             return -1
164
165     def _transfer_ping_script(self, ssh):
166         """
167         Transfert vping script to VM.
168
169         Uses SCP to copy the ping script via the SSH client
170         :param ssh: the SSH client
171         :return:
172         """
173         self.logger.info("Trying to transfer ping.sh")
174         scp = SCPClient(ssh.get_transport())
175         ping_script = pkg_resources.resource_filename(
176             'functest.opnfv_tests.openstack.vping', 'ping.sh')
177         try:
178             scp.put(ping_script, "~/")
179         except Exception:
180             self.logger.error("Cannot SCP the file '%s'", ping_script)
181             return False
182
183         cmd = 'chmod 755 ~/ping.sh'
184         # pylint: disable=unused-variable
185         (stdin, stdout, stderr) = ssh.exec_command(cmd)
186         for line in stdout.readlines():
187             print line
188
189         return True
190
191     def _do_vping_ssh(self, ssh, test_ip):
192         """
193         Execute ping command via SSH.
194
195         Pings the test_ip via the SSH client
196         :param ssh: the SSH client used to issue the ping command
197         :param test_ip: the IP for the ping command to use
198         :return: exit_code (int)
199         """
200         exit_code = TestCase.EX_TESTCASE_FAILED
201         self.logger.info("Waiting for ping...")
202
203         sec = 0
204         cmd = '~/ping.sh ' + test_ip
205         flag = False
206
207         while True:
208             time.sleep(1)
209             (_, stdout, _) = ssh.exec_command(cmd)
210             output = stdout.readlines()
211
212             for line in output:
213                 if "vPing OK" in line:
214                     self.logger.info("vPing detected!")
215                     exit_code = TestCase.EX_OK
216                     flag = True
217                     break
218
219                 elif sec == self.ping_timeout:
220                     self.logger.info("Timeout reached.")
221                     flag = True
222                     break
223             if flag:
224                 break
225             log = "Pinging %s. Waiting for response..." % test_ip
226             self.logger.debug(log)
227             sec += 1
228         return exit_code
229
230     def __create_security_group(self):
231         """
232         Configure OpenStack security groups.
233
234         Configures and deploys an OpenStack security group object
235         :return: the creator object
236         """
237         sg_rules = list()
238         sg_rules.append(
239             SecurityGroupRuleSettings(sec_grp_name=self.sg_name,
240                                       direction=Direction.ingress,
241                                       protocol=Protocol.icmp))
242         sg_rules.append(
243             SecurityGroupRuleSettings(sec_grp_name=self.sg_name,
244                                       direction=Direction.ingress,
245                                       protocol=Protocol.tcp, port_range_min=22,
246                                       port_range_max=22))
247         sg_rules.append(
248             SecurityGroupRuleSettings(sec_grp_name=self.sg_name,
249                                       direction=Direction.egress,
250                                       protocol=Protocol.tcp, port_range_min=22,
251                                       port_range_max=22))
252
253         log = "Security group with name: '%s'" % self.sg_name
254         self.logger.info(log)
255         return deploy_utils.create_security_group(self.os_creds,
256                                                   SecurityGroupSettings(
257                                                       name=self.sg_name,
258                                                       description=self.sg_desc,
259                                                       rule_settings=sg_rules))