From 8ee9c90c59de395991e6159fb75b5e114225f6e8 Mon Sep 17 00:00:00 2001 From: Yulong Pei Date: Thu, 11 May 2017 11:13:57 +0800 Subject: nics: support html report for performance result Support html format report for NIC performance and support to send it out by email. Signed-off-by: Yulong Pei --- nics/perf_report.jinja | 82 ++++++++++++++++++++++++++++++ nics/perf_report.py | 111 +++++++++++++++++++++++++++++++++++++++++ nics/system_info.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100644 nics/perf_report.jinja create mode 100644 nics/perf_report.py create mode 100644 nics/system_info.py diff --git a/nics/perf_report.jinja b/nics/perf_report.jinja new file mode 100644 index 0000000..1a3f903 --- /dev/null +++ b/nics/perf_report.jinja @@ -0,0 +1,82 @@ + + + + +{{ title }} + + + + + +
+

DPDK Git Information

+

Branch: {{ git_info['branch'] }}

+

commit: {{ git_info['commit'] }}

+

Author: {{ git_info['author'] }}

+

Date: {{ git_info['date'] }}

+

Summary: {{ git_info['summary'] }}

+
+ +
+

NIC Detail Information

+ + + + + + {% for key in nic_infos %} + + + + + {% endfor %} +
ItemDescription
{{ key }}{{ nic_infos[key] }}
+
+ +
+

Test Result:

+ + + + + + + {% for result in test_results %} + + + + + + {% endfor %} +
Frame_size(bytes)Throughput(Mpps)Line rate%
{{ result[0] }}{{ result[1] }}{{ result[2] }}
+
+ +
+

Hardware and Software Ingredients

