diff options
Diffstat (limited to 'extras/vpp_config/vpplib/VppGrubUtil.py')
-rw-r--r-- | extras/vpp_config/vpplib/VppGrubUtil.py | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/extras/vpp_config/vpplib/VppGrubUtil.py b/extras/vpp_config/vpplib/VppGrubUtil.py new file mode 100644 index 00000000000..4aac427c22a --- /dev/null +++ b/extras/vpp_config/vpplib/VppGrubUtil.py @@ -0,0 +1,236 @@ +# 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('"') + + 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() |