Blame SOURCES/kvm-tools-kvm_stat-add-option-guest.patch

4a2fec
From 8b7b31fc24968fc62be018b9932ea94263e1b586 Mon Sep 17 00:00:00 2001
4a2fec
From: David Hildenbrand <david@redhat.com>
4a2fec
Date: Tue, 17 Oct 2017 19:15:40 +0200
4a2fec
Subject: [PATCH 35/69] tools/kvm_stat: add option '--guest'
4a2fec
MIME-Version: 1.0
4a2fec
Content-Type: text/plain; charset=UTF-8
4a2fec
Content-Transfer-Encoding: 8bit
4a2fec
4a2fec
RH-Author: David Hildenbrand <david@redhat.com>
4a2fec
Message-id: <20171017191605.2378-15-david@redhat.com>
4a2fec
Patchwork-id: 77323
4a2fec
O-Subject: [RHEL-7.5 qemu-kvm-rhev PATCH 14/39] tools/kvm_stat: add option '--guest'
4a2fec
Bugzilla: 1497137
4a2fec
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
4a2fec
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
4a2fec
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
4a2fec
RH-Acked-by: Thomas Huth <thuth@redhat.com>
4a2fec
4a2fec
Upstream-status: linux.git f9ff1087354e5e063b96a291360a8de84bea0bed
4a2fec
4a2fec
Convertion of documentation (for man page generation) to texi.
4a2fec
4a2fec
commit f9ff1087354e5e063b96a291360a8de84bea0bed
4a2fec
Author: Stefan Raspl <raspl@linux.vnet.ibm.com>
4a2fec
Date:   Fri Mar 10 13:40:13 2017 +0100
4a2fec
4a2fec
    tools/kvm_stat: add option '--guest'
4a2fec
4a2fec
    Add a new option '-g'/'--guest' to select a particular process by providing
4a2fec
    the QEMU guest name.
4a2fec
    Notes:
4a2fec
    - The logic to figure out the pid corresponding to the guest name might look
4a2fec
      scary, but works pretty reliably in practice; in the unlikely event that it
4a2fec
      returns add'l flukes, it will bail out and hint at using '-p' instead, no
4a2fec
      harm done.
4a2fec
    - Mixing '-g' and '-p' is possible, and the final instance specified on the
4a2fec
      command line is the significant one. This is consistent with current
4a2fec
      behavior for '-p' which, if specified multiple times, also regards the final
4a2fec
      instance as the significant one.
4a2fec
4a2fec
    Signed-off-by: Stefan Raspl <raspl@linux.vnet.ibm.com>
4a2fec
    Reviewed-by: Janosch Frank <frankja@linux.vnet.ibm.com>
4a2fec
    Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
4a2fec
4a2fec
Signed-off-by: David Hildenbrand <david@redhat.com>
4a2fec
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
---
4a2fec
 scripts/kvm/kvm_stat      | 101 +++++++++++++++++++++++++++++++++++++++++++++-
4a2fec
 scripts/kvm/kvm_stat.texi |   5 +++
4a2fec
 2 files changed, 104 insertions(+), 2 deletions(-)
4a2fec
4a2fec
diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat
4a2fec
index f2a868b..f263312 100755
4a2fec
--- a/scripts/kvm/kvm_stat
4a2fec
+++ b/scripts/kvm/kvm_stat
4a2fec
@@ -30,6 +30,7 @@ import fcntl
4a2fec
 import resource
4a2fec
 import struct
4a2fec
 import re
4a2fec
+import subprocess
4a2fec
 from collections import defaultdict
4a2fec
 
