File 0001-Update-osutil-support-for-SUSE-distro.patch of Package openstack-octavia

From b4020c50a8136bdf1418e64a7461c7e240c395ea Mon Sep 17 00:00:00 2001
From: Swaminathan Vasudevan <SVasudevan@suse.com>
Date: Wed, 7 Feb 2018 09:09:28 -0800
Subject: [PATCH] Update osutil support for SUSE distro

Provide osutil support for SUSE distro to create networks
in a SUSE distro based Amphora Image.
This is a generic patch that can support different SUSE
flavors.
This patch will be the base patch and the diskimage builder
and devstack related changes to include the elements to build
the required services will depend on this patch

Change-Id: I29eeebb15a58cc54789edcb11c64ba47373cfb7b
(cherry picked from commit 24309d11547caba580c6082836798b0f28ed0859)
(cherry picked from commit 7ddf1cae2ea1785eb443964c74b6d41f3edd3dce)
---
 .../backends/agent/api_server/osutils.py      | 160 ++++++++++++++++
 .../templates/suse_plug_port_ethX.conf.j2     |  45 +++++
 .../templates/suse_plug_vip_ethX.conf.j2      |  59 ++++++
 .../templates/suse_route_ethX.conf.j2         |  23 +++
 octavia/common/constants.py                   |   1 +
 .../backends/agent/api_server/test_osutils.py | 175 ++++++++++++++++++
 6 files changed, 463 insertions(+)
 create mode 100644 octavia/amphorae/backends/agent/api_server/templates/suse_plug_port_ethX.conf.j2
 create mode 100644 octavia/amphorae/backends/agent/api_server/templates/suse_plug_vip_ethX.conf.j2
 create mode 100644 octavia/amphorae/backends/agent/api_server/templates/suse_route_ethX.conf.j2

diff --git a/octavia/amphorae/backends/agent/api_server/osutils.py b/octavia/amphorae/backends/agent/api_server/osutils.py
index 4f5431c9..bf8e43b5 100644
--- a/octavia/amphorae/backends/agent/api_server/osutils.py
+++ b/octavia/amphorae/backends/agent/api_server/osutils.py
@@ -563,3 +563,163 @@ class CentOS(RH):
     @classmethod
     def is_os_name(cls, os_name):
         return os_name in ['centos']
