1 # Copyright 2015-2017 Intel Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 """Tools for access to OS details
25 from conf import settings as S
26 from tools.version import Version
28 def match_line(file_name, pattern):
29 """ loops through given file and returns first line matching given pattern
31 :returns: string with the matching line without end of line or None
34 with open(file_name, encoding="latin-1") as file_:
38 if not line.strip().startswith(pattern):
41 return line.strip().rstrip('\n')
49 :returns: Return distro name as a string
51 return ' '.join(distro.linux_distribution())
54 """Get kernel version.
56 :returns: Return kernel version as a string
58 return platform.release()
61 """Get CPU information.
63 :returns: Return CPU information as a string
65 cpu = match_line('/proc/cpuinfo', 'model name')
66 return cpu.split(':')[1] if cpu else cpu
69 """Get NIC(s) information.
71 :returns: Return NIC(s) information as a list
74 output = subprocess.check_output('lspci', shell=True)
75 output = output.decode(locale.getdefaultlocale()[1])
76 for line in output.split('\n'):
77 for nic in S.getValue('NICS'):
78 # lspci shows PCI addresses without domain part, i.e. last 7 chars
79 if line.startswith(nic['pci'][-7:]):
80 nics.append(''.join(line.split(':')[2:]).strip())
84 """Get platform information.
86 Currently this is the motherboard vendor, name and socket
89 :returns: Return platform information as a string
93 with open('/sys/class/dmi/id/board_vendor', 'r') as file_:
94 output.append(file_.readline().rstrip())
96 with open('/sys/class/dmi/id/board_name', 'r') as file_:
97 output.append(file_.readline().rstrip())
99 num_nodes = len([name for name in os.listdir(
100 '/sys/devices/system/node/') if name.startswith('node')])
101 output.append(''.join(['[', str(num_nodes), ' sockets]']))
103 return ' '.join(output).strip()
106 """Get number of CPU cores.
108 :returns: Return number of CPU cores
111 with open('/proc/cpuinfo') as file_:
113 if line.rstrip('\n').startswith('processor'):
117 # this code must be executed by at leat one core...
123 """Get memory information.
125 :returns: amount of system memory as string together with unit
127 memory = match_line('/proc/meminfo', 'MemTotal')
128 return memory.split(':')[1].strip() if memory else memory
130 def get_memory_bytes():
131 """Get memory information in bytes
133 :returns: amount of system memory
135 mem_list = get_memory().split(' ')
136 mem = float(mem_list[0].strip())
137 if mem_list.__len__() > 1:
138 unit = mem_list[1].strip().lower()
150 def get_pids(proc_names_list):
151 """ Get pid(s) of process(es) with given name(s)
153 :returns: list with pid(s) of given processes or None if processes
154 with given names are not running
158 pids = subprocess.check_output(['sudo', 'LC_ALL=' + S.getValue('DEFAULT_CMD_LOCALE'), 'pidof']
160 except subprocess.CalledProcessError:
161 # such process isn't running
164 return list(map(str, map(int, pids.split())))
166 def get_pid(proc_name_str):
167 """ Get pid(s) of process with given name
169 :returns: list with pid(s) of given process or None if process
170 with given name is not running
172 return get_pids([proc_name_str])
174 def pid_isalive(pid):
175 """ Checks if given PID is alive
177 :param pid: PID of the process
178 :returns: True if given process is running, False otherwise
180 return os.path.isdir('/proc/' + str(pid))
182 def get_bin_version(binary, regex):
183 """ get version of given binary selected by given regex
185 :returns: version string or None
188 output = str(subprocess.check_output(
189 binary, stderr=subprocess.STDOUT, shell=True).decode().rstrip('\n'))
190 except subprocess.CalledProcessError:
193 versions = re.findall(regex, output)
199 def get_git_tag(path):
200 """ get tag of recent commit from repository located at 'path'
202 :returns: git tag in form of string with commit hash or None if there
203 isn't any git repository at given path
206 if os.path.isdir(path):
207 return subprocess.check_output('cd {}; git rev-parse HEAD'.format(path), shell=True,
208 stderr=subprocess.DEVNULL).decode().rstrip('\n')
209 elif os.path.isfile(path):
210 return subprocess.check_output('cd $(dirname {}); git log -1 --pretty="%H" {}'.format(path, path),
211 shell=True, stderr=subprocess.DEVNULL).decode().rstrip('\n')
214 except subprocess.CalledProcessError:
217 # This function uses long switch per purpose, so let us suppress pylint warning too-many-branches
218 # pylint: disable=too-many-branches, too-many-statements
219 def get_version(app_name):
220 """ Get version of given application and its git tag
222 :returns: dictionary {'name' : app_name, 'version' : app_version, 'git_tag' : app_git_tag) in case that
223 version or git tag are not known or not applicaple, than None is returned for any unknown value
227 'ovs' : r'Open vSwitch\) ([0-9.]+)',
228 'testpmd' : r'RTE Version: \'\S+ ([0-9.]+)',
229 'qemu' : r'QEMU emulator version ([0-9.]+)',
230 'loopback_l2fwd' : os.path.join(S.getValue('ROOT_DIR'), 'src/l2fwd/l2fwd.c'),
231 'ixnet' : os.path.join(S.getValue('TRAFFICGEN_IXNET_LIB_PATH'), 'pkgIndex.tcl'),
232 'ixia' : os.path.join(S.getValue('TRAFFICGEN_IXIA_ROOT_DIR'), 'lib/ixTcl1.0/ixTclHal.tcl'),
233 'trex' : os.path.join(S.getValue('ROOT_DIR'), 'src/trex/trex'),
241 if app_name.lower().startswith('ovs'):
242 app_version = get_bin_version('{} --version'.format(S.getValue('TOOLS')['ovs-vswitchd']),
243 app_version_file['ovs'])
244 if 'vswitch_src' in S.getValue('TOOLS'):
245 app_git_tag = get_git_tag(S.getValue('TOOLS')['vswitch_src'])
246 elif app_name.lower() in ['dpdk', 'testpmd']:
247 app_version = get_bin_version('{} -v -h'.format(S.getValue('TOOLS')['testpmd']),
248 app_version_file['testpmd'])
249 # we have to consult PATHS settings to be sure, that dpdk/testpmd
250 # were build from the sources
251 if S.getValue('PATHS')[app_name.lower()]['type'] == 'src':
252 app_git_tag = get_git_tag(S.getValue('TOOLS')['dpdk_src'])
253 elif app_name.lower() == 'loopback_testpmd':
254 # testpmd inside the guest is compiled from downloaded sources
255 # stored at TOOS['dpdk_src'] directory
256 tmp_ver = ['', '', '']
258 # TOOLS dictionary is created during runtime and it is not
259 # available in some vsperf modes (e.g. -m trafficgen), thus
260 # following definition can't be part of app_version_file dict above
261 app_file = os.path.join(S.getValue('TOOLS')['dpdk_src'],
262 'lib/librte_eal/common/include/rte_version.h')
263 with open(app_file) as file_:
268 if line.startswith('#define RTE_VER_MAJOR'):
269 tmp_ver[0] = line.rstrip('\n').split(' ')[2]
271 elif line.startswith('#define RTE_VER_PATCH_LEVEL'):
272 tmp_ver[2] = line.rstrip('\n').split(' ')[2]
274 elif line.startswith('#define RTE_VER_PATCH_RELEASE'):
275 release = line.rstrip('\n').split(' ')[2]
276 if not '16' in release:
277 tmp_ver[2] += line.rstrip('\n').split(' ')[2]
279 elif line.startswith('#define RTE_VER_MINOR'):
281 tmp_ver[2] = line.rstrip('\n').split(' ')[2]
283 tmp_ver[1] = line.rstrip('\n').split(' ')[2]
285 elif line.startswith('#define RTE_VER_SUFFIX'):
286 tmp_ver[2] += line.rstrip('\n').split('"')[1]
288 elif line.startswith('#define RTE_VER_YEAR'):
290 tmp_ver[0] = line.rstrip('\n').split(' ')[2]
292 elif line.startswith('#define RTE_VER_MONTH'):
293 tmp_ver[1] = '{:0>2}'.format(line.rstrip('\n').split(' ')[2])
295 elif line.startswith('#define RTE_VER_RELEASE'):
296 release = line.rstrip('\n').split(' ')[2]
297 if not '16' in release:
298 tmp_ver[2] += line.rstrip('\n').split(' ')[2]
301 app_version = '.'.join(tmp_ver)
302 app_git_tag = get_git_tag(S.getValue('TOOLS')['dpdk_src'])
303 elif app_name.lower().startswith('qemu'):
304 app_version = get_bin_version('{} --version'.format(S.getValue('TOOLS')['qemu-system']),
305 app_version_file['qemu'])
306 if 'qemu_src' in S.getValue('TOOLS'):
307 app_git_tag = get_git_tag(S.getValue('TOOLS')['qemu_src'])
308 elif app_name.lower() == 'ixnet':
309 app_version = match_line(app_version_file['ixnet'], 'package provide IxTclNetwork')
311 app_version = app_version.split(' ')[3]
312 elif app_name.lower() == 'ixia':
313 app_version = match_line(app_version_file['ixia'], 'package provide IxTclHal')
315 app_version = app_version.split(' ')[3]
316 elif app_name.lower() == 'trex':
317 app_version = match_line(os.path.join(app_version_file['trex'], 'VERSION'), 'v')
318 app_git_tag = get_git_tag(app_version_file['trex'])
319 elif app_name.lower() == 'xena':
321 app_version = S.getValue('XENA_VERSION')
322 except AttributeError:
323 # setting was not available after execution
325 elif app_name.lower() == 'dummy':
326 # get git tag of file with Dummy implementation
327 app_git_tag = get_git_tag(os.path.join(S.getValue('ROOT_DIR'), 'tools/pkt_gen/dummy/dummy.py'))
328 elif app_name.lower() == 'vswitchperf':
329 app_git_tag = get_git_tag(S.getValue('ROOT_DIR'))
330 elif app_name.lower() == 'l2fwd':
331 app_version = match_line(app_version_file['loopback_l2fwd'], 'MODULE_VERSION')
333 app_version = app_version.split('"')[1]
334 app_git_tag = get_git_tag(app_version_file['loopback_l2fwd'])
335 elif app_name.lower() in ['linux_bridge', 'buildin']:
336 # without login into running VM, it is not possible to check bridge_utils version
340 return Version(app_name, app_version, app_git_tag)
342 def get_loopback_version(loopback_app_name):
343 """ Get version of given guest loopback application and its git tag
345 :returns: dictionary {'name' : app_name, 'version' : app_version, 'git_tag' : app_git_tag) in case that
346 version or git tag are not known or not applicaple, than None is returned for any unknown value
348 version = get_version("loopback_{}".format(loopback_app_name))
349 version.set_value('name', loopback_app_name)