+ + + + + + {% for key in system_infos %} + + + + + {% endfor %} +
ItemDescription
{{ key }}{{ system_infos[key] }}
+
+ + + + diff --git a/nics/perf_report.py b/nics/perf_report.py new file mode 100644 index 0000000..e833d6c --- /dev/null +++ b/nics/perf_report.py @@ -0,0 +1,111 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2017 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import time +import re + +import jinja2 +import smtplib + +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from collections import OrderedDict +#install GitPython +from git import Repo +from system_info import SystemInfo +import utils + +def get_dpdk_git_info(repo_dir="/root/dpdk"): + + if not os.path.exists(repo_dir): + return None + + commit = OrderedDict() + + git_repo = Repo(repo_dir) + assert not git_repo.bare + + latest_commit = git_repo.active_branch.commit + commit['branch'] = str(git_repo.active_branch) + commit['commit'] = str(latest_commit) + commit['author'] = latest_commit.author + commit['date'] = time.ctime(latest_commit.authored_date) + commit['summary'] = latest_commit.summary + return commit + +def generate_html_report(file_tpl, perf_data, git_info, nic_info, system_info): + + if not os.path.exists(file_tpl): + return None + + templateLoader = jinja2.FileSystemLoader(searchpath = "/") + templateEnv = jinja2.Environment(loader=templateLoader) + template = templateEnv.get_template(file_tpl) + + templateVars = { "title" : "Daily Performance Test Report", \ + "test_results" : perf_data, \ + "system_infos" : system_info, \ + "nic_infos" : nic_info, \ + "git_info" : git_info \ + } + + output = template.render(templateVars) + return output + +#sender = 'zzz@intel.com' +#mailto = ['xxx@intel.com', 'yyy@intel.com'] +def html_message(sender, mailto, subject, html_msg): + + msg = MIMEMultipart('alternative') + msg['From'] = sender + msg['to'] = ";".join(mailto) + msg['Subject'] = subject + + msg.attach(MIMEText(html_msg, 'html')) + + return msg + +#smtp = smtplib.SMTP('smtp.intel.com') +def send_email(sender, mailto, message, smtp_server): + + try: + smtp = smtplib.SMTP(smtp_server) + smtp.sendmail(sender, mailto, message.as_string()) + smtp.quit() + print utils.GREEN("Email sent successfully.") + except Exception, e: + print utils.RED("Failed to send email " + str(e)) + +def send_html_report(sender, mailto, subject, html_msg, smtp_server): + + message = html_message(sender, mailto, subject, html_msg) + send_email(sender, mailto, message, smtp_server) diff --git a/nics/system_info.py b/nics/system_info.py new file mode 100644 index 0000000..1f473d8 --- /dev/null +++ b/nics/system_info.py @@ -0,0 +1,133 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2017 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +import time +import re + +from collections import OrderedDict +#install GitPython +from git import Repo + +class SystemInfo(object): + + def __init__(self, dut, pci_device_id): + self.dut = dut + self.pci_device_id = pci_device_id + self.session = self.dut.session + self.system_info = OrderedDict() + self.nic_info = OrderedDict() + + def get_system_info(self): + + board = self.session.send_expect("dmidecode -s system-product-name", "# ") + self.system_info["Board"] = board + + processors = self.session.send_expect("dmidecode -s processor-version", "# ") + processor = processors.split('\r\n')[0] + self.system_info["CPU"] = processor + + memories = self.session.send_expect("dmidecode -t memory", "]# ") + channels, size, speed = self._strip_memory(memories) + memory_info = "Total %d MBs in %d channels @ %s" %(size, channels, speed) + self.system_info["Memory"] = memory_info + + release = self.session.send_expect("lsb_release -d |awk -F':' '{print $2}'", "# ") + self.system_info["Operating system"] = release + + kernel = self.session.send_expect("uname -r", "# ") + self.system_info["Linux kernel version"] = kernel + + gcc_info = self.session.send_expect("gcc --version", "# ") + gcc = gcc_info.split('\r\n')[0] + self.system_info["GCC version"] = gcc + + return self.system_info + + def _strip_memory(self, memories): + """ + Size: 8192 MB Locator: DIMM_A1 Speed: 2133 MHz + """ + s_regex = r"(\s+)Size: (\d+) MB" + l_regex= r"(\s+)Locator: DIMM_(\w+)" + speed_regex = r"(\s+)Speed: (.*)" + size = "" + locate = "" + speed = "Unknown" + memory_infos = [] + memory_channel = set() + lines = memories.split('\r\n') + total_size = 0 + for line in lines: + m = re.match(s_regex, line) + if m: + size = m.group(2) + l_m = re.match(l_regex, line) + if l_m: + locate = l_m.group(2) + s_m = re.match(speed_regex, line) + if s_m: + speed = s_m.group(2) + if speed != "Unknown": + memory={"Size": size, "Locate": locate, "Speed": speed} + memory_infos.append(memory) + speed = "Unknown" + total_size += int(size) + memory_channel.add(locate[0]) + + return len(memory_channel), total_size, memory_infos[0]["Speed"] + + def get_nic_info(self): + + cmd = "cat /sys/bus/pci/devices/%s/vendor" % self.pci_device_id + vendor = self.session.send_expect(cmd, "# ") + if "No such" in vendor: + return None + + cmd = "cat /sys/bus/pci/devices/%s/device" % self.pci_device_id + device = self.session.send_expect(cmd, "# ") + if "No such" in device: + return None + + cmd = "ls --color=never /sys/bus/pci/devices/%s/net" % self.pci_device_id + interface = self.session.send_expect(cmd, "# ") + if "No such" in interface: + return None + cmd = "ethtool -i %s | grep --color=never firmware |awk -F':' '{print $2}'" % interface + firmware = self.session.send_expect(cmd, "# ") + if "No such" in firmware: + return None + cmd = "lspci -vmmks %s |grep -i ^device |awk -F':' '{print $2}'" % self.pci_device_id + self.nic_info['nic_name'] = self.session.send_expect(cmd, "# ") + self.nic_info['device_id'] = vendor[2:] + ':' + device[2:] + self.nic_info['firmware-version'] = firmware + return self.nic_info + -- cgit v1.2.3