From: Stefan Raspl <raspl@linux.vnet.ibm.com>
To: kvm@vger.kernel.org
Cc: pbonzini@redhat.com, rkrcmar@redhat.com, frankja@linux.vnet.ibm.com
Subject: [PATCH 14/17] tools/kvm_stat: add option '--guest'
Date: Mon, 20 Feb 2017 16:42:08 +0100 [thread overview]
Message-ID: <20170220154211.11882-15-raspl@linux.vnet.ibm.com> (raw)
In-Reply-To: <20170220154211.11882-1-raspl@linux.vnet.ibm.com>
Add a new option '-g'/'--guest' to select a particular process by providing
the QEMU guest name.
Notes:
- The logic to figure out the pid corresponding to the guest name might look
scary, but works pretty reliably in practice; in the unlikely event that it
returns add'l flukes, it will bail out and hint at using '-p' instead, no
harm done.
- Mixing '-g' and '-p' is possible, and the final instance specified on the
command line is the significant one. This is consistent with current
behavior for '-p' which, if specified multiple times, also regards the final
instance as the significant one.
Signed-off-by: Stefan Raspl <raspl@linux.vnet.ibm.com>
---
tools/kvm/kvm_stat/kvm_stat | 101 +++++++++++++++++++++++++++++++++++++++-
tools/kvm/kvm_stat/kvm_stat.txt | 6 +++
2 files changed, 105 insertions(+), 2 deletions(-)
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat
index 17d2eff..ec77aac 100755
--- a/tools/kvm/kvm_stat/kvm_stat
+++ b/tools/kvm/kvm_stat/kvm_stat
@@ -30,6 +30,7 @@ import fcntl
import resource
import struct
import re
+import subprocess
from collections import defaultdict
VMX_EXIT_REASONS = {
@@ -320,6 +321,30 @@ def parse_int_list(list_string):
return integers
+def get_pid_from_gname(gname):
+ """Fuzzy function to convert guest name to QEMU process pid.
+
+ Returns a list of potential pids, can be empty if no match found.
+ Throws an exception on processing errors.
+
+ """
+ pids = []
+ try:
+ child = subprocess.Popen(['ps', '-A', '--format', 'pid,args'],
+ stdout=subprocess.PIPE)
+ except:
+ raise Exception
+ for line in child.stdout:
+ line = line.lstrip().split(' ', 1)
+ # perform a sanity check before calling the more expensive
+ # function to possibly extract the guest name
+ if ' -name ' in line[1] and gname == get_gname_from_pid(line[0]):
+ pids.append(int(line[0]))
+ child.stdout.close()
+
+ return pids
+
+
def get_gname_from_pid(pid):
"""Returns the guest name for a QEMU process pid.
@@ -976,7 +1001,7 @@ class Tui(object):
except re.error:
continue
- def show_vm_selection(self):
+ def show_vm_selection_by_pid(self):
"""Draws PID selection mask.
Asks for a pid until a valid pid or 0 has been entered.
@@ -1015,6 +1040,50 @@ class Tui(object):
msg = '"' + str(pid) + '": Not a valid pid'
continue
+ def show_vm_selection_by_guest_name(self):
+ """Draws guest selection mask.
+
+ Asks for a guest name until a valid guest name or '' is entered.
+
+ """
+ msg = ''
+ while True:
+ self.screen.erase()
+ self.screen.addstr(0, 0,
+ 'Show statistics for specific guest.',
+ curses.A_BOLD)
+ self.screen.addstr(1, 0,
+ 'This might limit the shown data to the trace '
+ 'statistics.')
+ self.screen.addstr(5, 0, msg)
+ curses.echo()
+ self.screen.addstr(3, 0, "Guest [ENTER or guest]: ")
+ gname = self.screen.getstr()
+ curses.noecho()
+
+ if not gname:
+ self.refresh_header(0)
+ self.update_pid(0)
+ break
+ else:
+ pids = []
+ try:
+ pids = get_pid_from_gname(gname)
+ except:
+ msg = '"' + gname + '": Internal error while searching, ' \
+ 'use pid filter instead'
+ continue
+ if len(pids) == 0:
+ msg = '"' + gname + '": Not an active guest'
+ continue
+ if len(pids) > 1:
+ msg = '"' + gname + '": Multiple matches found, use pid ' \
+ 'filter instead'
+ continue
+ self.refresh_header(pids[0])
+ self.update_pid(pids[0])
+ break
+
def show_stats(self):
"""Refreshes the screen and processes user input."""
sleeptime = DELAY_INITIAL
@@ -1034,8 +1103,11 @@ class Tui(object):
if char == 'f':
self.show_filter_selection()
sleeptime = DELAY_INITIAL
+ if char == 'g':
+ self.show_vm_selection_by_guest_name()
+ sleeptime = DELAY_INITIAL
if char == 'p':
- self.show_vm_selection()
+ self.show_vm_selection_by_pid()
sleeptime = DELAY_INITIAL
except KeyboardInterrupt:
break
@@ -1105,6 +1177,7 @@ Requirements:
Interactive Commands:
f filter by regular expression
+ g filter by guest name
p filter by PID
q quit
x toggle reporting of stats for individual child trace events
@@ -1118,6 +1191,22 @@ Press any other key to refresh statistics immediately.
else:
return ""
+ def cb_guest_to_pid(option, opt, val, parser):
+ try:
+ pids = get_pid_from_gname(val)
+ except:
+ raise optparse.OptionValueError('Error while searching for guest '
+ '"{}", use "-p" to specify a pid '
+ 'instead'.format(val))
+ if len(pids) == 0:
+ raise optparse.OptionValueError('No guest by the name "{}" '
+ 'found'.format(val))
+ if len(pids) > 1:
+ raise optparse.OptionValueError('Multiple processes found (pids: '
+ '{}) - use "-p" to specify a pid '
+ 'instead'.format(" ".join(pids)))
+ parser.values.pid = pids[0]
+
optparser = optparse.OptionParser(description=description_text,
formatter=PlainHelpFormatter())
optparser.add_option('-1', '--once', '--batch',
@@ -1157,6 +1246,14 @@ Press any other key to refresh statistics immediately.
dest='pid',
help='restrict statistics to pid',
)
+ optparser.add_option('-g', '--guest',
+ action='callback',
+ type='string',
+ dest='pid',
+ metavar='GUEST',
+ help='restrict statistics to guest by name',
+ callback=cb_guest_to_pid,
+ )
(options, _) = optparser.parse_args(sys.argv)
return options
diff --git a/tools/kvm/kvm_stat/kvm_stat.txt b/tools/kvm/kvm_stat/kvm_stat.txt
index 077bcc7..35587c3 100644
--- a/tools/kvm/kvm_stat/kvm_stat.txt
+++ b/tools/kvm/kvm_stat/kvm_stat.txt
@@ -31,6 +31,8 @@ INTERACTIVE COMMANDS
[horizontal]
*f*:: filter by regular expression
+*g*:: filter by guest name
+
*p*:: filter by PID
*q*:: quit
@@ -62,6 +64,10 @@ OPTIONS
--pid=<pid>::
limit statistics to one virtual machine (pid)
+-g<guest>::
+--guest=<guest_name>::
+ limit statistics to one virtual machine (guest name)
+
-f<fields>::
--fields=<fields>::
fields to display (regex)
--
2.8.4
next prev parent reply other threads:[~2017-02-20 15:42 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-20 15:41 [PATCH 00/17] tools/kvm_stat: Misc Patches Stefan Raspl
2017-02-20 15:41 ` [PATCH 01/17] tools/kvm_stat: hide cursor Stefan Raspl
2017-02-20 15:41 ` [PATCH 02/17] tools/kvm_stat: catch curses exceptions only Stefan Raspl
2017-02-20 15:41 ` [PATCH 03/17] tools/kvm_stat: handle SIGINT in log and batch modes Stefan Raspl
2017-02-20 15:41 ` [PATCH 04/17] tools/kvm_stat: fix misc glitches Stefan Raspl
2017-03-09 16:51 ` Paolo Bonzini
2017-03-10 6:04 ` Stefan Raspl
2017-03-10 8:14 ` Paolo Bonzini
2017-03-10 8:33 ` Stefan Raspl
2017-03-10 8:38 ` Paolo Bonzini
2017-03-10 9:42 ` Stefan Raspl
2017-03-10 10:05 ` Paolo Bonzini
2017-02-20 15:41 ` [PATCH 05/17] tools/kvm_stat: fix trace setup glitch on field updates in TracepointProvider Stefan Raspl
2017-02-20 15:42 ` [PATCH 06/17] tools/kvm_stat: full PEP8 compliance Stefan Raspl
2017-02-20 15:42 ` [PATCH 07/17] tools/kvm_stat: reduce perceived idle time on filter updates Stefan Raspl
2017-03-09 16:54 ` Paolo Bonzini
2017-02-20 15:42 ` [PATCH 08/17] tools/kvm_stat: document list of interactive commands Stefan Raspl
2017-02-20 15:42 ` [PATCH 09/17] tools/kvm_stat: display guest name when using pid filter Stefan Raspl
2017-03-09 16:54 ` Paolo Bonzini
2017-03-10 6:08 ` Stefan Raspl
2017-02-20 15:42 ` [PATCH 10/17] tools/kvm_stat: remove pid filter on empty input Stefan Raspl
2017-02-20 15:42 ` [PATCH 11/17] tools/kvm_stat: print error messages on faulty pid filter input Stefan Raspl
2017-02-20 15:42 ` [PATCH 12/17] tools/kvm_stat: display regex when set to non-default Stefan Raspl
2017-02-20 15:42 ` [PATCH 13/17] tools/kvm_stat: remove regex filter on empty input Stefan Raspl
2017-02-20 15:42 ` Stefan Raspl [this message]
2017-03-10 11:52 ` [PATCH 14/17] tools/kvm_stat: add option '--guest' Janosch Frank
2017-02-20 15:42 ` [PATCH 15/17] tools/kvm_stat: add interactive command 'c' Stefan Raspl
2017-02-20 15:42 ` [PATCH 16/17] tools/kvm_stat: add interactive command 'r' Stefan Raspl
2017-03-10 11:37 ` Janosch Frank
2017-03-10 12:32 ` Stefan Raspl
2017-02-20 15:42 ` [PATCH 17/17] tools/kvm_stat: add '%Total' column Stefan Raspl
2017-03-06 8:08 ` [PATCH 00/17] tools/kvm_stat: Misc Patches Stefan Raspl
2017-03-06 16:05 ` Paolo Bonzini
2017-03-09 17:00 ` Paolo Bonzini
2017-03-10 6:13 ` Stefan Raspl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170220154211.11882-15-raspl@linux.vnet.ibm.com \
--to=raspl@linux.vnet.ibm.com \
--cc=frankja@linux.vnet.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=rkrcmar@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.