Hi, 

I've added the 'vmctl status' view to systat(1).  I am not sure if this
is of general interest.  

Any opinions about it?  

Index: usr.bin/systat/Makefile
===================================================================
RCS file: /cvs/src/usr.bin/systat/Makefile,v
retrieving revision 1.27
diff -u -p -r1.27 Makefile
--- usr.bin/systat/Makefile     12 Mar 2015 01:03:00 -0000      1.27
+++ usr.bin/systat/Makefile     26 Feb 2017 11:21:16 -0000
@@ -5,13 +5,14 @@ PROG= systat
 .PATH: ${.CURDIR}/../../usr.bin/vmstat
 
 CFLAGS+=-DNOKVM
+CPPFLAGS+=-I${.CURDIR}/../../usr.sbin/vmd/
 CPPFLAGS+=-I${.CURDIR}/../../usr.bin/vmstat
 CPPFLAGS+=-I${.CURDIR}/../../sbin/pfctl
 SRCS=  dkstats.c engine.c if.c inetname.c iostat.c main.c mbufs.c netstat.c \
        nfs.c pigs.c sensors.c swap.c vmstat.c pftop.c cache.c pf.c \
-       pool.c malloc.c cpu.c
+       pool.c malloc.c cpu.c vmm.c
 
 DPADD= ${LIBCURSES} ${LIBM} ${LIBKVM}
-LDADD= -lcurses -lm -lkvm
+LDADD= -lcurses -lm -lkvm -lutil
 
 .include <bsd.prog.mk>
Index: usr.bin/systat/engine.c
===================================================================
RCS file: /cvs/src/usr.bin/systat/engine.c,v
retrieving revision 1.19
diff -u -p -r1.19 engine.c
--- usr.bin/systat/engine.c     2 Jan 2016 20:01:48 -0000       1.19
+++ usr.bin/systat/engine.c     26 Feb 2017 11:21:17 -0000
@@ -1320,6 +1320,7 @@ engine_initialize(void)
        signal(SIGQUIT, sig_close);
        signal(SIGWINCH, sig_resize);
        signal(SIGALRM, sig_alarm);
+       signal(SIGPIPE, SIG_IGN); 
 }
 
 void
Index: usr.bin/systat/main.c
===================================================================
RCS file: /cvs/src/usr.bin/systat/main.c,v
retrieving revision 1.66
diff -u -p -r1.66 main.c
--- usr.bin/systat/main.c       13 Oct 2016 11:22:46 -0000      1.66
+++ usr.bin/systat/main.c       26 Feb 2017 11:21:17 -0000
@@ -362,6 +362,7 @@ initialize(void)
        initmalloc();
        initnfs();
        initcpu();
+       initvmm();
 }
 
 void
