Merge "task: use CONF_FILE from constants"
[yardstick.git] / yardstick / network_services / vnf_generic / vnf / tg_ping.py
1 # Copyright (c) 2016-2017 Intel Corporation
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """ PING acts as traffic generation and vnf definitions based on IETS Spec """
15
16 from __future__ import absolute_import
17 from __future__ import print_function
18 import logging
19 import re
20
21 from multiprocessing import Queue
22 from ipaddress import IPv4Interface
23
24 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
25 from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
26 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
27
28 LOG = logging.getLogger(__name__)
29
30
31 class PingParser(object):
32     """ Class providing file-like API for talking with SSH connection """
33
34     def __init__(self, q_out):
35         self.queue = q_out
36         self.closed = False
37
38     def write(self, chunk):
39         """ 64 bytes from 10.102.22.93: icmp_seq=1 ttl=64 time=0.296 ms """
40         match = re.search(r"icmp_seq=(\d+).*time=([0-9.]+)", chunk)
41         LOG.debug("Parser called on %s", chunk)
42         if match:
43             # IMPORTANT: in order for the data to be properly taken
44             # in by InfluxDB, it needs to be converted to numeric types
45             self.queue.put({
46                 "packets_received": float(match.group(1)),
47                 "rtt": float(match.group(2)),
48             })
49
50     def close(self):
51         """ close the ssh connection """
52         self.closed = True
53
54     def clear(self):
55         """ clear queue till Empty """
56         while self.queue.qsize() > 0:
57             self.queue.get()
58
59
60 class PingSetupEnvHelper(DpdkVnfSetupEnvHelper):
61
62     def setup_vnf_environment(self):
63         for intf in self.vnfd_helper.interfaces:
64             vi = intf['virtual-interface']
65             vi['local_iface_name'] = self.get_local_iface_name_by_vpci(vi['vpci'])
66
67
68 class PingResourceHelper(ClientResourceHelper):
69
70     def __init__(self, setup_helper):
71         super(PingResourceHelper, self).__init__(setup_helper)
72         self._queue = Queue()
73         self._parser = PingParser(self._queue)
74
75     def run_traffic(self, traffic_profile):
76         # drop the connection in order to force a new one
77         self.ssh_helper.drop_connection()
78
79         self.client_started.value = 1
80         cmd_list = [
81             "sudo ip addr flush {local_if_name}",
82             "sudo ip addr add {local_ip}/24 dev {local_if_name}",
83             "sudo ip link set {local_if_name} up",
84         ]
85
86         self.cmd_kwargs['packet_size'] = traffic_profile.params['traffic_profile']['frame_size']
87
88         for cmd in cmd_list:
89             self.ssh_helper.execute(cmd.format(**self.cmd_kwargs))
90
91         ping_cmd = "nohup ping -s {packet_size} {target_ip}&"
92         self.ssh_helper.run(ping_cmd.format(**self.cmd_kwargs),
93                             stdout=self._parser,
94                             keep_stdin_open=True, pty=True)
95
96
97 class PingTrafficGen(SampleVNFTrafficGen):
98     """
99     This traffic generator can ping a single IP with pingsize
100     and target given in traffic profile
101     """
102
103     TG_NAME = 'Ping'
104     APP_NAME = 'Ping'
105     RUN_WAIT = 4
106
107     def __init__(self, name, vnfd, setup_env_helper_type=None, resource_helper_type=None):
108         if setup_env_helper_type is None:
109             setup_env_helper_type = PingSetupEnvHelper
110         if resource_helper_type is None:
111             resource_helper_type = PingResourceHelper
112
113         super(PingTrafficGen, self).__init__(name, vnfd, setup_env_helper_type,
114                                              resource_helper_type)
115         self._result = {}
116
117     def scale(self, flavor=""):
118         """ scale vnf-based on flavor input """
119         pass
120
121     def _check_status(self):
122         return self._tg_process.is_alive()
123
124     def instantiate(self, scenario_cfg, context_cfg):
125         self._start_server()
126         self._result = {
127             "packets_received": 0,
128             "rtt": 0,
129         }
130         intf = self.vnfd_helper.interfaces[0]["virtual-interface"]
131         self.resource_helper.cmd_kwargs = {
132             'target_ip': IPv4Interface(intf["dst_ip"]).ip.exploded,
133             'local_ip': IPv4Interface(intf["local_ip"]).ip.exploded,
134             'local_if_name': intf["local_iface_name"].split('/')[0],
135         }
136
137         self.setup_helper.setup_vnf_environment()
138
139     def wait_for_instantiate(self):
140         pass
141
142     def listen_traffic(self, traffic_profile):
143         """ Not needed for ping
144
145         :param traffic_profile:
146         :return:
147         """
148         pass