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