1 # Copyright 2015-2016 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
23 from conf import settings as S
25 def match_line(file_name, pattern):
26 """ loops through given file and returns first line matching given pattern
28 :returns: string with the matching line without end of line or None
31 with open(file_name, encoding="latin-1") as file_:
35 if not line.strip().startswith(pattern):
38 return line.strip().rstrip('\n')
46 :returns: Return distro name as a string
48 return ' '.join(platform.dist())
51 """Get kernel version.
53 :returns: Return kernel version as a string
55 return platform.release()
58 """Get CPU information.
60 :returns: Return CPU information as a string
62 cpu = match_line('/proc/cpuinfo', 'model name')
63 return cpu.split(':')[1] if cpu else cpu
66 """Get NIC(s) information.
68 :returns: Return NIC(s) information as a list
71 output = subprocess.check_output('lspci', shell=True)
72 output = output.decode(locale.getdefaultlocale()[1])
73 for line in output.split('\n'):
74 for nic in S.getValue('NICS'):
75 # lspci shows PCI addresses without domain part, i.e. last 7 chars
76 if line.startswith(nic['pci'][-7:]):
77 nics.append(''.join(line.split(':')[2:]).strip())
81 """Get platform information.
83 Currently this is the motherboard vendor, name and socket
86 :returns: Return platform information as a string
90 with open('/sys/class/dmi/id/board_vendor', 'r') as file_:
91 output.append(file_.readline().rstrip())
93 with open('/sys/class/dmi/id/board_name', 'r') as file_:
94 output.append(file_.readline().rstrip())
96 num_nodes = len([name for name in os.listdir(
97 '/sys/devices/system/node/') if name.startswith('node')])
98 output.append(''.join(['[', str(num_nodes), ' sockets]']))
100 return ' '.join(output).strip()
103 """Get number of CPU cores.
105 :returns: Return number of CPU cores
108 with open('/proc/cpuinfo') as file_:
110 if line.rstrip('\n').startswith('processor'):
114 # this code must be executed by at leat one core...
120 """Get memory information.
122 :returns: amount of system memory as string together with unit
124 memory = match_line('/proc/meminfo', 'MemTotal')
125 return memory.split(':')[1].strip() if memory else memory
127 def get_memory_bytes():
128 """Get memory information in bytes
130 :returns: amount of system memory
132 mem_list = get_memory().split(' ')
133 mem = float(mem_list[0].strip())
134 if mem_list.__len__() > 1:
135 unit = mem_list[1].strip().lower()
147 def get_pids(proc_names_list):
148 """ Get pid(s) of process(es) with given name(s)
150 :returns: list with pid(s) of given processes or None if processes
151 with given names are not running
155 pids = subprocess.check_output(['sudo', 'LC_ALL=' + S.getValue('DEFAULT_CMD_LOCALE'), 'pidof']
157 except subprocess.CalledProcessError:
158 # such process isn't running
161 return list(map(str, map(int, pids.split())))
163 def get_pid(proc_name_str):
164 """ Get pid(s) of process with given name
166 :returns: list with pid(s) of given process or None if process
167 with given name is not running
169 return get_pids([proc_name_str])
171 def pid_isalive(pid):
172 """ Checks if given PID is alive
174 :param pid: PID of the process
175 :returns: True if given process is running, False otherwise
177 return os.path.isdir('/proc/' + str(pid))
179 # This function uses long switch per purpose, so let us suppress pylint warning too-many-branches
180 # pylint: disable=R0912
181 def get_version(app_name):
182 """ Get version of given application and its git tag
184 :returns: dictionary {'name' : app_name, 'version' : app_version, 'git_tag' : app_git_tag) in case that
185 version or git tag are not known or not applicaple, than None is returned for any unknown value
189 'ovs' : os.path.join(S.getValue('OVS_DIR'), 'include/openvswitch/version.h'),
190 'dpdk' : os.path.join(S.getValue('RTE_SDK'), 'lib/librte_eal/common/include/rte_version.h'),
191 'qemu' : os.path.join(S.getValue('QEMU_DIR'), 'VERSION'),
192 'l2fwd' : os.path.join(S.getValue('ROOT_DIR'), 'src/l2fwd/l2fwd.c'),
193 'ixnet' : os.path.join(S.getValue('TRAFFICGEN_IXNET_LIB_PATH'), 'pkgIndex.tcl'),
197 def get_git_tag(path):
198 """ get tag of recent commit from repository located at 'path'
200 :returns: git tag in form of string with commit hash or None if there
201 isn't any git repository at given path
204 if os.path.isdir(path):
205 return subprocess.check_output('cd {}; git rev-parse HEAD'.format(path), shell=True,
206 stderr=subprocess.DEVNULL).decode().rstrip('\n')
207 elif os.path.isfile(path):
208 return subprocess.check_output('cd $(dirname {}); git log -1 --pretty="%H" {}'.format(path, path),
209 shell=True, stderr=subprocess.DEVNULL).decode().rstrip('\n')
212 except subprocess.CalledProcessError:
219 if app_name.lower().startswith('ovs'):
220 app_version = match_line(app_version_file['ovs'], '#define OVS_PACKAGE_VERSION')
222 app_version = app_version.split('"')[1]
223 app_git_tag = get_git_tag(S.getValue('OVS_DIR'))
224 elif app_name.lower() in ['dpdk', 'testpmd']:
225 tmp_ver = ['', '', '']
227 with open(app_version_file['dpdk']) as file_:
232 if line.startswith('#define RTE_VER_MAJOR'):
233 tmp_ver[0] = line.rstrip('\n').split(' ')[2]
235 elif line.startswith('#define RTE_VER_PATCH_LEVEL'):
236 tmp_ver[2] = line.rstrip('\n').split(' ')[2]
238 elif line.startswith('#define RTE_VER_PATCH_RELEASE'):
239 release = line.rstrip('\n').split(' ')[2]
240 if not '16' in release:
241 tmp_ver[2] += line.rstrip('\n').split(' ')[2]
243 elif line.startswith('#define RTE_VER_MINOR'):
245 tmp_ver[2] = line.rstrip('\n').split(' ')[2]
247 tmp_ver[1] = line.rstrip('\n').split(' ')[2]
249 elif line.startswith('#define RTE_VER_SUFFIX'):
250 tmp_ver[2] += line.rstrip('\n').split('"')[1]
252 elif line.startswith('#define RTE_VER_YEAR'):
254 tmp_ver[0] = line.rstrip('\n').split(' ')[2]
256 elif line.startswith('#define RTE_VER_MONTH'):
257 tmp_ver[1] = '{:0>2}'.format(line.rstrip('\n').split(' ')[2])
259 elif line.startswith('#define RTE_VER_RELEASE'):
260 release = line.rstrip('\n').split(' ')[2]
261 if not '16' in release:
262 tmp_ver[2] += line.rstrip('\n').split(' ')[2]
265 app_version = '.'.join(tmp_ver)
266 app_git_tag = get_git_tag(S.getValue('RTE_SDK'))
267 elif app_name.lower().startswith('qemu'):
268 app_version = match_line(app_version_file['qemu'], '')
269 app_git_tag = get_git_tag(S.getValue('QEMU_DIR'))
270 elif app_name.lower() == 'ixnet':
271 app_version = match_line(app_version_file['ixnet'], 'package provide IxTclNetwork')
273 app_version = app_version.split(' ')[3]
274 elif app_name.lower() == 'xena':
276 app_version = S.getValue('XENA_VERSION')
277 except AttributeError:
278 # setting was not available after execution
280 elif app_name.lower() == 'dummy':
281 # get git tag of file with Dummy implementation
282 app_git_tag = get_git_tag(os.path.join(S.getValue('ROOT_DIR'), 'tools/pkt_gen/dummy/dummy.py'))
283 elif app_name.lower() == 'vswitchperf':
284 app_git_tag = get_git_tag(S.getValue('ROOT_DIR'))
285 elif app_name.lower() == 'l2fwd':
286 app_version = match_line(app_version_file[app_name], 'MODULE_VERSION')
288 app_version = app_version.split('"')[1]
289 app_git_tag = get_git_tag(app_version_file[app_name])
290 elif app_name.lower() in ['linux_bridge', 'buildin']:
291 # without login into running VM, it is not possible to check bridge_utils version
295 return {'name' : app_name, 'version' : app_version, 'git_tag' : app_git_tag}