|
|
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 |
|