1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """VPP Grub Utility Library."""
18 from vpplib.VPPUtil import VPPUtil
20 __all__ = ['VppGrubUtil']
23 class VppGrubUtil(object):
24 """ VPP Grub Utilities."""
26 def _get_current_cmdline(self):
28 Using /proc/cmdline return the current grub cmdline
30 :returns: The current grub cmdline
34 # Get the memory information using /proc/meminfo
35 cmd = 'sudo cat /proc/cmdline'
36 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
38 raise RuntimeError('{} on node {} {} {}'.
39 format(cmd, self._node['host'],
42 self._current_cmdline = stdout.strip('\n')
44 def _get_default_cmdline(self):
46 Using /etc/default/grub return the default grub cmdline
48 :returns: The default grub cmdline
52 # Get the default grub cmdline
53 rootdir = self._node['rootdir']
54 gfile = self._node['cpu']['grub_config_file']
55 grubcmdline = self._node['cpu']['grubcmdline']
56 cmd = 'cat {}'.format(rootdir + gfile)
57 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
59 raise RuntimeError('{} Executing failed on node {} {}'.
60 format(cmd, self._node['host'], stderr))
62 # Get the Default Linux command line, ignoring commented lines
63 lines = stdout.split('\n')
65 if line == '' or line[0] == '#':
67 ldefault = re.findall(r'{}=.+'.format(grubcmdline), line)
69 self._default_cmdline = ldefault[0]
72 def get_current_cmdline(self):
74 Returns the saved grub cmdline
76 :returns: The saved grub cmdline
79 return self._current_cmdline
81 def get_default_cmdline(self):
83 Returns the default grub cmdline
85 :returns: The default grub cmdline
88 return self._default_cmdline
90 def create_cmdline(self, isolated_cpus):
92 Create the new grub cmdline
94 :param isolated_cpus: The isolated cpu string
95 :type isolated_cpus: string
96 :returns: The command line
99 grubcmdline = self._node['cpu']['grubcmdline']
100 cmdline = self._default_cmdline
101 value = cmdline.split('{}='.format(grubcmdline))[1]
102 value = value.rstrip('"').lstrip('"')
104 # jadfix intel_pstate=disable sometimes cause networks to
106 # iommu = re.findall(r'iommu=\w+', value)
107 # pstate = re.findall(r'intel_pstate=\w+', value)
108 # If there is already some iommu commands set, leave them,
110 # if iommu == [] and pstate == []:
111 # value = '{} intel_pstate=disable'.format(value)
113 # Replace isolcpus with ours
114 isolcpus = re.findall(r'isolcpus=[\w+\-,]+', value)
116 if isolated_cpus != '':
117 value = "{} isolcpus={}".format(value, isolated_cpus)
119 if isolated_cpus != '':
120 value = re.sub(r'isolcpus=[\w+\-,]+',
121 'isolcpus={}'.format(isolated_cpus),
124 value = re.sub(r'isolcpus=[\w+\-,]+', '', value)
126 nohz = re.findall(r'nohz_full=[\w+\-,]+', value)
128 if isolated_cpus != '':
129 value = "{} nohz_full={}".format(value, isolated_cpus)
131 if isolated_cpus != '':
132 value = re.sub(r'nohz_full=[\w+\-,]+',
133 'nohz_full={}'.format(isolated_cpus),
136 value = re.sub(r'nohz_full=[\w+\-,]+', '', value)
138 rcu = re.findall(r'rcu_nocbs=[\w+\-,]+', value)
140 if isolated_cpus != '':
141 value = "{} rcu_nocbs={}".format(value, isolated_cpus)
143 if isolated_cpus != '':
144 value = re.sub(r'rcu_nocbs=[\w+\-,]+',
145 'rcu_nocbs={}'.format(isolated_cpus),
148 value = re.sub(r'rcu_nocbs=[\w+\-,]+', '', value)
150 value = value.lstrip(' ').rstrip(' ')
151 cmdline = '{}="{}"'.format(grubcmdline, value)
154 def apply_cmdline(self, node, isolated_cpus):
156 Apply cmdline to the default grub file
158 :param node: Node dictionary with cpuinfo.
159 :param isolated_cpus: The isolated cpu string
161 :type isolated_cpus: string
162 :return The vpp cmdline
166 vpp_cmdline = self.create_cmdline(isolated_cpus)
167 if vpp_cmdline == '':
171 # Save the original file
172 rootdir = node['rootdir']
173 grubcmdline = node['cpu']['grubcmdline']
174 ofilename = rootdir + node['cpu']['grub_config_file'] + '.orig'
175 filename = rootdir + node['cpu']['grub_config_file']
177 # Write the output file
178 # Does a copy of the original file exist, if not create one
179 (ret, stdout, stderr) = VPPUtil.exec_command('ls {}'.format(ofilename))
181 if stdout.strip('\n') != ofilename:
182 cmd = 'sudo cp {} {}'.format(filename, ofilename)
183 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
185 raise RuntimeError('{} failed on node {} {}'.
186 format(cmd, self._node['host'], stderr))
188 # Get the contents of the current grub config file
189 cmd = 'cat {}'.format(filename)
190 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
192 raise RuntimeError('{} failed on node {} {}'.format(
197 # Write the new contents
198 # Get the Default Linux command line, ignoring commented lines
200 lines = stdout.split('\n')
203 content += line + '\n'
206 content += line + '\n'
209 ldefault = re.findall(r'{}=.+'.format(grubcmdline), line)
211 content += vpp_cmdline + '\n'
213 content += line + '\n'
215 content = content.replace(r"`", r"\`")
216 content = content.rstrip('\n')
217 cmd = "sudo cat > {0} << EOF\n{1}\n".format(filename, content)
218 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
220 raise RuntimeError('{} failed on node {} {}'.format(
227 def __init__(self, node):
228 distro = VPPUtil.get_linux_distro()
229 if distro[0] == 'Ubuntu':
230 node['cpu']['grubcmdline'] = 'GRUB_CMDLINE_LINUX_DEFAULT'
232 node['cpu']['grubcmdline'] = 'GRUB_CMDLINE_LINUX'
235 self._current_cmdline = ""
236 self._default_cmdline = ""
237 self._get_current_cmdline()
238 self._get_default_cmdline()