diff options
author | Stefan Raspl <stefan.raspl@de.ibm.com> | 2018-02-22 06:16:27 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2018-02-23 19:43:44 -0500 |
commit | 516f1190a1e0cce12128a6446e6438745c8de62a (patch) | |
tree | 68b797dd40e3bd6e10191e14aef5fd826f20e9bc /tools | |
parent | c0e8c21eae616ed8703c1b4b01046a1578ee875c (diff) |
tools/kvm_stat: eliminate extra guest/pid selection dialog
We can do with a single dialog that takes both, pids and guest names.
Note that we keep both interactive commands, 'p' and 'g' for now, to
avoid confusion among users used to a specific key.
While at it, we improve on some minor glitches regarding curses usage,
e.g. cursor still visible when not supposed to be.
Signed-off-by: Stefan Raspl <raspl@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/kvm/kvm_stat/kvm_stat | 110 | ||||
-rw-r--r-- | tools/kvm/kvm_stat/kvm_stat.txt | 4 |
2 files changed, 39 insertions, 75 deletions
diff --git a/tools/kvm/kvm_stat/kvm_stat b/tools/kvm/kvm_stat/kvm_stat index c09b7428f563..0d5776785d27 100755 --- a/tools/kvm/kvm_stat/kvm_stat +++ b/tools/kvm/kvm_stat/kvm_stat | |||
@@ -1041,6 +1041,8 @@ class Tui(object): | |||
1041 | 1041 | ||
1042 | def _update_pid(self, pid): | 1042 | def _update_pid(self, pid): |
1043 | """Propagates pid selection to stats object.""" | 1043 | """Propagates pid selection to stats object.""" |
1044 | self.screen.addstr(4, 1, 'Updating pid filter...') | ||
1045 | self.screen.refresh() | ||
1044 | self.stats.pid_filter = pid | 1046 | self.stats.pid_filter = pid |
1045 | 1047 | ||
1046 | def _refresh_header(self, pid=None): | 1048 | def _refresh_header(self, pid=None): |
@@ -1144,10 +1146,10 @@ class Tui(object): | |||
1144 | ' filters)', | 1146 | ' filters)', |
1145 | ' c clear filter', | 1147 | ' c clear filter', |
1146 | ' f filter by regular expression', | 1148 | ' f filter by regular expression', |
1147 | ' g filter by guest name', | 1149 | ' g filter by guest name/PID', |
1148 | ' h display interactive commands reference', | 1150 | ' h display interactive commands reference', |
1149 | ' o toggle sorting order (Total vs CurAvg/s)', | 1151 | ' o toggle sorting order (Total vs CurAvg/s)', |
1150 | ' p filter by PID', | 1152 | ' p filter by guest name/PID', |
1151 | ' q quit', | 1153 | ' q quit', |
1152 | ' r reset stats', | 1154 | ' r reset stats', |
1153 | ' s set update interval', | 1155 | ' s set update interval', |
@@ -1199,44 +1201,6 @@ class Tui(object): | |||
1199 | msg = '"' + regex + '": Not a valid regular expression' | 1201 | msg = '"' + regex + '": Not a valid regular expression' |
1200 | continue | 1202 | continue |
1201 | 1203 | ||
1202 | def _show_vm_selection_by_pid(self): | ||
1203 | """Draws PID selection mask. | ||
1204 | |||
1205 | Asks for a pid until a valid pid or 0 has been entered. | ||
1206 | |||
1207 | """ | ||
1208 | msg = '' | ||
1209 | while True: | ||
1210 | self.screen.erase() | ||
1211 | self.screen.addstr(0, 0, | ||
1212 | 'Show statistics for specific pid.', | ||
1213 | curses.A_BOLD) | ||
1214 | self.screen.addstr(1, 0, | ||
1215 | 'This might limit the shown data to the trace ' | ||
1216 | 'statistics.') | ||
1217 | self.screen.addstr(5, 0, msg) | ||
1218 | self._print_all_gnames(7) | ||
1219 | |||
1220 | curses.echo() | ||
1221 | self.screen.addstr(3, 0, "Pid [0 or pid]: ") | ||
1222 | pid = self.screen.getstr().decode(ENCODING) | ||
1223 | curses.noecho() | ||
1224 | |||
1225 | try: | ||
1226 | if len(pid) > 0: | ||
1227 | pid = int(pid) | ||
1228 | if pid != 0 and not os.path.isdir(os.path.join('/proc/', | ||
1229 | str(pid))): | ||
1230 | msg = '"' + str(pid) + '": Not a running process' | ||
1231 | continue | ||
1232 | else: | ||
1233 | pid = 0 | ||
1234 | self._refresh_header(pid) | ||
1235 | self._update_pid(pid) | ||
1236 | break | ||
1237 | except ValueError: | ||
1238 | msg = '"' + str(pid) + '": Not a valid pid' | ||
1239 | |||
1240 | def _show_set_update_interval(self): | 1204 | def _show_set_update_interval(self): |
1241 | """Draws update interval selection mask.""" | 1205 | """Draws update interval selection mask.""" |
1242 | msg = '' | 1206 | msg = '' |
@@ -1269,17 +1233,17 @@ class Tui(object): | |||
1269 | msg = '"' + str(val) + '": Invalid value' | 1233 | msg = '"' + str(val) + '": Invalid value' |
1270 | self._refresh_header() | 1234 | self._refresh_header() |
1271 | 1235 | ||
1272 | def _show_vm_selection_by_guest_name(self): | 1236 | def _show_vm_selection_by_guest(self): |
1273 | """Draws guest selection mask. | 1237 | """Draws guest selection mask. |
1274 | 1238 | ||
1275 | Asks for a guest name until a valid guest name or '' is entered. | 1239 | Asks for a guest name or pid until a valid guest name or '' is entered. |
1276 | 1240 | ||
1277 | """ | 1241 | """ |
1278 | msg = '' | 1242 | msg = '' |
1279 | while True: | 1243 | while True: |
1280 | self.screen.erase() | 1244 | self.screen.erase() |
1281 | self.screen.addstr(0, 0, | 1245 | self.screen.addstr(0, 0, |
1282 | 'Show statistics for specific guest.', | 1246 | 'Show statistics for specific guest or pid.', |
1283 | curses.A_BOLD) | 1247 | curses.A_BOLD) |
1284 | self.screen.addstr(1, 0, | 1248 | self.screen.addstr(1, 0, |
1285 | 'This might limit the shown data to the trace ' | 1249 | 'This might limit the shown data to the trace ' |
@@ -1287,32 +1251,39 @@ class Tui(object): | |||
1287 | self.screen.addstr(5, 0, msg) | 1251 | self.screen.addstr(5, 0, msg) |
1288 | self._print_all_gnames(7) | 1252 | self._print_all_gnames(7) |
1289 | curses.echo() | 1253 | curses.echo() |
1290 | self.screen.addstr(3, 0, "Guest [ENTER or guest]: ") | 1254 | curses.curs_set(1) |
1291 | gname = self.screen.getstr().decode(ENCODING) | 1255 | self.screen.addstr(3, 0, "Guest or pid [ENTER exits]: ") |
1256 | guest = self.screen.getstr().decode(ENCODING) | ||
1292 | curses.noecho() | 1257 | curses.noecho() |
1293 | 1258 | ||
1294 | if not gname: | 1259 | pid = 0 |
1295 | self._refresh_header(0) | 1260 | if not guest or guest == '0': |
1296 | self._update_pid(0) | ||
1297 | break | 1261 | break |
1298 | else: | 1262 | if guest.isdigit(): |
1299 | pids = [] | 1263 | if not os.path.isdir(os.path.join('/proc/', guest)): |
1300 | try: | 1264 | msg = '"' + guest + '": Not a running process' |
1301 | pids = self.get_pid_from_gname(gname) | ||
1302 | except: | ||
1303 | msg = '"' + gname + '": Internal error while searching, ' \ | ||
1304 | 'use pid filter instead' | ||
1305 | continue | ||
1306 | if len(pids) == 0: | ||
1307 | msg = '"' + gname + '": Not an active guest' | ||
1308 | continue | 1265 | continue |
1309 | if len(pids) > 1: | 1266 | pid = int(guest) |
1310 | msg = '"' + gname + '": Multiple matches found, use pid ' \ | ||
1311 | 'filter instead' | ||
1312 | continue | ||
1313 | self._refresh_header(pids[0]) | ||
1314 | self._update_pid(pids[0]) | ||
1315 | break | 1267 | break |
1268 | pids = [] | ||
1269 | try: | ||
1270 | pids = self.get_pid_from_gname(guest) | ||
1271 | except: | ||
1272 | msg = '"' + guest + '": Internal error while searching, ' \ | ||
1273 | 'use pid filter instead' | ||
1274 | continue | ||
1275 | if len(pids) == 0: | ||
1276 | msg = '"' + guest + '": Not an active guest' | ||
1277 | continue | ||
1278 | if len(pids) > 1: | ||
1279 | msg = '"' + guest + '": Multiple matches found, use pid ' \ | ||
1280 | 'filter instead' | ||
1281 | continue | ||
1282 | pid = pids[0] | ||
1283 | break | ||
1284 | curses.curs_set(0) | ||
1285 | self._refresh_header(pid) | ||
1286 | self._update_pid(pid) | ||
1316 | 1287 | ||
1317 | def show_stats(self): | 1288 | def show_stats(self): |
1318 | """Refreshes the screen and processes user input.""" | 1289 | """Refreshes the screen and processes user input.""" |
@@ -1344,20 +1315,13 @@ class Tui(object): | |||
1344 | self._show_filter_selection() | 1315 | self._show_filter_selection() |
1345 | curses.curs_set(0) | 1316 | curses.curs_set(0) |
1346 | sleeptime = self._delay_initial | 1317 | sleeptime = self._delay_initial |
1347 | if char == 'g': | 1318 | if char == 'g' or char == 'p': |
1348 | curses.curs_set(1) | 1319 | self._show_vm_selection_by_guest() |
1349 | self._show_vm_selection_by_guest_name() | ||
1350 | curses.curs_set(0) | ||
1351 | sleeptime = self._delay_initial | 1320 | sleeptime = self._delay_initial |
1352 | if char == 'h': | 1321 | if char == 'h': |
1353 | self._show_help_interactive() | 1322 | self._show_help_interactive() |
1354 | if char == 'o': | 1323 | if char == 'o': |
1355 | self._sorting = not self._sorting | 1324 | self._sorting = not self._sorting |
1356 | if char == 'p': | ||
1357 | curses.curs_set(1) | ||
1358 | self._show_vm_selection_by_pid() | ||
1359 | curses.curs_set(0) | ||
1360 | sleeptime = self._delay_initial | ||
1361 | if char == 'q': | 1325 | if char == 'q': |
1362 | break | 1326 | break |
1363 | if char == 'r': | 1327 | if char == 'r': |
diff --git a/tools/kvm/kvm_stat/kvm_stat.txt b/tools/kvm/kvm_stat/kvm_stat.txt index b5b3810c9e94..0811d860fe75 100644 --- a/tools/kvm/kvm_stat/kvm_stat.txt +++ b/tools/kvm/kvm_stat/kvm_stat.txt | |||
@@ -35,13 +35,13 @@ INTERACTIVE COMMANDS | |||
35 | 35 | ||
36 | *f*:: filter by regular expression | 36 | *f*:: filter by regular expression |
37 | 37 | ||
38 | *g*:: filter by guest name | 38 | *g*:: filter by guest name/PID |
39 | 39 | ||
40 | *h*:: display interactive commands reference | 40 | *h*:: display interactive commands reference |
41 | 41 | ||
42 | *o*:: toggle sorting order (Total vs CurAvg/s) | 42 | *o*:: toggle sorting order (Total vs CurAvg/s) |
43 | 43 | ||
44 | *p*:: filter by PID | 44 | *p*:: filter by guest name/PID |
45 | 45 | ||
46 | *q*:: quit | 46 | *q*:: quit |
47 | 47 | ||