Redhat and small system support
Initial 17.10 commit
Final 17.07 cleanup, 17.10 next
Added CentOS grub support, this should complete the CentOS support
Added Centos install/unistall
Added TCP parameters.

Change-Id: I064e3a4118969ac36e62924a6a3f8a98f132ba60
Signed-off-by: John DeNisco <jdenisco@cisco.com>
Signed-off-by: Dave Barach <dave@barachs.net>
diff --git a/extras/vpp_config/vpplib/VppGrubUtil.py b/extras/vpp_config/vpplib/VppGrubUtil.py
new file mode 100644
index 0000000..4aac427
--- /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()