339bc6b51d
On ubuntu: $cd <basedir>/extras/vpp_config $./scripts/clean.sh $./scripts/cp-data.sh $sudo apt-get install python3-pip python3-setuptools $python3 -m pip install . $vpp-config Changes: * Convert to print() function. * raw_input changes. * floor division changes. * replace vpp-config.py with a setuptools 'vpp-config' entry_point. * replace netaddr with ipaddress from the standard library and backport. * .decode() subprocess.Popen's stdout because in python3 they are bytes. Change-Id: Id98894ee54e0c31a0ba0304134b159caef415705 Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
239 lines
8.1 KiB
Python
239 lines
8.1 KiB
Python
# Copyright (c) 2016 Cisco and/or its affiliates.
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at:
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""VPP Grub Utility Library."""
|
|
|
|
import re
|
|
|
|
from vpplib.VPPUtil import VPPUtil
|
|
|
|
__all__ = ['VppGrubUtil']
|
|
|
|
|
|
class VppGrubUtil(object):
|
|
""" VPP Grub Utilities."""
|
|
|
|
def _get_current_cmdline(self):
|
|
"""
|
|
Using /proc/cmdline return the current grub cmdline
|
|
|
|
:returns: The current grub cmdline
|
|
:rtype: string
|
|
"""
|
|
|
|
# Get the memory information using /proc/meminfo
|
|
cmd = 'sudo cat /proc/cmdline'
|
|
(ret, stdout, stderr) = VPPUtil.exec_command(cmd)
|
|
if ret != 0:
|
|
raise RuntimeError('{} on node {} {} {}'.
|
|
format(cmd, self._node['host'],
|
|
stdout, stderr))
|
|
|
|
self._current_cmdline = stdout.strip('\n')
|
|
|
|
def _get_default_cmdline(self):
|
|
"""
|
|
Using /etc/default/grub return the default grub cmdline
|
|
|
|
:returns: The default grub cmdline
|
|
:rtype: string
|
|
"""
|
|
|
|
# Get the default grub cmdline
|
|
rootdir = self._node['rootdir']
|
|
gfile = self._node['cpu']['grub_config_file']
|
|
grubcmdline = self._node['cpu']['grubcmdline']
|
|
cmd = 'cat {}'.format(rootdir + gfile)
|
|
(ret, stdout, stderr) = VPPUtil.exec_command(cmd)
|
|
if ret != 0:
|
|
raise RuntimeError('{} Executing failed on node {} {}'.
|
|
format(cmd, self._node['host'], stderr))
|
|
|
|
# Get the Default Linux command line, ignoring commented lines
|
|
lines = stdout.split('\n')
|
|
for line in lines:
|
|
if line == '' or line[0] == '#':
|
|
continue
|
|
ldefault = re.findall(r'{}=.+'.format(grubcmdline), line)
|
|
if ldefault:
|
|
self._default_cmdline = ldefault[0]
|
|
break
|
|
|
|
def get_current_cmdline(self):
|
|
"""
|
|
Returns the saved grub cmdline
|
|
|
|
:returns: The saved grub cmdline
|
|
:rtype: string
|
|
"""
|
|
return self._current_cmdline
|
|
|
|
def get_default_cmdline(self):
|
|
"""
|
|
Returns the default grub cmdline
|
|
|
|
:returns: The default grub cmdline
|
|
:rtype: string
|
|
"""
|
|
return self._default_cmdline
|
|
|
|
def create_cmdline(self, isolated_cpus):
|
|
"""
|
|
Create the new grub cmdline
|
|
|
|
:param isolated_cpus: The isolated cpu string
|
|
:type isolated_cpus: string
|
|
:returns: The command line
|
|
:rtype: string
|
|
"""
|
|
grubcmdline = self._node['cpu']['grubcmdline']
|
|
cmdline = self._default_cmdline
|
|
value = cmdline.split('{}='.format(grubcmdline))[1]
|
|
value = value.rstrip('"').lstrip('"')
|
|
|
|
# jadfix intel_pstate=disable sometimes cause networks to
|
|
# hang on reboot
|
|
# iommu = re.findall(r'iommu=\w+', value)
|
|
# pstate = re.findall(r'intel_pstate=\w+', value)
|
|
# If there is already some iommu commands set, leave them,
|
|
# if not use ours
|
|
# if iommu == [] and pstate == []:
|
|
# value = '{} intel_pstate=disable'.format(value)
|
|
|
|
# Replace isolcpus with ours
|
|
isolcpus = re.findall(r'isolcpus=[\w+\-,]+', value)
|
|
if not isolcpus:
|
|
if isolated_cpus != '':
|
|
value = "{} isolcpus={}".format(value, isolated_cpus)
|
|
else:
|
|
if isolated_cpus != '':
|
|
value = re.sub(r'isolcpus=[\w+\-,]+',
|
|
'isolcpus={}'.format(isolated_cpus),
|
|
value)
|
|
else:
|
|
value = re.sub(r'isolcpus=[\w+\-,]+', '', value)
|
|
|
|
nohz = re.findall(r'nohz_full=[\w+\-,]+', value)
|
|
if not nohz:
|
|
if isolated_cpus != '':
|
|
value = "{} nohz_full={}".format(value, isolated_cpus)
|
|
else:
|
|
if isolated_cpus != '':
|
|
value = re.sub(r'nohz_full=[\w+\-,]+',
|
|
'nohz_full={}'.format(isolated_cpus),
|
|
value)
|
|
else:
|
|
value = re.sub(r'nohz_full=[\w+\-,]+', '', value)
|
|
|
|
rcu = re.findall(r'rcu_nocbs=[\w+\-,]+', value)
|
|
if not rcu:
|
|
if isolated_cpus != '':
|
|
value = "{} rcu_nocbs={}".format(value, isolated_cpus)
|
|
else:
|
|
if isolated_cpus != '':
|
|
value = re.sub(r'rcu_nocbs=[\w+\-,]+',
|
|
'rcu_nocbs={}'.format(isolated_cpus),
|
|
value)
|
|
else:
|
|
value = re.sub(r'rcu_nocbs=[\w+\-,]+', '', value)
|
|
|
|
value = value.lstrip(' ').rstrip(' ')
|
|
cmdline = '{}="{}"'.format(grubcmdline, value)
|
|
return cmdline
|
|
|
|
def apply_cmdline(self, node, isolated_cpus):
|
|
"""
|
|
Apply cmdline to the default grub file
|
|
|
|
:param node: Node dictionary with cpuinfo.
|
|
:param isolated_cpus: The isolated cpu string
|
|
:type node: dict
|
|
:type isolated_cpus: string
|
|
:return The vpp cmdline
|
|
:rtype string
|
|
"""
|
|
|
|
vpp_cmdline = self.create_cmdline(isolated_cpus)
|
|
if vpp_cmdline == '':
|
|
return vpp_cmdline
|
|
|
|
# Update grub
|
|
# Save the original file
|
|
rootdir = node['rootdir']
|
|
grubcmdline = node['cpu']['grubcmdline']
|
|
ofilename = rootdir + node['cpu']['grub_config_file'] + '.orig'
|
|
filename = rootdir + node['cpu']['grub_config_file']
|
|
|
|
# Write the output file
|
|
# Does a copy of the original file exist, if not create one
|
|
(ret, stdout, stderr) = VPPUtil.exec_command('ls {}'.format(ofilename))
|
|
if ret != 0:
|
|
if stdout.strip('\n') != ofilename:
|
|
cmd = 'sudo cp {} {}'.format(filename, ofilename)
|
|
(ret, stdout, stderr) = VPPUtil.exec_command(cmd)
|
|
if ret != 0:
|
|
raise RuntimeError('{} failed on node {} {}'.
|
|
format(cmd, self._node['host'], stderr))
|
|
|
|
# Get the contents of the current grub config file
|
|
cmd = 'cat {}'.format(filename)
|
|
(ret, stdout, stderr) = VPPUtil.exec_command(cmd)
|
|
if ret != 0:
|
|
raise RuntimeError('{} failed on node {} {}'.format(
|
|
cmd,
|
|
self._node['host'],
|
|
stderr))
|
|
|
|
# Write the new contents
|
|
# Get the Default Linux command line, ignoring commented lines
|
|
content = ""
|
|
lines = stdout.split('\n')
|
|
for line in lines:
|
|
if line == '':
|
|
content += line + '\n'
|
|
continue
|
|
if line[0] == '#':
|
|
content += line + '\n'
|
|
continue
|
|
|
|
ldefault = re.findall(r'{}=.+'.format(grubcmdline), line)
|
|
if ldefault:
|
|
content += vpp_cmdline + '\n'
|
|
else:
|
|
content += line + '\n'
|
|
|
|
content = content.replace(r"`", r"\`")
|
|
content = content.rstrip('\n')
|
|
cmd = "sudo cat > {0} << EOF\n{1}\n".format(filename, content)
|
|
(ret, stdout, stderr) = VPPUtil.exec_command(cmd)
|
|
if ret != 0:
|
|
raise RuntimeError('{} failed on node {} {}'.format(
|
|
cmd,
|
|
self._node['host'],
|
|
stderr))
|
|
|
|
return vpp_cmdline
|
|
|
|
def __init__(self, node):
|
|
distro = VPPUtil.get_linux_distro()
|
|
if distro[0] == 'Ubuntu':
|
|
node['cpu']['grubcmdline'] = 'GRUB_CMDLINE_LINUX_DEFAULT'
|
|
else:
|
|
node['cpu']['grubcmdline'] = 'GRUB_CMDLINE_LINUX'
|
|
|
|
self._node = node
|
|
self._current_cmdline = ""
|
|
self._default_cmdline = ""
|
|
self._get_current_cmdline()
|
|
self._get_default_cmdline()
|