summaryrefslogtreecommitdiffstats
path: root/vstf/vstf/agent/env/basic/device_manager.py
blob: 3209d7c9e74153c5ff029c561914bc3cac395a6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
"""
Created on 2015-9-25

@author: y00228926
"""

import re
import logging
from vstf.agent.perf import netns
from vstf.common.utils import check_output, get_device_name, my_sleep, check_call, call, IPCommandHelper

LOG = logging.getLogger(__name__)

default_drivers = {
    '82599': 'ixgbe',
    '82576': 'igb',
}


class LspciHelper(object):
    def __init__(self):
        self.bdf_desc_map = {}
        self.bdf_device_map = {}
        self.device_bdf_map = {}
        self.bdf_ip_map = {}
        self.bdf_driver_map = {}
        self.mac_bdf_map = {}
        self.bdf_mac_map = {}
        self._get_bdfs()
        self._get_devices()
        self._get_drivers()
        self._get_ip_macs()

    def _get_bdfs(self):
        self.bdf_desc_map = {}
        out = check_output('lspci |grep Eth', shell=True)
        for line in out.splitlines():
            bdf, desc = line.split(' ', 1)
            self.bdf_desc_map[bdf] = desc

    def _get_devices(self):
        for bdf, desc in self.bdf_desc_map.items():
            device = get_device_name(bdf)
            if device is None:
                LOG.info("cann't find device name for bdf:%s, no driver is available.", bdf)
                try:
                    self._load_driver(desc)
                except:
                    LOG.warn("!!!unable to load_driver for device:%s", bdf)
                my_sleep(0.2)
                device = get_device_name(bdf)
            self.bdf_device_map[bdf] = device
            if device:
                self.device_bdf_map[device] = bdf
                check_call("ip link set dev %s up" % device, shell=True)

    def _get_drivers(self):
        for device, bdf in self.device_bdf_map.items():
            buf = check_output('ethtool -i %s | head -n1' % device, shell=True)
            driver = buf.split()[1]
            self.bdf_driver_map[bdf] = driver

    def _get_ip_macs(self):
        for device, bdf in self.device_bdf_map.items():
            buf = check_output("ip addr show dev %s" % device, shell=True)
            macs = re.compile("[A-F0-9]{2}(?::[A-F0-9]{2}){5}", re.IGNORECASE | re.MULTILINE)
            for mac in macs.findall(buf):
                if mac.lower() in ('00:00:00:00:00:00', 'ff:ff:ff:ff:ff:ff'):
                    continue
                else:
                    break
            ips = re.compile(r"inet (\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}/\d{1,2})", re.MULTILINE)
            ip = ips.findall(buf)
            if ip:
                self.bdf_ip_map[bdf] = ip[0]
            else:
                self.bdf_ip_map[bdf] = None
            self.bdf_mac_map[bdf] = mac
            self.mac_bdf_map[mac] = bdf

    def _load_driver(self, desc):
        for key in default_drivers:
            if key in desc:
                driver = default_drivers[key]
                LOG.info("try to load default driver [%s]", driver)
                check_call('modprobe %s' % driver, shell=True)
                break
        else:
            LOG.warn("unsupported nic type:%s", desc)


class DeviceManager(object):
    def __init__(self):
        super(DeviceManager, self).__init__()
        mgr = netns.NetnsManager()
        mgr.clean_all_namespace()
        self.lspci_helper = LspciHelper()

    def _get_device_detail(self, bdf):
        device = self.lspci_helper.bdf_device_map[bdf]
        mac = self.lspci_helper.bdf_mac_map[bdf]
        ip = self.lspci_helper.bdf_ip_map[bdf]
        desc = self.lspci_helper.bdf_desc_map[bdf]
        driver = self.lspci_helper.bdf_driver_map[bdf]
        detail = {
            'bdf': bdf,
            'device': device,
            'mac': mac,
            'ip': ip,
            'desc': desc,
            'driver': driver
        }
        return detail

    def get_device_detail(self, identity):
        """
        Gets the detail of a network card.

        :param identity: be it the mac address, bdf, device name of a network card.
        :return: device detail of a network card.
        """
        if identity in self.lspci_helper.bdf_device_map:
            bdf = identity
        elif identity in self.lspci_helper.device_bdf_map:
            bdf = self.lspci_helper.device_bdf_map[identity]
        elif identity in self.lspci_helper.mac_bdf_map:
            bdf = self.lspci_helper.mac_bdf_map[identity]
        else:
            raise Exception("cann't find the device by identity:%s" % identity)
        return self._get_device_detail(bdf)

    def get_device_verbose(self, identity):
        return IPCommandHelper().get_device_verbose(identity)

    def list_nic_devices(self):
        """
        Get all the details of network devices in the host.
        :return: a list of network card detail.
        """
        device_list = []
        for bdf in self.lspci_helper.bdf_device_map.keys():
            detail = self._get_device_detail(bdf)
            device_list.append(detail)
        return device_list