Index: usr.bin/systat/vmm.c
===================================================================
RCS file: usr.bin/systat/vmm.c
diff -N usr.bin/systat/vmm.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ usr.bin/systat/vmm.c        26 Feb 2017 11:21:25 -0000
@@ -0,0 +1,239 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/signal.h>
+#include <sys/queue.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+#include <machine/vmmvar.h>
+
+#include <imsg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
+#include <unistd.h>
+
+#include "systat.h"
+#include "vmd.h"
+
+#define VMM_IDENT 256
+
+int initvmm(void);
+void print_vmm(void);
+int read_vmm(void);
+int vmm_keyboard_callback(int ch); 
+
+static void connect_vmd(void); 
+static void get_info_vm(uint32_t id, const char *name, int console);
+static int add_info(struct imsg *imsg, int *ret);
+
+static struct vmop_info_result*        vir     = NULL;
+static struct imsgbuf  *ibuf;
+static const char      *socket_name = SOCKET_NAME;
+static int is_connected = 0; 
+static int ctl_sock = -1; 
+static size_t  ct = 0;                                         /* counter for 
number of VM's */
+
+field_def fields_vmm[] = {
+       {"ID",     6, 10, 1, FLD_ALIGN_LEFT,  -1, 0, 0, 0},
+       {"PID",    5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+       {"VCPUS",  5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+       {"MAXMEM", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+       {"CURMEM", 5, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
+       {"TTY",    5, 15, 1, FLD_ALIGN_LEFT,  -1, 0, 0, 0},
+       {"NAME",   5, 15, 1, FLD_ALIGN_LEFT,  -1, 0, 0, 0},
+};
+
+#define FLD_VMM_ID      FIELD_ADDR(fields_vmm,0)
+#define FLD_VMM_PID     FIELD_ADDR(fields_vmm,1)
+#define FLD_VMM_VCPUS   FIELD_ADDR(fields_vmm,2)
+#define FLD_VMM_MAXMEM  FIELD_ADDR(fields_vmm,3)
+#define FLD_VMM_CURMEM  FIELD_ADDR(fields_vmm,4)
+#define FLD_VMM_TTYNAME FIELD_ADDR(fields_vmm,5)
+#define FLD_VMM_NAME    FIELD_ADDR(fields_vmm,6)
+
+/* Define views */
+field_def *view_vmm_0[] = {
+       FLD_VMM_ID, FLD_VMM_PID, FLD_VMM_VCPUS, FLD_VMM_MAXMEM, 
+       FLD_VMM_CURMEM, FLD_VMM_TTYNAME, FLD_VMM_NAME, NULL
+};
+
+/* Define view managers */
+struct view_manager vmm_mgr = {
+       "VMM", NULL, read_vmm, NULL, print_header,
+       print_vmm, vmm_keyboard_callback, NULL, NULL
+};
+
+field_view views_vmm[] = {
+       {view_vmm_0, "vmm", '6', &vmm_mgr},
+       {NULL, NULL, 0, NULL}
+};
+
+static void 
+connect_vmd(void) 
+{
+       struct sockaddr_un sun;
+
+       if (ctl_sock != -1) {
+               close(ibuf->fd); 
+               free(ibuf); 
+       }
+
+       if ((ctl_sock = socket(AF_UNIX,
+                       SOCK_STREAM|SOCK_CLOEXEC, 0)) == -1)
+               err(1, "socket");
+       
+       bzero(&sun, sizeof(sun));
+       sun.sun_family = AF_UNIX;
+       strlcpy(sun.sun_path, socket_name, sizeof(sun.sun_path));
+       
+       if (connect(ctl_sock,
+                                                       (struct sockaddr 
*)&sun, sizeof(sun)) == -1) 
+         is_connected = 0;
+       else
+               is_connected = 1; 
+       
+       if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
+               err(1, "malloc");
+       imsg_init(ibuf, ctl_sock);
+}
+
+static void
+get_info_vm(uint32_t id, const char *name, int console)
+{
+       if (imsg_compose(ibuf, IMSG_VMDOP_GET_INFO_VM_REQUEST, 
+           0, 0, -1, NULL, 0) < 0)
+               errx(1, "imsg_compose");
+}
+
+
+static int
+add_info(struct imsg *imsg, int *ret)
+{
+       if (imsg->hdr.type == IMSG_VMDOP_GET_INFO_VM_DATA) {
+               if ((vir = reallocarray(vir, ct + 1,
+                                sizeof(struct vmop_info_result))) == NULL) {
+                       *ret = ENOMEM;
+                       return (1);
+               }
+               memcpy(&vir[ct], imsg->data, sizeof(struct vmop_info_result));
+               ct++;
+               *ret = 0;
+               return (0);
+       } else if (imsg->hdr.type == IMSG_VMDOP_GET_INFO_VM_END_DATA) {
+               *ret = 0;
+               return (1);
+       } else {
+               *ret = EINVAL;
+               return (1);
+       }
+}
+
+int
+read_vmm(void)
+{
+       int n; 
+       struct imsg     imsg;
+       int ret, done = 0; 
+       
+       if (!is_connected)
+               connect_vmd(); 
+
+       get_info_vm(0, NULL, 0);
+       while (is_connected && ibuf->w.queued) 
+               if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) 
+                       is_connected = 0; 
+       ct = 0; 
+               
+       while (is_connected && !done) {
+               if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
+                       errx(1, "imsg_read error");
+               if (n == 0)
+                       errx(1, "pipe closed");
+               
+               while (is_connected && !done) {
+                       if ((n = imsg_get(ibuf, &imsg)) == -1)
+                               errx(1, "imsg_get error");
+                       if (n == 0)
+                               break;
+                       
+                       if (imsg.hdr.type == IMSG_CTL_FAIL) {
+                               if (IMSG_DATA_SIZE(&imsg) == sizeof(ret)) {
+                                       memcpy(&ret, imsg.data, sizeof(ret));
+                                       errno = ret;
+                                       warn("command failed");
+                               } else 
+                                       warn("command failed");
+                               done = 1;
+                               break;
+                       }
+                       
+                       ret = 0;
+                       done = add_info(&imsg, &ret);
+                       
+                       imsg_free(&imsg);
+               }
+       }
+       
+       return 0;
+}
+
+void
+print_vmm(void)
+{
+       char mem[VMM_IDENT];
+       char cmem[VMM_IDENT];
+       char tty[VMM_IDENT];
+       char name[VMM_MAX_NAME_LEN];
+       struct vm_info_result *v;
+       int i; 
+
+       for (i = 0; vir != NULL && i < ct; i++) {
+               v = &vir[i].vir_info;
+               if (v != NULL) {
+                       print_fld_uint(FLD_VMM_ID, v->vir_id);
+                       print_fld_uint(FLD_VMM_PID, v->vir_creator_pid);
+                       print_fld_uint(FLD_VMM_VCPUS, v->vir_ncpus);
+                       
+                       snprintf(mem, sizeof(mem), "%7zdMB", 
v->vir_memory_size);
+                       print_fld_str(FLD_VMM_MAXMEM, mem);
+                       snprintf(cmem, sizeof(cmem), "%7zdMB", 
v->vir_used_size/1024/1024);
+                       print_fld_str(FLD_VMM_CURMEM, cmem);
+                       snprintf(tty, sizeof(tty), "%s", vir[i].vir_ttyname);
+                       print_fld_str(FLD_VMM_TTYNAME, tty);
+                       snprintf(name, VMM_MAX_NAME_LEN, "%s", v->vir_name);
+                       print_fld_str(FLD_VMM_NAME, name);
+                       
+                       end_line();
+               }
+       }
+       end_line();
+       print_fld_str(FLD_VMM_ID, "Total:");
+       print_fld_uint(FLD_VMM_PID, ct);
+       print_fld_str(FLD_VMM_NAME, 
+                     (is_connected) ? "connected" : "disconnected");
+       
+       if (vir != NULL)
+               free(vir); 
+       vir = NULL; 
+}
+
+int 
+vmm_keyboard_callback(int ch) 
+{
+       keyboard_callback(ch);
+       read_vmm();
+}
+
+int
+initvmm(void)
+{
+       field_view *v;
+       
+       connect_vmd();
+       for (v = views_vmm; v->name != NULL; v++)
+               add_view(v);
+       
+       return(1);
+}

Reply via email to