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