Merge "Change PTL informatin in INFO"
[bottlenecks.git] / testsuites / vstf / vstf_scripts / vstf / agent / env / basic / device_manager.py
1 ##############################################################################
2 # Copyright (c) 2015 Huawei Technologies Co.,Ltd and others.
3 #
4 # All rights reserved. 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 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 import re
11 import logging
12 from vstf.agent.perf import netns
13 from vstf.common.utils import check_output, get_device_name, my_sleep, check_call, call, IPCommandHelper
14
15 LOG = logging.getLogger(__name__)
16
17 default_drivers = {
18     '82599': 'ixgbe',
19     '82576': 'igb',
20 }
21
22
23 class LspciHelper(object):
24
25     def __init__(self):
26         self.bdf_desc_map = {}
27         self.bdf_device_map = {}
28         self.device_bdf_map = {}
29         self.bdf_ip_map = {}
30         self.bdf_driver_map = {}
31         self.mac_bdf_map = {}
32         self.bdf_mac_map = {}
33         self._get_bdfs()
34         self._get_devices()
35         self._get_drivers()
36         self._get_ip_macs()
37
38     def _get_bdfs(self):
39         self.bdf_desc_map = {}
40         out = check_output('lspci |grep Eth', shell=True)
41         for line in out.splitlines():
42             bdf, desc = line.split(' ', 1)
43             self.bdf_desc_map[bdf] = desc
44
45     def _get_devices(self):
46         for bdf, desc in self.bdf_desc_map.items():
47             device = get_device_name(bdf)
48             if device is None:
49                 LOG.info(
50                     "cann't find device name for bdf:%s, no driver is available.", bdf)
51                 try:
52                     self._load_driver(desc)
53                 except:
54                     LOG.warn("!!!unable to load_driver for device:%s", bdf)
55                 my_sleep(0.2)
56                 device = get_device_name(bdf)
57             self.bdf_device_map[bdf] = device
58             if device:
59                 self.device_bdf_map[device] = bdf
60                 check_call("ip link set dev %s up" % device, shell=True)
61
62     def _get_drivers(self):
63         for device, bdf in self.device_bdf_map.items():
64             buf = check_output('ethtool -i %s | head -n1' % device, shell=True)
65             driver = buf.split()[1]
66             self.bdf_driver_map[bdf] = driver
67
68     def _get_ip_macs(self):
69         for device, bdf in self.device_bdf_map.items():
70             buf = check_output("ip addr show dev %s" % device, shell=True)
71             macs = re.compile(
72                 "[A-F0-9]{2}(?::[A-F0-9]{2}){5}",
73                 re.IGNORECASE | re.MULTILINE)
74             for mac in macs.findall(buf):
75                 if mac.lower() in ('00:00:00:00:00:00', 'ff:ff:ff:ff:ff:ff'):
76                     continue
77                 else:
78                     break
79             ips = re.compile(
80                 r"inet (\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}/\d{1,2})",
81                 re.MULTILINE)
82             ip = ips.findall(buf)
83             if ip:
84                 self.bdf_ip_map[bdf] = ip[0]
85             else:
86                 self.bdf_ip_map[bdf] = None
87             self.bdf_mac_map[bdf] = mac
88             self.mac_bdf_map[mac] = bdf
89
90     def _load_driver(self, desc):
91         for key in default_drivers:
92             if key in desc:
93                 driver = default_drivers[key]
94                 LOG.info("try to load default driver [%s]", driver)
95                 check_call('modprobe %s' % driver, shell=True)
96                 break
97         else:
98             LOG.warn("unsupported nic type:%s", desc)
99
100
101 class DeviceManager(object):
102
103     def __init__(self):
104         super(DeviceManager, self).__init__()
105         mgr = netns.NetnsManager()
106         mgr.clean_all_namespace()
107         self.lspci_helper = LspciHelper()
108
109     def _get_device_detail(self, bdf):
110         device = self.lspci_helper.bdf_device_map[bdf]
111         mac = self.lspci_helper.bdf_mac_map[bdf]
112         ip = self.lspci_helper.bdf_ip_map[bdf]
113         desc = self.lspci_helper.bdf_desc_map[bdf]
114         driver = self.lspci_helper.bdf_driver_map[bdf]
115         detail = {
116             'bdf': bdf,
117             'device': device,
118             'mac': mac,
119             'ip': ip,
120             'desc': desc,
121             'driver': driver
122         }
123         return detail
124
125     def get_device_detail(self, identity):
126         """
127         Gets the detail of a network card.
128
129         :param identity: be it the mac address, bdf, device name of a network card.
130         :return: device detail of a network card.
131         """
132         if identity in self.lspci_helper.bdf_device_map:
133             bdf = identity
134         elif identity in self.lspci_helper.device_bdf_map:
135             bdf = self.lspci_helper.device_bdf_map[identity]
136         elif identity in self.lspci_helper.mac_bdf_map:
137             bdf = self.lspci_helper.mac_bdf_map[identity]
138         else:
139             raise Exception("cann't find the device by identity:%s" % identity)
140         return self._get_device_detail(bdf)
141
142     def get_device_verbose(self, identity):
143         return IPCommandHelper().get_device_verbose(identity)
144
145     def list_nic_devices(self):
146         """
147         Get all the details of network devices in the host.
148         :return: a list of network card detail.
149         """
150         device_list = []
151         for bdf in self.lspci_helper.bdf_device_map.keys():
152             detail = self._get_device_detail(bdf)
153             device_list.append(detail)
154         return device_list