Merge "Change PTL informatin in INFO"
[bottlenecks.git] / testsuites / vstf / vstf_scripts / vstf / common / utils.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 import subprocess
13 import random
14 import os
15 import signal
16 import time
17 from StringIO import StringIO
18
19 LOG = logging.getLogger(__name__)
20
21
22 def info():
23     def _deco(func):
24         def __deco(*args, **kwargs):
25             if "shell" in kwargs and kwargs["shell"]:
26                 LOG.info(args[0])
27             else:
28                 LOG.info(' '.join(args[0]))
29             return func(*args, **kwargs)
30         return __deco
31     return _deco
32
33
34 @info()
35 def call(cmd, shell=False):
36     ret = subprocess.call(cmd, shell=shell)
37     if ret != 0:
38         LOG.info("warning: %s not success.", cmd)
39
40
41 @info()
42 def check_call(cmd, shell=False):
43     subprocess.check_call(cmd, shell=shell)
44
45
46 @info()
47 def check_output(cmd, shell=False):
48     return subprocess.check_output(cmd, shell=shell)
49
50
51 @info()
52 def my_popen(cmd, shell=False, stdout=None, stderr=None):
53     return subprocess.Popen(cmd, shell=shell, stdout=stdout, stderr=stderr)
54
55
56 def ping(ip):
57     cmd = "ping -w2 -c1 %s" % ip
58     p = my_popen(cmd, shell=True)
59     return 0 == p.wait()
60
61
62 def get_device_name(bdf):
63     path = '/sys/bus/pci/devices/0000:%s/net/' % bdf
64     path1 = '/sys/bus/pci/devices/0000:%s/virtio*/net/' % bdf
65     if os.path.exists(path):
66         device = check_output("ls " + path, shell=True).strip()
67         return device
68     else:  # virtio driver
69         try:
70             device = check_output("ls " + path1, shell=True).strip()
71             return device
72         except Exception:
73             return None
74
75
76 def my_sleep(delay):
77     LOG.info('sleep %s' % delay)
78     time.sleep(delay)
79
80
81 def my_mkdir(filepath):
82     try:
83         LOG.info("mkdir -p %s" % filepath)
84         os.makedirs(filepath)
85     except OSError as e:
86         if e.errno == 17:
87             LOG.info("! %s already exists" % filepath)
88         else:
89             raise
90
91
92 def get_eth_by_bdf(bdf):
93     bdf = bdf.replace(' ', '')
94     path = '/sys/bus/pci/devices/0000:%s/net/' % bdf
95     if os.path.exists(path):
96         device = check_output("ls " + path, shell=True).strip()
97     else:
98         raise Exception("cann't get device name of bdf:%s" % bdf)
99     return device
100
101
102 def check_and_kill(process):
103     cmd = "ps -ef | grep -v grep | awk '{print $8}' | grep -w %s | wc -l" % process
104     out = check_output(cmd, shell=True)
105     if int(out):
106         check_call(['killall', process])
107
108
109 def list_mods():
110     return check_output(
111         "lsmod | sed 1,1d | awk '{print $1}'",
112         shell=True).split()
113
114
115 def check_and_rmmod(mod):
116     if mod in list_mods():
117         check_call(['rmmod', mod])
118
119
120 def kill_by_name(process):
121     out = check_output(['ps', '-A'])
122     for line in out.splitlines():
123         values = line.split()
124         pid, name = values[0], values[3]
125         if process == name:
126             pid = int(pid)
127             os.kill(pid, signal.SIGKILL)
128             LOG.info("os.kill(%s)" % pid)
129
130
131 def ns_cmd(ns, cmd):
132     netns_exec_str = "ip netns exec %s "
133     if ns in (None, 'null', 'None', 'none'):
134         pass
135     else:
136         cmd = (netns_exec_str % ns) + cmd
137     return cmd
138
139
140 def randomMAC():
141     mac = [0x00, 0x16, 0x3e,
142            random.randint(0x00, 0x7f),
143            random.randint(0x00, 0xff),
144            random.randint(0x00, 0xff)]
145     return ':'.join(map(lambda x: "%02x" % x, mac))
146
147
148 class IPCommandHelper(object):
149
150     def __init__(self, ns=None):
151         self.devices = []
152         self.macs = []
153         self.device_mac_map = {}
154         self.mac_device_map = {}
155         self.bdf_device_map = {}
156         self.device_bdf_map = {}
157         self.mac_bdf_map = {}
158         self.bdf_mac_map = {}
159         cmd = "ip link"
160         if ns:
161             cmd = "ip netns exec %s " % ns + cmd
162         buf = check_output(cmd, shell=True)
163         sio = StringIO(buf)
164         for line in sio:
165             m = re.match(r'^\d+:(.*):.*', line)
166             if m and m.group(1).strip() != "lo":
167                 device = m.group(1).strip()
168                 self.devices.append(device)
169                 mac = self._get_mac(ns, device)
170                 self.macs.append(mac)
171         for device, mac in zip(self.devices, self.macs):
172             self.device_mac_map[device] = mac
173             self.mac_device_map[mac] = device
174
175         cmd = "ethtool -i %s"
176         if ns:
177             cmd = "ip netns exec %s " % ns + cmd
178         for device in self.devices:
179             buf = check_output(cmd % device, shell=True)
180             bdfs = re.findall(
181                 r'^bus-info: \d{4}:(\d{2}:\d{2}\.\d*)$',
182                 buf,
183                 re.MULTILINE)
184             if bdfs:
185                 self.bdf_device_map[bdfs[0]] = device
186                 self.device_bdf_map[device] = bdfs[0]
187                 mac = self.device_mac_map[device]
188                 self.mac_bdf_map[mac] = bdfs[0]
189                 self.bdf_mac_map[bdfs[0]] = mac
190
191     @staticmethod
192     def _get_mac(ns, device):
193         cmd = "ip addr show dev %s" % device
194         if ns:
195             cmd = "ip netns exec %s " % ns + cmd
196         buf = check_output(cmd, shell=True)
197         macs = re.compile(
198             r"[A-F0-9]{2}(?::[A-F0-9]{2}){5}",
199             re.IGNORECASE | re.MULTILINE)
200         for mac in macs.findall(buf):
201             if mac.lower() not in ('00:00:00:00:00:00', 'ff:ff:ff:ff:ff:ff'):
202                 return mac
203         return None
204
205     def get_device_verbose(self, identity):
206         if identity in self.device_mac_map:
207             device = identity
208         elif identity in self.bdf_device_map:
209             device = self.bdf_device_map[identity]
210         elif identity in self.mac_device_map:
211             device = self.mac_device_map[identity]
212         else:
213             raise Exception("cann't find the device by identity:%s" % identity)
214         detail = {
215             'bdf': self.device_bdf_map[device] if device in self.device_bdf_map else None,
216             'iface': device,
217             'mac': self.device_mac_map[device] if device in self.device_mac_map else None,
218         }
219         return detail
220
221
222 class AttrDict(dict):
223     """A dictionary with attribute-style access. It maps attribute access to
224     the real dictionary.  """
225
226     def __init__(self, init={}):
227         dict.__init__(self, init)
228
229     def __getstate__(self):
230         return self.__dict__.items()
231
232     def __setstate__(self, items):
233         for key, val in items:
234             self.__dict__[key] = val
235
236     def __repr__(self):
237         return "%s(%s)" % (self.__class__.__name__, dict.__repr__(self))
238
239     def __setitem__(self, key, value):
240         return super(AttrDict, self).__setitem__(key, value)
241
242     def __getitem__(self, name):
243         return super(AttrDict, self).__getitem__(name)
244
245     def __delitem__(self, name):
246         return super(AttrDict, self).__delitem__(name)
247
248     __getattr__ = __getitem__
249     __setattr__ = __setitem__
250
251     def copy(self):
252         ch = AttrDict(self)
253         return ch
254
255
256 if __name__ == "__main__":
257     ipcmd = IPCommandHelper()
258     print ipcmd.device_mac_map
259     print ipcmd.mac_device_map
260     print ipcmd.bdf_device_map
261     print ipcmd.device_bdf_map
262     print ipcmd.mac_bdf_map
263     print ipcmd.bdf_mac_map
264     print ipcmd.get_device_verbose("tap0")