From 17ba1346b7d3cdc6914442465ed172518cb81d30 Mon Sep 17 00:00:00 2001
From: KeithMnemonic <keith.berger@suse.com>
Date: Tue, 7 Apr 2020 15:14:45 -0400
Subject: [PATCH] Do not copy /sbin/ip to /usr/bin/monasa-agent-ip

This patch removes the code that does the copy of /sbin/ip to
/usr/bin/monasca-agent-ip. There is a limitation with /sbin/ip
that limits copying it to a new name that is longer than
2 characters. The error is:

./monasca-agent-ip a
Object "nasca-agent-ip" is unknown, try "ip help".

As this is not working on RHEL,SLES, or Ubuntu this code
should be removed.

Change-Id: I439be00070eb1cf16416325f23a86fc7cd518acc
Story: 2001593
Task: 6543
---
 docs/Libvirt.md                            | 12 ++--
 monasca_setup/detection/plugins/libvirt.py | 74 ++++++----------------
 2 files changed, 28 insertions(+), 58 deletions(-)

diff --git a/docs/Libvirt.md b/docs/Libvirt.md
index 36679d3b..ed3f8ebe 100644
--- a/docs/Libvirt.md
+++ b/docs/Libvirt.md
@@ -336,17 +336,19 @@ It is helpful for determining, for example, if a VM is in a panicked or halted s
 2. Neutron L2 plugin with a tenant network type of `vlan` or `vxlan` (other types may be supported, but have not been tested).
 3. The `python-neutronclient` library and its dependencies installed and available to the Monasca Agent
 4. Each VM needs an appropriate security group configuration to allow ICMP
+5. A sudoers entry for the monasca-agent user needs to be created which allows access to /bin/ip. For example:
+
+Defaults:monasca-agent !requiretty
+Defaults:monasca-agent  secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
+monasca-agent ALL = (root) NOPASSWD:/bin/ip
 
 #### Detection
 The monasca-setup detection plugin for libvirt performs the following tests and tasks before configuring ping checks:
 
 1. Ability to determine the name of the user under which monasca-agent processes run (eg, `mon-agent`)
 2. Availability of the `python-neutronclient` library (by attempting to import `client` from `neutronclient.v2_0`)
-3. A separate enhanced-capabilities `ip` command exists:
-   a. The detection plugin copies `/sbin/ip` to `sys.path[0]/monasca-agent-ip` (see the [configuration](#configuration) section above for an example)
-   b. Permissions on the copy are changed to the `mon-agent` user (or whichever Agent user is configured), mode 0700.
-   c. The `/sbin/setcap` command is called, applying `cap_sys_admin+ep` to the copy, as `cap_sys_admin` is the only capability which provides `setns`, necessary to execute commands in a separate namespace.
-   d. The detection plugin confirms that the enhanced capabilities were successfully applied
+3. Existance of /bin/ip. A separate enhanced-capabilities `ip` command exists:
 4. Existence of a ping command; detection will try `/usr/bin/fping`, `/sbin/fping`, and `/bin/ping` in that order.  `fping` is preferred because it allows for sub-second timeouts, but is not installed by default in some Linux distributions.
 
 If any of the above requirements fail, a WARN-level message is output, describing the problem.  The libvirt plugin will continue to function without these requirements, but ping checks will be disabled.
diff --git a/monasca_setup/detection/plugins/libvirt.py b/monasca_setup/detection/plugins/libvirt.py
index 1d904fb5..c42e6cc6 100644
--- a/monasca_setup/detection/plugins/libvirt.py
+++ b/monasca_setup/detection/plugins/libvirt.py
@@ -16,9 +16,6 @@
 import logging
 import os
 import pwd
-from shutil import copy
-import subprocess
-import sys
 
 from oslo_config import cfg
 from oslo_utils import importutils
@@ -49,7 +46,7 @@ ping_options = [["/usr/bin/fping", "-n", "-c1", "-t250", "-q"],
                 ["/bin/ping", "-n", "-c1", "-w1", "-q"],
                 ["/usr/bin/ping", "-n", "-c1", "-w1", "-q"]]
 # Path to 'ip' command (needed to execute ping within network namespaces)
-ip_cmd = "/sbin/ip"
+ip_cmd = "sudo /bin/ip"
 # How many ping commands to run concurrently
 default_max_ping_concurrency = 8
 # Disk metrics can be collected at a larger interval than other vm metrics
@@ -147,56 +144,27 @@ class Libvirt(plugin.Plugin):
             log.warn("\tUnable to determine agent user. Skipping ping checks.")
             return
 
-        try:
-            client = importutils.try_import('neutronclient.v2_0.client',
-                                            False)
-            if not client:
-                log.warning(
-                    '\tpython-neutronclient module missing, '
-                    'required for ping checks.')
-                return
+        client = importutils.try_import('neutronclient.v2_0.client',
+                                        False)
+        if not client:
+            log.warning(
+                '\tpython-neutronclient module missing, '
+                'required for ping checks.')
+            return
 
-            # TODO(dmllr) Find a better rundir or avoid copying the binary
-            # alltogether. see https://storyboard.openstack.org/#!/story/2001593
-            monasca_rundir = sys.path[0]
-            monasca_ip = "{0}/monasca-agent-ip".format(monasca_rundir)
-            # Copy system 'ip' command to monasca_rundir
-            copy(ip_cmd, monasca_ip)
-
-            # Restrict permissions on the local 'ip' command
-            os.chown(monasca_ip, *self._get_user_uid_gid(self._agent_user))
-            os.chmod(monasca_ip, 0o700)
-
-            # Set capabilities on 'ip' which will allow
-            # self.agent_user to exec commands in namespaces
-            setcap_cmd = ['/sbin/setcap', 'cap_sys_admin+ep',
-                          monasca_ip]
-            subprocess.Popen(setcap_cmd, stdout=subprocess.PIPE,
-                             stderr=subprocess.PIPE)
-            # Verify that the capabilities were set
-            setcap_cmd.extend(['-v', '-q'])
-            subprocess.check_call(setcap_cmd)
-            # Look for the best ping command
-            for ping_cmd in ping_options:
-                if os.path.isfile(ping_cmd[0]):
-                    init_config[
-                        'ping_check'] = "{0} netns exec NAMESPACE {1}".format(
-                            monasca_ip,
-                            ' '.join(ping_cmd))
-                    log.info(
-                        "\tEnabling ping checks using {0}".format(ping_cmd[0]))
-                    break
-            if init_config['ping_check'] is False:
-                log.warn('\tUnable to find suitable ping command, '
-                         'disabling ping checks.')
-        except IOError:
-            log.warn('\tUnable to copy {0}, '
-                     'ping checks disabled.'.format(ip_cmd))
-            pass
-        except (subprocess.CalledProcessError, OSError):
-            log.warn('\tUnable to set up ping checks, '
-                     'setcap failed ({0})'.format(' '.join(setcap_cmd)))
-            pass
+        # Look for the best ping command
+        for ping_cmd in ping_options:
+            if os.path.isfile(ping_cmd[0]):
+                init_config[
+                    'ping_check'] = "{0} netns exec NAMESPACE {1}".format(
+                        ip_cmd,
+                        ' '.join(ping_cmd))
+                log.info(
+                    "\tEnabling ping checks using {0}".format(ping_cmd[0]))
+                break
+        if init_config['ping_check'] is False:
+            log.warn('\tUnable to find suitable ping command, '
+                     'disabling ping checks.')
 
     def dependencies_installed(self):
         return importutils.try_import('novaclient.client', False)