+
+
+class SUSE(BaseOS):
+
+    ETH_X_PORT_CONF = 'suse_plug_port_ethX.conf.j2'
+    ETH_X_VIP_CONF = 'suse_plug_vip_ethX.conf.j2'
+    ROUTE_ETH_X_CONF = 'suse_route_ethX.conf.j2'
+
+    @classmethod
+    def is_os_name(cls, os_name):
+        return os_name.lower() in ['opensuse', 'suse', 'sles']
+
+    def cmd_get_version_of_installed_package(self, package_name):
+        name = self._map_package_name(package_name)
+        return "rpm -q --queryformat %{{VERSION}} {name}".format(name=name)
+
+    def get_network_interface_file(self, interface):
+        if CONF.amphora_agent.agent_server_network_file:
+            LOG.warning('CONF.amphora_agent.agent_server_network_file: %s '
+                        'will be ignored as it is not supported by the SUSE '
+                        'platforms. Please use '
+                        'CONF.amphora_agent.agent_server_network_dir option '
+                        'instead.',
+                        CONF.amphora_agent.agent_server_network_file)
+        ifcfg_prefix = 'ifcfg-' if 'ifroute' not in interface else ''
+        if CONF.amphora_agent.agent_server_network_dir:
+            network_dir = CONF.amphora_agent.agent_server_network_dir
+        else:
+            network_dir = consts.SUSE_AMP_NET_DIR_TEMPLATE.format(
+                netns=consts.AMPHORA_NAMESPACE)
+        return os.path.join(network_dir, ifcfg_prefix + interface)
+
+    def get_network_path(self):
+        return '/etc/sysconfig/network'
+
+    def get_netns_network_dir(self):
+        return 'sysconfig/network'
+
+    def get_static_routes_interface_file(self, interface):
+        return self.get_network_interface_file('ifroute-' + interface)
+
+    def create_netns_dir(
+            self, network_dir=None, netns_network_dir=None, ignore=None):
+        if not netns_network_dir:
+            netns_network_dir = self.get_netns_network_dir()
+            LOG.debug("Netns network directory: %s", netns_network_dir)
+        if not network_dir:
+            network_dir = self.get_network_path()
+            LOG.debug("Network directory: %s", network_dir)
+        if not ignore:
+            ignore = shutil.ignore_patterns('ifcfg-eth0*')
+        super(SUSE, self).create_netns_dir(
+            network_dir, netns_network_dir, ignore)
+
+    def write_interfaces_file(self):
+        # No interfaces file in SUSE distros.
+        return
+
+    def write_vip_interface_file(self, interface_file_path,
+                                 primary_interface, vip, ip, broadcast,
+                                 netmask, gateway, mtu, vrrp_ip, vrrp_version,
+                                 render_host_routes, template_vip=None):
+        if not template_vip:
+            template_vip = j2_env.get_template(self.ETH_X_VIP_CONF)
+        super(SUSE, self).write_vip_interface_file(
+            interface_file_path, primary_interface, vip, ip, broadcast,
+            netmask, gateway, mtu, vrrp_ip, vrrp_version, render_host_routes,
+            template_vip)
+
+        routes_interface_file_path = (
+            self.get_static_routes_interface_file(primary_interface))
+        template_routes = j2_env.get_template(self.ROUTE_ETH_X_CONF)
+
+        self.write_static_routes_interface_file(
+            routes_interface_file_path, primary_interface,
+            render_host_routes, template_routes, gateway, vip)
+        # NOTE: Copy{netns}/etc/sysconfig/network/ifroute-* file to
+        # /etc/sysconfig/network to overcome an issue with the
+        # ifup-route and namespace.
+        dst = self.get_network_path()
+        shutil.copy2(routes_interface_file_path, dst)
+
+    def write_static_routes_interface_file(self, interface_file_path,
+                                           interface, host_routes,
+                                           template_routes, gateway, vip):
+        # write static routes interface file
+
+        mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
+
+        # TODO(johnsom): We need a way to clean out old interfaces records
+        if CONF.amphora_agent.agent_server_network_file:
+            flags = os.O_WRONLY | os.O_CREAT | os.O_APPEND
+        else:
+            flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
+
+        with os.fdopen(os.open(interface_file_path, flags, mode),
+                       'w') as text_file:
+            text = template_routes.render(
+                interface=interface,
+                host_routes=host_routes,
+                gateway=gateway,
+                vip=vip,
+            )
+            text_file.write(text)
+
+    def write_port_interface_file(self, netns_interface, fixed_ips, mtu,
+                                  interface_file_path=None,
+                                  template_port=None):
+        if not interface_file_path:
+            interface_file_path = self.get_network_interface_file(
+                netns_interface)
+        if not template_port:
+            template_port = j2_env.get_template(self.ETH_X_PORT_CONF)
+        super(SUSE, self).write_port_interface_file(
+            netns_interface, fixed_ips, mtu, interface_file_path,
+            template_port)
+
+    def _bring_if_up(self, interface, what, flush=True):
+        # Note, we are not using pyroute2 for this as it is not /etc/netns
+        # aware.
+        os.chdir(self.get_network_path())
+        addr_flush = "ip netns exec {ns} ip addr flush {int}".format(
+            ns=consts.AMPHORA_NAMESPACE, int=interface)
+        cmd = ("ip netns exec {ns} ifup.ns {params}".format(
+            ns=consts.AMPHORA_NAMESPACE, params=interface))
+        try:
+            if flush:
+                subprocess.check_output(addr_flush.split(),
+                                        stderr=subprocess.STDOUT)
+
+            subprocess.check_output(cmd.split(),
+                                    stderr=subprocess.STDOUT)
+
+        except subprocess.CalledProcessError as e:
+            LOG.error('Failed to if up %s due to error: %s', interface, e)
+            raise exceptions.HTTPException(
+                response=webob.Response(json=dict(
+                    message='Error plugging {0}'.format(what),
+                    details=e.output), status=500))
+
+    def _bring_if_down(self, interface):
+        # Note, we are not using pyroute2 for this as it is not /etc/netns
+        # aware.
+        os.chdir(self.get_network_path())
+        cmd = ("ip netns exec {ns} ifdown.ns {params}".format(
+            ns=consts.AMPHORA_NAMESPACE, params=interface))
+        try:
+            subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
+        except subprocess.CalledProcessError:
+            pass
+
+    def bring_interfaces_up(self, ip, primary_interface, secondary_interface):
+        self._bring_if_down(primary_interface)
+        self._bring_if_up(primary_interface, 'VIP')
+        if secondary_interface:
+            LOG.error('Skipping secondary int %s , it is not used for suse',
+                      secondary_interface)
+
+    def has_ifup_all(self):
+        return True
diff --git a/octavia/amphorae/backends/agent/api_server/templates/suse_plug_port_ethX.conf.j2 b/octavia/amphorae/backends/agent/api_server/templates/suse_plug_port_ethX.conf.j2
new file mode 100644
index 00000000..e89617e4
--- /dev/null
+++ b/octavia/amphorae/backends/agent/api_server/templates/suse_plug_port_ethX.conf.j2
@@ -0,0 +1,45 @@
+{#
+# Copyright 2019 SUSE LLC
+#
+# 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.
+#}
+# Generated by Octavia agent
+DEVICE="{{ interface }}"
+ONBOOT="yes"
+STARTMODE="auto"
+TYPE="Ethernet"
+{%- if ipv6 %}
+IPV6INIT="yes"
+{%- if mtu %}
+IPV6_MTU="{{ mtu }}"
+{%- endif %}
+{%- if ip_address %}
+IPV6_AUTOCONF="no"
+IPV6ADDR="{{ ip_address }}"
+{%- else %}
+IPV6_AUTOCONF="yes"
+{%- endif %}
+{%- else %}
+IPV6INIT="no"
+{%- if mtu %}
+MTU="{{ mtu }}"
+{%- endif %}
+{%- if ip_address %}
+BOOTPROTO="static"
+IPADDR="{{ ip_address }}"
+NETMASK="{{ netmask }}"
+{%- else %}
+BOOTPROTO="dhcp"
+{%- endif %}
+{%- endif %}
+
diff --git a/octavia/amphorae/backends/agent/api_server/templates/suse_plug_vip_ethX.conf.j2 b/octavia/amphorae/backends/agent/api_server/templates/suse_plug_vip_ethX.conf.j2
new file mode 100644
index 00000000..e637b18f
--- /dev/null
+++ b/octavia/amphorae/backends/agent/api_server/templates/suse_plug_vip_ethX.conf.j2
@@ -0,0 +1,59 @@
+{#
+# Copyright 2019 SUSE LLC
+#
+# 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.
+#}
+# Generated by Octavia agent
+DEVICE="{{ interface }}"
+ONBOOT="yes"
+TYPE="Ethernet"
+USERCTL="yes"
+STARTMODE="auto"
+LINK_REQUIRED="no"
+{%- if vrrp_ip %}
+{%- if vrrp_ipv6 %}
+IPV6INIT="yes"
+IPV6_DEFROUTE="yes"
+IPV6_AUTOCONF="no"
+IPV6ADDR="{{ vrrp_ip }}/{{ prefix }}"
+{%- if gateway %}
+IPV6_DEFAULTGW="{{ gateway }}"
+{%- endif %}
+{%- if mtu %}
+IPV6_MTU="{{ mtu }}"
+{%- endif %}
+{%- else %} {# not vrrp_ipv6 #}
+BOOTPROTO="static"
+IPADDR="{{ vrrp_ip }}"
+NETMASK="{{ netmask }}"
+{%- if gateway %}
+GATEWAY="{{ gateway }}"
+{%- endif %}
+MTU="{{ mtu }}"
+LABEL_0="0"
+IPADDR_0="{{ vip }}"
+NETMASK_0="{{ netmask }}"
+{%- endif %} {# end if vrrp_ipv6 #}
+{%- else %} {# not vrrp_ip #}
+{%- if vip_ipv6 %}
+IPV6INIT="yes"
+IPV6_DEFROUTE="yes"
+IPV6_AUTOCONF="yes"
+{%- else %}
+BOOTPROTO="dhcp"
+{%- endif %} {# end if vip_ipv6 #}
+{%- endif %} {# end if vrrp_ip #}
+
+{%- if vip_ipv6 %}
+IPV6ADDR_SECONDARIES="{{ vip }}/{{ prefix }}"
+{%- endif %}
diff --git a/octavia/amphorae/backends/agent/api_server/templates/suse_route_ethX.conf.j2 b/octavia/amphorae/backends/agent/api_server/templates/suse_route_ethX.conf.j2
new file mode 100644
index 00000000..b672ebcd
--- /dev/null
+++ b/octavia/amphorae/backends/agent/api_server/templates/suse_route_ethX.conf.j2
@@ -0,0 +1,23 @@
+{#
+# Copyright 2019 SUSE LLC
+#
+# 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.
+#}
+# Generated by Octavia agent
+{%- for hr in host_routes %}
+{{ hr.network }} {{ hr.gw }} {{ hr.netmask}} {{ interface }}
+{%- endfor %}
+# Add a source routing table to allow members to access the VIP
+{%- if gateway %}
+default  {{ gateway }} - -
+{%- endif %}
diff --git a/octavia/common/constants.py b/octavia/common/constants.py
index d182f86c..c8452cf6 100644
--- a/octavia/common/constants.py
+++ b/octavia/common/constants.py
@@ -507,6 +507,7 @@ TESTING = 'testing'
 # Amphora distro-specific data
 UBUNTU_AMP_NET_DIR_TEMPLATE = '/etc/netns/{netns}/network/interfaces.d/'
 RH_AMP_NET_DIR_TEMPLATE = '/etc/netns/{netns}/sysconfig/network-scripts/'
+SUSE_AMP_NET_DIR_TEMPLATE = '/etc/netns/{netns}/sysconfig/network/'
 UBUNTU = 'ubuntu'
 CENTOS = 'centos'
 
diff --git a/octavia/tests/unit/amphorae/backends/agent/api_server/test_osutils.py b/octavia/tests/unit/amphorae/backends/agent/api_server/test_osutils.py
index 1a8409b3..5e24567a 100644
--- a/octavia/tests/unit/amphorae/backends/agent/api_server/test_osutils.py
+++ b/octavia/tests/unit/amphorae/backends/agent/api_server/test_osutils.py
@@ -47,6 +47,10 @@ class TestOSUtils(base.TestCase):
                         return_value='centos'):
             self.centos_os_util = osutils.BaseOS.get_os_util()
 
+        with mock.patch('distro.id',
+                        return_value='sles'):
+            self.suse_os_util = osutils.BaseOS.get_os_util()
+
     def test_get_os_util(self):
         with mock.patch('distro.id',
                         return_value='ubuntu'):
@@ -64,6 +68,14 @@ class TestOSUtils(base.TestCase):
                         return_value='centos'):
             returned_cls = osutils.BaseOS.get_os_util()
             self.assertIsInstance(returned_cls, osutils.CentOS)
+        with mock.patch('distro.id',
+                        return_value='opensuse'):
+            returned_cls = osutils.BaseOS.get_os_util()
+            self.assertIsInstance(returned_cls, osutils.SUSE)
+        with mock.patch('distro.id',
+                        return_value='sles'):
+            returned_cls = osutils.BaseOS.get_os_util()
+            self.assertIsInstance(returned_cls, osutils.SUSE)
         with mock.patch('distro.id',
                         return_value='FakeOS'):
             self.assertRaises(
@@ -101,6 +113,23 @@ class TestOSUtils(base.TestCase):
                 netns=consts.AMPHORA_NAMESPACE),
             ubuntu_interface_name)
 
+        suse_ifroute_interface = 'ifroute-foo'
+        suse_ifcfg_ifroute_interface = 'ifroute-foo'
+        suse_fake_nic_path = os.path.join(
+            fake_agent_server_network_dir,
+            'ifcfg-' + consts.NETNS_PRIMARY_INTERFACE)
+        suse_fake_ifroute_nic_path = os.path.join(
+            fake_agent_server_network_dir,
+            suse_ifcfg_ifroute_interface)
+        suse_nic_path = os.path.join(
+            consts.SUSE_AMP_NET_DIR_TEMPLATE.format(
+                netns=consts.AMPHORA_NAMESPACE),
+            'ifcfg-' + consts.NETNS_PRIMARY_INTERFACE)
+        suse_ifroute_nic_path = os.path.join(
+            consts.SUSE_AMP_NET_DIR_TEMPLATE.format(
+                netns=consts.AMPHORA_NAMESPACE),
+            suse_ifcfg_ifroute_interface)
+
         # Check that agent_server_network_file is returned, when provided
         conf.config(group="amphora_agent",
                     agent_server_network_file=fake_agent_server_network_file)
@@ -120,6 +149,19 @@ class TestOSUtils(base.TestCase):
             get_network_interface_file(consts.NETNS_PRIMARY_INTERFACE))
         self.assertEqual(fake_agent_server_network_file, ubuntu_interface_file)
 
+        # NOTE(gyee): for SUSE, CONF.amphora_agent.agent_server_network_file
+        # will be ignored as there's no single network file in SUSE. Instead,
+        # we should be using agent_server_network_dir.
+        suse_interface_file = (
+            self.suse_os_util.
+            get_network_interface_file(consts.NETNS_PRIMARY_INTERFACE))
+        self.assertEqual(suse_nic_path, suse_interface_file)
+
+        suse_ifroute_interface_file = (
+            self.suse_os_util.
+            get_network_interface_file(suse_ifroute_interface))
+        self.assertEqual(suse_ifroute_nic_path, suse_ifroute_interface_file)
+
         # Check that agent_server_network_dir is used, when provided
         conf.config(group="amphora_agent", agent_server_network_file=None)
         conf.config(group="amphora_agent",
@@ -140,6 +182,19 @@ class TestOSUtils(base.TestCase):
             get_network_interface_file(consts.NETNS_PRIMARY_INTERFACE))
         self.assertEqual(ubuntu_fake_nic_path, ubuntu_interface_file)
 
+        # FIXME(gyee): we may want to refactor these tests into
+        # perhaps one class per platform?
+        suse_interface_file = (
+            self.suse_os_util.
+            get_network_interface_file(consts.NETNS_PRIMARY_INTERFACE))
+        self.assertEqual(suse_fake_nic_path, suse_interface_file)
+
+        suse_ifroute_interface_file = (
+            self.suse_os_util.
+            get_network_interface_file(suse_ifroute_interface))
+        self.assertEqual(suse_fake_ifroute_nic_path,
+                         suse_ifroute_interface_file)
+
         # Check When neither agent_server_network_dir or
         # agent_server_network_file where provided.
         conf.config(group="amphora_agent", agent_server_network_file=None)
@@ -160,12 +215,127 @@ class TestOSUtils(base.TestCase):
             get_network_interface_file(consts.NETNS_PRIMARY_INTERFACE))
         self.assertEqual(ubuntu_real_nic_path, ubuntu_interface_file)
 
+        suse_interface_file = (
+            self.suse_os_util.
+            get_network_interface_file(consts.NETNS_PRIMARY_INTERFACE))
+        self.assertEqual(suse_nic_path, suse_interface_file)
+
+    def _test_RH_get_static_routes_interface_file(self, version):
+        conf = self.useFixture(oslo_fixture.Config(config.cfg.CONF))
+
+        fake_agent_server_network_dir = "/path/to/interface"
+        fake_agent_server_network_file = "/path/to/interfaces_file"
+
+        route = 'route6' if version == 6 else 'route'
+        rh_route_name = '{route}-{nic}'.format(
+            route=route, nic=consts.NETNS_PRIMARY_INTERFACE)
+        rh_fake_route_path = os.path.join(fake_agent_server_network_dir,
+                                          rh_route_name)
+        rh_real_route_path = os.path.join(
+            consts.RH_AMP_NET_DIR_TEMPLATE.format(
+                netns=consts.AMPHORA_NAMESPACE),
+            rh_route_name)
+
+        # Check that agent_server_network_file is returned, when provided
+        conf.config(group="amphora_agent",
+                    agent_server_network_file=fake_agent_server_network_file)
+
+        rh_route_file = (
+            self.rh_os_util.
+            get_static_routes_interface_file(consts.NETNS_PRIMARY_INTERFACE,
+                                             version))
+        self.assertEqual(fake_agent_server_network_file, rh_route_file)
+
+        # Check that agent_server_network_dir is used, when provided
+        conf.config(group="amphora_agent", agent_server_network_file=None)
+        conf.config(group="amphora_agent",
+                    agent_server_network_dir=fake_agent_server_network_dir)
+
+        rh_route_file = (
+            self.rh_os_util.
+            get_static_routes_interface_file(consts.NETNS_PRIMARY_INTERFACE,
+                                             version))
+        self.assertEqual(rh_fake_route_path, rh_route_file)
+
+        # Check When neither agent_server_network_dir or
+        # agent_server_network_file where provided.
+        conf.config(group="amphora_agent", agent_server_network_file=None)
+        conf.config(group="amphora_agent", agent_server_network_dir=None)
+
+        rh_route_file = (
+            self.rh_os_util.
+            get_static_routes_interface_file(consts.NETNS_PRIMARY_INTERFACE,
+                                             version))
+        self.assertEqual(rh_real_route_path, rh_route_file)
+
+    def test_RH_get_static_routes_interface_file(self):
+        self._test_RH_get_static_routes_interface_file(4)
+
+    def test_RH_get_static_routes_interface_file_ipv6(self):
+        self._test_RH_get_static_routes_interface_file(6)
+
+    def _test_RH_get_route_rules_interface_file(self, version):
+        conf = self.useFixture(oslo_fixture.Config(config.cfg.CONF))
+
+        fake_agent_server_network_dir = "/path/to/interface"
+        fake_agent_server_network_file = "/path/to/interfaces_file"
+
+        rule = 'rule6' if version == 6 else 'rule'
+        rh_route_rules_name = '{rule}-{nic}'.format(
+            rule=rule, nic=consts.NETNS_PRIMARY_INTERFACE)
+        rh_fake_route_rules_path = os.path.join(fake_agent_server_network_dir,
+                                                rh_route_rules_name)
+        rh_real_route_rules_path = os.path.join(
+            consts.RH_AMP_NET_DIR_TEMPLATE.format(
+                netns=consts.AMPHORA_NAMESPACE),
+            rh_route_rules_name)
+
+        # Check that agent_server_network_file is returned, when provided
+        conf.config(group="amphora_agent",
+                    agent_server_network_file=fake_agent_server_network_file)
+
+        rh_route_rules_file = (
+            self.rh_os_util.
+            get_route_rules_interface_file(consts.NETNS_PRIMARY_INTERFACE,
+                                           version))
+        self.assertEqual(fake_agent_server_network_file, rh_route_rules_file)
+
+        # Check that agent_server_network_dir is used, when provided
+        conf.config(group="amphora_agent", agent_server_network_file=None)
+        conf.config(group="amphora_agent",
+                    agent_server_network_dir=fake_agent_server_network_dir)
+
+        rh_route_rules_file = (
+            self.rh_os_util.
+            get_route_rules_interface_file(consts.NETNS_PRIMARY_INTERFACE,
+                                           version))
+        self.assertEqual(rh_fake_route_rules_path, rh_route_rules_file)
+
+        # Check When neither agent_server_network_dir or
+        # agent_server_network_file where provided.
+        conf.config(group="amphora_agent", agent_server_network_file=None)
+        conf.config(group="amphora_agent", agent_server_network_dir=None)
+
+        rh_route_rules_file = (
+            self.rh_os_util.
+            get_route_rules_interface_file(consts.NETNS_PRIMARY_INTERFACE,
+                                           version))
+        self.assertEqual(rh_real_route_rules_path, rh_route_rules_file)
+
+    def test_RH_get_route_rules_interface_file(self):
+        self._test_RH_get_route_rules_interface_file(4)
+
+    def test_RH_get_route_rules_interface_file_ipv6(self):
+        self._test_RH_get_route_rules_interface_file(6)
+
     def test_cmd_get_version_of_installed_package(self):
         package_name = 'foo'
         ubuntu_cmd = "dpkg-query -W -f=${{Version}} {name}".format(
             name=package_name)
         rh_cmd = "rpm -q --queryformat %{{VERSION}} {name}".format(
             name=package_name)
+        suse_cmd = "rpm -q --queryformat %{{VERSION}} {name}".format(
+            name=package_name)
 
         returned_ubuntu_cmd = (
             self.ubuntu_os_util.cmd_get_version_of_installed_package(
@@ -176,6 +346,11 @@ class TestOSUtils(base.TestCase):
                            cmd_get_version_of_installed_package(package_name))
         self.assertEqual(rh_cmd, returned_rh_cmd)
 
+        returned_suse_cmd = (
+            self.suse_os_util.
+            cmd_get_version_of_installed_package(package_name))
+        self.assertEqual(suse_cmd, returned_suse_cmd)
+
     def test_cmd_get_version_of_installed_package_mapped(self):
         package_name = 'haproxy'
         centos_cmd = "rpm -q --queryformat %{VERSION} haproxy18"
-- 
2.26.1

openSUSE Build Service is sponsored by