]> xenbits.xensource.com Git - libvirt.git/commitdiff
Added vcpuinfo vcpupin commands to virsh. Fixed off by one bug in virDomainVcpuPin...
authorDaniel P. Berrange <berrange@redhat.com>
Mon, 7 Aug 2006 14:35:20 +0000 (14:35 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 7 Aug 2006 14:35:20 +0000 (14:35 +0000)
ChangeLog
include/libvirt/libvirt.h
src/libvirt.c
src/virsh.c

index 952c9d6f3f421af61dc70edfe091e952d0382f59..1efed88a54ce9ab64f472a061be49b73188f512d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Fri Aug  4 20:19:23 EDT 2006 Daniel Berrange <berrange@redhat.com>
+
+       * src/libvirt.c: Fix off-by-one in validated VCPU number (it is
+       zero based, not one based).
+       * include/libvirt/libvirt.h: Add some convenience macros for 
+       calculating neccessary CPU map lengths & total host CPUs
+       * src/virsh.c: Add 'vcpuinfo' and 'vcpumap' commands
+       
 Fri Aug  4 14:45:25 CEST 2006 Daniel Veillard <veillard@redhat.com>
 
        * python/generator.py: fix the generator when handling long integers
index 2db8beba03ba7424f100a172198464e048b602d1..f846fe03514fda41ed0a2b4051fcc5b16a17ac0f 100644 (file)
@@ -167,6 +167,18 @@ struct _virNodeInfo {
     unsigned int threads;/* number of threads per core */
 };
 
+
+/**
+ * VIR_NODEINFO_MAXCPUS:
+ * @nodeinfo: virNodeInfo instance
+ *
+ * This macro is to calculate the total number of CPUs supported
+ * but not neccessarily active in the host.
+ */
+
+
+#define VIR_NODEINFO_MAXCPUS(nodeinfo) ((nodeinfo).nodes*(nodeinfo).sockets*(nodeinfo).cores*(nodeinfo).threads)
+
 /**
  * virNodeInfoPtr:
  *
@@ -339,6 +351,18 @@ int                        virDomainPinVcpu        (virDomainPtr domain,
 
 #define VIR_UNUSE_CPU(cpumap,cpu)      (cpumap[(cpu)/8] &= ~(1<<((cpu)%8)))
 
+/**
+ * VIR_CPU_MAPLEN
+ * @cpu: number of physical CPUs
+ *
+ * This macro is to be used in conjonction with virDomainPinVcpu() API.
+ * It returns the length (in bytes) required to store the complete
+ * CPU map between a single virtual & all physical CPUs of a domain.
+ */
+
+#define VIR_CPU_MAPLEN(cpu)      (((cpu)+7)/8)
+
+
 int                    virDomainGetVcpus       (virDomainPtr domain,
                                                 virVcpuInfoPtr info,
                                                 int maxinfo,
index 70fcf0a7bccc86a114ee9975ca97d886bfa7ffde..14294894cda198e67d18399dbeb4763f3219c8ed 100644 (file)
@@ -1720,7 +1720,7 @@ virDomainPinVcpu(virDomainPtr domain, unsigned int vcpu,
     }
     if (domain->conn->flags & VIR_CONNECT_RO)
         return (-1);
-    if ((vcpu < 1) || (cpumap == NULL) || (maplen < 1)) {
+    if ((vcpu < 0) || (cpumap == NULL) || (maplen < 1)) {
         virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return (-1);
     }
index 84a05554e3d8814dcd0b67dff019a8d4dc51214c..a5f72ac0a05e54062b87a8ed584eb3882ae7e247 100644 (file)
@@ -207,6 +207,7 @@ static void vshDebug(vshControl * ctl, int level, const char *format, ...);
 #define vshPrint(_ctl, ...)   fprintf(stdout, __VA_ARGS__)
 
 static const char *vshDomainStateToString(int state);
+static const char *vshDomainVcpuStateToString(int state);
 static int vshConnectionUsability(vshControl * ctl, virConnectPtr conn,
                                   int showerror);
 
@@ -793,6 +794,175 @@ cmdDominfo(vshControl * ctl, vshCmd * cmd)
     return ret;
 }
 
+/*
+ * "vcpuinfo" command
+ */
+static vshCmdInfo info_vcpuinfo[] = {
+    {"syntax", "vcpuinfo <domain>"},
+    {"help", "domain vcpu information"},
+    {"desc", "Returns basic information about the domain virtual CPUs."},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vcpuinfo[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, "domain name, id or uuid"},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVcpuinfo(vshControl * ctl, vshCmd * cmd)
+{
+    virDomainInfo info;
+    virDomainPtr dom;
+    virNodeInfo nodeinfo;
+    virVcpuInfoPtr cpuinfo;
+    unsigned char *cpumap;
+    int ncpus;
+    size_t cpumaplen;
+    int ret = TRUE;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
+        return FALSE;
+
+    if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) {
+        virDomainFree(dom);
+       return FALSE;
+    }
+
+    if (virDomainGetInfo(dom, &info) != 0) {
+        virDomainFree(dom);
+        return FALSE;
+    }
+
+    cpuinfo = malloc(sizeof(virVcpuInfo)*info.nrVirtCpu);
+    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
+    cpumap = malloc(info.nrVirtCpu * cpumaplen);
+
+    if ((ncpus = virDomainGetVcpus(dom, 
+                                  cpuinfo, info.nrVirtCpu,
+                                  cpumap, cpumaplen)) >= 0) {
+        int n;
+       for (n = 0 ; n < ncpus ; n++) {
+           unsigned int m;
+           vshPrint(ctl, "%-15s %d\n", "VCPU:", n);
+           vshPrint(ctl, "%-15s %d\n", "CPU:", cpuinfo[n].cpu);
+           vshPrint(ctl, "%-15s %s\n", "State:",
+                    vshDomainVcpuStateToString(cpuinfo[n].state));
+           if (cpuinfo[n].cpuTime != 0) {
+               double cpuUsed = cpuinfo[n].cpuTime;
+               
+               cpuUsed /= 1000000000.0;
+               
+               vshPrint(ctl, "%-15s %.1lfs\n", "CPU time:", cpuUsed);
+           }
+           vshPrint(ctl, "%-15s ", "CPU Affinity:");
+           for (m = 0 ; m < VIR_NODEINFO_MAXCPUS(nodeinfo) ; m++) {
+               vshPrint(ctl, "%c", VIR_CPU_USABLE(cpumap, cpumaplen, n, m) ? 'y' : '-');
+           }
+           vshPrint(ctl, "\n");
+           if (n < (ncpus - 1)) {
+               vshPrint(ctl, "\n");
+           }
+       }
+    } else {
+        ret = FALSE;
+    }
+
+    free(cpumap);
+    free(cpuinfo);
+    virDomainFree(dom);
+    return ret;
+}
+
+/*
+ * "vcpupin" command
+ */
+static vshCmdInfo info_vcpupin[] = {
+    {"syntax", "vcpupin <domain>"},
+    {"help", "control domain vcpu affinity"},
+    {"desc", "Pin domain VCPUs to host physical CPUs"},
+    {NULL, NULL}
+};
+
+static vshCmdOptDef opts_vcpupin[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, "domain name, id or uuid"},
+    {"vcpu", VSH_OT_DATA, VSH_OFLAG_REQ, "vcpu number"},
+    {"cpulist", VSH_OT_DATA, VSH_OFLAG_REQ, "host cpu number(s) (comma separated)"},
+    {NULL, 0, 0, NULL}
+};
+
+static int
+cmdVcpupin(vshControl * ctl, vshCmd * cmd)
+{
+    virDomainInfo info;
+    virDomainPtr dom;
+    virNodeInfo nodeinfo;
+    int vcpu;
+    char *cpulist;
+    int ret = TRUE;
+    int vcpufound = 0;
+    unsigned char *cpumap;
+    int cpumaplen;
+
+    if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+        return FALSE;
+
+    if (!(dom = vshCommandOptDomain(ctl, cmd, "domain", NULL)))
+        return FALSE;
+
+    vcpu = vshCommandOptInt(cmd, "vcpu", &vcpufound);
+    if (!vcpufound) {
+        virDomainFree(dom);
+        return FALSE;
+    }
+
+    if (!(cpulist = vshCommandOptString(cmd, "cpulist", NULL))) {
+        virDomainFree(dom);
+        return FALSE;
+    }
+      
+    if (virNodeGetInfo(ctl->conn, &nodeinfo) != 0) {
+        virDomainFree(dom);
+        return FALSE;
+    }
+
+    if (virDomainGetInfo(dom, &info) != 0) {
+        virDomainFree(dom);
+        return FALSE;
+    }
+
+    if (vcpu >= info.nrVirtCpu) {
+        virDomainFree(dom);
+        return FALSE;
+    }
+
+    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
+    cpumap = malloc(cpumaplen);
+    memset(cpumap, 0, cpumaplen);
+
+    do {
+        unsigned int cpu = atoi(cpulist);
+
+        if (cpu < VIR_NODEINFO_MAXCPUS(nodeinfo)) {
+            VIR_USE_CPU(cpumap, cpu);
+        }
+        cpulist = index(cpulist, ',');
+        if (cpulist)
+            cpulist++;
+    } while (cpulist);
+
+    if (virDomainPinVcpu(dom, vcpu, cpumap, cpumaplen) != 0) {
+        ret = FALSE;
+    }
+
+    free(cpumap);
+    virDomainFree(dom);
+    return ret;
+}
+
 /*
  * "nodeinfo" command
  */
@@ -1081,6 +1251,8 @@ static vshCmdDef commands[] = {
     {"save", cmdSave, opts_save, info_save},
     {"shutdown", cmdShutdown, opts_shutdown, info_shutdown},
     {"suspend", cmdSuspend, opts_suspend, info_suspend},
+    {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo},
+    {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin},
     {"version", cmdVersion, NULL, info_version},
     {NULL, NULL, NULL, NULL}
 };
@@ -1643,6 +1815,22 @@ vshDomainStateToString(int state)
     return NULL;
 }
 
+static const char *
+vshDomainVcpuStateToString(int state)
+{
+    switch (state) {
+        case VIR_VCPU_OFFLINE:
+            return "offline";
+        case VIR_VCPU_BLOCKED:
+            return "blocked";
+        case VIR_VCPU_RUNNING:
+            return "running";
+        default:
+            return "no state";
+    }
+    return NULL;
+}
+
 static int
 vshConnectionUsability(vshControl * ctl, virConnectPtr conn, int showerror)
 {