4a2fec
 VMX_EXIT_REASONS = {
4a2fec
@@ -320,6 +321,30 @@ def parse_int_list(list_string):
4a2fec
     return integers
4a2fec
 
4a2fec
 
4a2fec
+def get_pid_from_gname(gname):
4a2fec
+    """Fuzzy function to convert guest name to QEMU process pid.
4a2fec
+
4a2fec
+    Returns a list of potential pids, can be empty if no match found.
4a2fec
+    Throws an exception on processing errors.
4a2fec
+
4a2fec
+    """
4a2fec
+    pids = []
4a2fec
+    try:
4a2fec
+        child = subprocess.Popen(['ps', '-A', '--format', 'pid,args'],
4a2fec
+                                 stdout=subprocess.PIPE)
4a2fec
+    except:
4a2fec
+        raise Exception
4a2fec
+    for line in child.stdout:
4a2fec
+        line = line.lstrip().split(' ', 1)
4a2fec
+        # perform a sanity check before calling the more expensive
4a2fec
+        # function to possibly extract the guest name
4a2fec
+        if ' -name ' in line[1] and gname == get_gname_from_pid(line[0]):
4a2fec
+            pids.append(int(line[0]))
4a2fec
+    child.stdout.close()
4a2fec
+
4a2fec
+    return pids
4a2fec
+
4a2fec
+
4a2fec
 def get_gname_from_pid(pid):
4a2fec
     """Returns the guest name for a QEMU process pid.
4a2fec
 
4a2fec
@@ -977,7 +1002,7 @@ class Tui(object):
4a2fec
             except re.error:
4a2fec
                 continue
4a2fec
 
4a2fec
-    def show_vm_selection(self):
4a2fec
+    def show_vm_selection_by_pid(self):
4a2fec
         """Draws PID selection mask.
4a2fec
 
4a2fec
         Asks for a pid until a valid pid or 0 has been entered.
4a2fec
@@ -1016,6 +1041,50 @@ class Tui(object):
4a2fec
                 msg = '"' + str(pid) + '": Not a valid pid'
4a2fec
                 continue
4a2fec
 
4a2fec
+    def show_vm_selection_by_guest_name(self):
4a2fec
+        """Draws guest selection mask.
4a2fec
+
4a2fec
+        Asks for a guest name until a valid guest name or '' is entered.
4a2fec
+
4a2fec
+        """
4a2fec
+        msg = ''
4a2fec
+        while True:
4a2fec
+            self.screen.erase()
4a2fec
+            self.screen.addstr(0, 0,
4a2fec
+                               'Show statistics for specific guest.',
4a2fec
+                               curses.A_BOLD)
4a2fec
+            self.screen.addstr(1, 0,
4a2fec
+                               'This might limit the shown data to the trace '
4a2fec
+                               'statistics.')
4a2fec
+            self.screen.addstr(5, 0, msg)
4a2fec
+            curses.echo()
4a2fec
+            self.screen.addstr(3, 0, "Guest [ENTER or guest]: ")
4a2fec
+            gname = self.screen.getstr()
4a2fec
+            curses.noecho()
4a2fec
+
4a2fec
+            if not gname:
4a2fec
+                self.refresh_header(0)
4a2fec
+                self.update_pid(0)
4a2fec
+                break
4a2fec
+            else:
4a2fec
+                pids = []
4a2fec
+                try:
4a2fec
+                    pids = get_pid_from_gname(gname)
4a2fec
+                except:
4a2fec
+                    msg = '"' + gname + '": Internal error while searching, ' \
4a2fec
+                          'use pid filter instead'
4a2fec
+                    continue
4a2fec
+                if len(pids) == 0:
4a2fec
+                    msg = '"' + gname + '": Not an active guest'
4a2fec
+                    continue
4a2fec
+                if len(pids) > 1:
4a2fec
+                    msg = '"' + gname + '": Multiple matches found, use pid ' \
4a2fec
+                          'filter instead'
4a2fec
+                    continue
4a2fec
+                self.refresh_header(pids[0])
4a2fec
+                self.update_pid(pids[0])
4a2fec
+                break
4a2fec
+
4a2fec
     def show_stats(self):
4a2fec
         """Refreshes the screen and processes user input."""
4a2fec
         sleeptime = DELAY_INITIAL
4a2fec
@@ -1035,8 +1104,11 @@ class Tui(object):
4a2fec
                 if char == 'f':
4a2fec
                     self.show_filter_selection()
4a2fec
                     sleeptime = DELAY_INITIAL
4a2fec
+                if char == 'g':
4a2fec
+                    self.show_vm_selection_by_guest_name()
4a2fec
+                    sleeptime = DELAY_INITIAL
4a2fec
                 if char == 'p':
4a2fec
-                    self.show_vm_selection()
4a2fec
+                    self.show_vm_selection_by_pid()
4a2fec
                     sleeptime = DELAY_INITIAL
4a2fec
             except KeyboardInterrupt:
4a2fec
                 break
4a2fec
@@ -1106,6 +1178,7 @@ Requirements:
4a2fec
 
4a2fec
 Interactive Commands:
4a2fec
    f     filter by regular expression
4a2fec
+   g     filter by guest name
4a2fec
    p     filter by PID
4a2fec
    q     quit
4a2fec
    x     toggle reporting of stats for individual child trace events
4a2fec
@@ -1119,6 +1192,22 @@ Press any other key to refresh statistics immediately.
4a2fec
             else:
4a2fec
                 return ""
4a2fec
 
4a2fec
+    def cb_guest_to_pid(option, opt, val, parser):
4a2fec
+        try:
4a2fec
+            pids = get_pid_from_gname(val)
4a2fec
+        except:
4a2fec
+            raise optparse.OptionValueError('Error while searching for guest '
4a2fec
+                                            '"{}", use "-p" to specify a pid '
4a2fec
+                                            'instead'.format(val))
4a2fec
+        if len(pids) == 0:
4a2fec
+            raise optparse.OptionValueError('No guest by the name "{}" '
4a2fec
+                                            'found'.format(val))
4a2fec
+        if len(pids) > 1:
4a2fec
+            raise optparse.OptionValueError('Multiple processes found (pids: '
4a2fec
+                                            '{}) - use "-p" to specify a pid '
4a2fec
+                                            'instead'.format(" ".join(pids)))
4a2fec
+        parser.values.pid = pids[0]
4a2fec
+
4a2fec
     optparser = optparse.OptionParser(description=description_text,
4a2fec
                                       formatter=PlainHelpFormatter())
4a2fec
     optparser.add_option('-1', '--once', '--batch',
4a2fec
@@ -1158,6 +1247,14 @@ Press any other key to refresh statistics immediately.
4a2fec
                          dest='pid',
4a2fec
                          help='restrict statistics to pid',
4a2fec
                          )
4a2fec
+    optparser.add_option('-g', '--guest',
4a2fec
+                         action='callback',
4a2fec
+                         type='string',
4a2fec
+                         dest='pid',
4a2fec
+                         metavar='GUEST',
4a2fec
+                         help='restrict statistics to guest by name',
4a2fec
+                         callback=cb_guest_to_pid,
4a2fec
+                         )
4a2fec
     (options, _) = optparser.parse_args(sys.argv)
4a2fec
     return options
4a2fec
 
4a2fec
diff --git a/scripts/kvm/kvm_stat.texi b/scripts/kvm/kvm_stat.texi
4a2fec
index 3519cf9..a8c1071 100644
4a2fec
--- a/scripts/kvm/kvm_stat.texi
4a2fec
+++ b/scripts/kvm/kvm_stat.texi
4a2fec
@@ -27,6 +27,9 @@ While running in regular (interactive) mode, use any of the following keys:
4a2fec
 @item f
4a2fec
 @kindex f
4a2fec
 filter by regular expression
4a2fec
+@item g
4a2fec
+@kindex g
4a2fec
+filter by guest name
4a2fec
 @item p
4a2fec
 @kindex p
4a2fec
 filter by PID
4a2fec
@@ -55,6 +58,8 @@ Press any other key to refresh statistics immediately.
4a2fec
   retrieve statistics from debugfs
4a2fec
 @item -p, --pid=@var{pid}
4a2fec
   limit statistics to one virtual machine (pid)
4a2fec
+@item -g, --guest=@var{guest_name}
4a2fec
+  limit statistics to one virtual machine (guest name)
4a2fec
 @item -f, --fields=@var{fields}
4a2fec
   fields to display (regex)
4a2fec
 @item -h, --help
4a2fec
-- 
4a2fec
1.8.3.1
4a2fec