Merge "Added NSB descriptors for vCMTS testcase"
[yardstick.git] / yardstick / network_services / vnf_generic / vnf / tg_ixload.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
15 import collections
16 import csv
17 import glob
18 import logging
19 import os
20 import shutil
21 import subprocess
22
23 from oslo_serialization import jsonutils
24
25 from yardstick.common import utils
26 from yardstick.network_services.vnf_generic.vnf import sample_vnf
27
28
29
30 LOG = logging.getLogger(__name__)
31
32 VNF_PATH = os.path.dirname(os.path.realpath(__file__))
33
34 MOUNT_CMD = """\
35 mount.cifs //{0[ip]}/Results {1.RESULTS_MOUNT} \
36 -o username={0[user]},password={0[password]}\
37 """
38
39 IXLOAD_CONFIG_TEMPLATE = '''\
40 {
41     "ixia_chassis": "%s",
42     "IXIA": {
43         "ports": %s,
44         "card": %s
45     },
46     "remote_server": "%s",
47     "result_dir": "%s",
48     "ixload_cfg": "C:/Results/%s",
49     "links_param": %s
50 }'''
51
52 IXLOAD_CMD = "{ixloadpy} {http_ixload} {args}"
53
54
55 class ResourceDataHelper(list):
56
57     def get_aggregates(self):
58         return {
59             "min": min(self),
60             "max": max(self),
61             "avg": sum(self) / len(self),
62         }
63
64
65 class IxLoadResourceHelper(sample_vnf.ClientResourceHelper):
66
67     RESULTS_MOUNT = "/mnt/Results"
68
69     KPI_LIST = collections.OrderedDict((
70         ('http_throughput', 'HTTP Total Throughput (Kbps)'),
71         ('simulated_users', 'HTTP Simulated Users'),
72         ('concurrent_connections', 'HTTP Concurrent Connections'),
73         ('connection_rate', 'HTTP Connection Rate'),
74         ('transaction_rate', 'HTTP Transaction Rate'),
75     ))
76
77     def __init__(self, setup_helper):
78         super(IxLoadResourceHelper, self).__init__(setup_helper)
79         self.result = collections.OrderedDict((key, ResourceDataHelper())
80                                               for key in self.KPI_LIST)
81         self.resource_file_name = ''
82         self.data = None
83
84     def parse_csv_read(self, reader):
85         for row in reader:
86             try:
87                 new_data = {key_left: int(row[key_right])
88                             for key_left, key_right in self.KPI_LIST.items()}
89             except (TypeError, ValueError):
90                 continue
91             else:
92                 for key, value in new_data.items():
93                     self.result[key].append(value)
94
95     def setup(self):
96         # NOTE: fixup scenario_helper to hanlde ixia
97         self.resource_file_name = \
98             utils.find_relative_file(
99                 self.scenario_helper.scenario_cfg['ixia_profile'],
100                 self.scenario_helper.scenario_cfg["task_path"])
101         utils.makedirs(self.RESULTS_MOUNT)
102         cmd = MOUNT_CMD.format(self.vnfd_helper.mgmt_interface, self)
103         LOG.debug(cmd)
104
105         if not os.path.ismount(self.RESULTS_MOUNT):
106             subprocess.call(cmd, shell=True)
107
108         shutil.rmtree(self.RESULTS_MOUNT, ignore_errors=True)
109         utils.makedirs(self.RESULTS_MOUNT)
110         shutil.copy(self.resource_file_name, self.RESULTS_MOUNT)
111
112     def make_aggregates(self):
113         return {key_right: self.result[key_left].get_aggregates()
114                 for key_left, key_right in self.KPI_LIST.items()}
115
116     def collect_kpi(self):
117         if self.data:
118             self._result.update(self.data)
119         LOG.info("Collect %s KPIs %s", self.RESOURCE_WORD, self._result)
120         return self._result
121
122     def log(self):
123         for key in self.KPI_LIST:
124             LOG.debug(self.result[key])
125
126
127 class IxLoadTrafficGen(sample_vnf.SampleVNFTrafficGen):
128
129     def __init__(self, name, vnfd, setup_env_helper_type=None, resource_helper_type=None):
130         if resource_helper_type is None:
131             resource_helper_type = IxLoadResourceHelper
132
133         super(IxLoadTrafficGen, self).__init__(name, vnfd, setup_env_helper_type,
134                                                resource_helper_type)
135         self._result = {}
136
137     def update_gateways(self, links):
138         for name in links:
139             try:
140                 gateway = next(intf["virtual-interface"]["dst_ip"] for intf in
141                                self.setup_helper.vnfd_helper["vdu"][0][
142                                    "external-interface"] if
143                                intf["virtual-interface"]["vld_id"] == name)
144
145                 try:
146                     links[name]["ip"]["gateway"] = gateway
147                 except KeyError:
148                     LOG.error("Invalid traffic profile: No IP section defined for %s", name)
149                     raise
150
151             except StopIteration:
152                 LOG.debug("Cant find gateway for link %s", name)
153                 links[name]["ip"]["gateway"] = "0.0.0.0"
154
155         return links
156
157     def run_traffic(self, traffic_profile):
158         ports = []
159         card = None
160         for interface in self.vnfd_helper.interfaces:
161             vpci_list = interface['virtual-interface']["vpci"].split(":")
162             card = vpci_list[0]
163             ports.append(str(vpci_list[1]))
164
165         for csv_file in glob.iglob(self.ssh_helper.join_bin_path('*.csv')):
166             os.unlink(csv_file)
167
168         links_param = self.update_gateways(
169             traffic_profile.get_links_param())
170
171         ixia_config = self.vnfd_helper.mgmt_interface["tg-config"]
172         ixload_config = IXLOAD_CONFIG_TEMPLATE % (
173             ixia_config["ixchassis"], ports, card,
174             self.vnfd_helper.mgmt_interface["ip"], self.ssh_helper.bin_path,
175             os.path.basename(self.resource_helper.resource_file_name),
176             jsonutils.dumps(links_param)
177         )
178
179         http_ixload_path = os.path.join(VNF_PATH, "../../traffic_profile")
180
181         cmd = IXLOAD_CMD.format(
182             ixloadpy=os.path.join(ixia_config["py_bin_path"], "ixloadpython"),
183             http_ixload=os.path.join(http_ixload_path, "http_ixload.py"),
184             args="'%s'" % ixload_config)
185
186         LOG.debug(cmd)
187         subprocess.call(cmd, shell=True)
188
189         with open(self.ssh_helper.join_bin_path("ixLoad_HTTP_Client.csv")) as csv_file:
190             lines = csv_file.readlines()[10:]
191         with open(self.ssh_helper.join_bin_path("http_result.csv"), 'wb+') as result_file:
192             result_file.writelines(lines[:-1])
193             result_file.flush()
194             result_file.seek(0)
195             reader = csv.DictReader(result_file)
196             self.resource_helper.parse_csv_read(reader)
197
198         self.resource_helper.log()
199         self.resource_helper.data = self.resource_helper.make_aggregates()
200
201     def terminate(self):
202         subprocess.call(["pkill", "-9", "http_ixload.py"])
203         super(IxLoadTrafficGen, self).terminate()