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)
39 "{} on node {} {} {}".format(cmd, self._node["host"], stdout, stderr)
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)
60 "{} Executing failed on node {} {}".format(
61 cmd, self._node["host"], stderr
65 # Get the Default Linux command line, ignoring commented lines
66 lines = stdout.split("\n")
68 if line == "" or line[0] == "#":
70 ldefault = re.findall(r"{}=.+".format(grubcmdline), line)
72 self._default_cmdline = ldefault[0]
75 def get_current_cmdline(self):
77 Returns the saved grub cmdline
79 :returns: The saved grub cmdline
82 return self._current_cmdline
84 def get_default_cmdline(self):
86 Returns the default grub cmdline
88 :returns: The default grub cmdline
91 return self._default_cmdline
93 def create_cmdline(self, isolated_cpus):
95 Create the new grub cmdline
97 :param isolated_cpus: The isolated cpu string
98 :type isolated_cpus: string
99 :returns: The command line
102 grubcmdline = self._node["cpu"]["grubcmdline"]
103 cmdline = self._default_cmdline
104 value = cmdline.split("{}=".format(grubcmdline))[1]
105 value = value.rstrip('"').lstrip('"')
107 # jadfix intel_pstate=disable sometimes cause networks to
109 # iommu = re.findall(r'iommu=\w+', value)
110 # pstate = re.findall(r'intel_pstate=\w+', value)
111 # If there is already some iommu commands set, leave them,
113 # if iommu == [] and pstate == []:
114 # value = '{} intel_pstate=disable'.format(value)
116 # Replace isolcpus with ours
117 isolcpus = re.findall(r"isolcpus=[\w+\-,]+", value)
119 if isolated_cpus != "":
120 value = "{} isolcpus={}".format(value, isolated_cpus)
122 if isolated_cpus != "":
124 r"isolcpus=[\w+\-,]+", "isolcpus={}".format(isolated_cpus), value
127 value = re.sub(r"isolcpus=[\w+\-,]+", "", value)
129 nohz = re.findall(r"nohz_full=[\w+\-,]+", value)
131 if isolated_cpus != "":
132 value = "{} nohz_full={}".format(value, isolated_cpus)
134 if isolated_cpus != "":
136 r"nohz_full=[\w+\-,]+", "nohz_full={}".format(isolated_cpus), value
139 value = re.sub(r"nohz_full=[\w+\-,]+", "", value)
141 rcu = re.findall(r"rcu_nocbs=[\w+\-,]+", value)
143 if isolated_cpus != "":
144 value = "{} rcu_nocbs={}".format(value, isolated_cpus)
146 if isolated_cpus != "":
148 r"rcu_nocbs=[\w+\-,]+", "rcu_nocbs={}".format(isolated_cpus), value
151 value = re.sub(r"rcu_nocbs=[\w+\-,]+", "", value)
153 value = value.lstrip(" ").rstrip(" ")
154 cmdline = '{}="{}"'.format(grubcmdline, value)
157 def apply_cmdline(self, node, isolated_cpus):
159 Apply cmdline to the default grub file
161 :param node: Node dictionary with cpuinfo.
162 :param isolated_cpus: The isolated cpu string
164 :type isolated_cpus: string
165 :return The vpp cmdline
169 vpp_cmdline = self.create_cmdline(isolated_cpus)
172 # Save the original file
173 rootdir = node["rootdir"]
174 grubcmdline = node["cpu"]["grubcmdline"]
175 ofilename = rootdir + node["cpu"]["grub_config_file"] + ".orig"
176 filename = rootdir + node["cpu"]["grub_config_file"]
178 # Write the output file
179 # Does a copy of the original file exist, if not create one
180 (ret, stdout, stderr) = VPPUtil.exec_command("ls {}".format(ofilename))
182 if stdout.strip("\n") != ofilename:
183 cmd = "sudo cp {} {}".format(filename, ofilename)
184 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
187 "{} failed on node {} {}".format(
188 cmd, self._node["host"], stderr
192 # Get the contents of the current grub config file
193 cmd = "cat {}".format(filename)
194 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
197 "{} failed on node {} {}".format(cmd, self._node["host"], stderr)
200 # Write the new contents
201 # Get the Default Linux command line, ignoring commented lines
203 lines = stdout.split("\n")
206 content += line + "\n"
209 content += line + "\n"
212 ldefault = re.findall(r"{}=.+".format(grubcmdline), line)
214 content += vpp_cmdline + "\n"
216 content += line + "\n"
218 content = content.replace(r"`", r"\`")
219 content = content.rstrip("\n")
220 cmd = "sudo cat > {0} << EOF\n{1}\n".format(filename, content)
221 (ret, stdout, stderr) = VPPUtil.exec_command(cmd)
224 "{} failed on node {} {}".format(cmd, self._node["host"], stderr)
229 def __init__(self, node):
230 distro = VPPUtil.get_linux_distro()
231 if distro[0] == "Ubuntu":
232 node["cpu"]["grubcmdline"] = "GRUB_CMDLINE_LINUX_DEFAULT"
234 node["cpu"]["grubcmdline"] = "GRUB_CMDLINE_LINUX"
237 self._current_cmdline = ""
238 self._default_cmdline = ""
239 self._get_current_cmdline()
240 self._get_default_cmdline()