[libvirt] [PATCH 8/8] Allow balloon driver collection to be adjusted dynamically

John Ferlan jferlan at redhat.com
Tue Jul 2 13:39:26 UTC 2013


Extend the virDomainSetMemeoryFlags() to accept a 'VIR_DOMAIN_MEM_PERIOD'
which will be used to dynamically set the collection period for the balloon
driver via a 'virsh dommemstat <domain> --period <value>' command.  Add
the --current, --live, & --config options to dommemstat.
---
 docs/formatdomain.html.in    | 14 +++++++++
 include/libvirt/libvirt.h.in |  1 +
 src/libvirt.c                |  8 ++++-
 src/qemu/qemu_driver.c       | 44 +++++++++++++++++++++++++++-
 tools/virsh-domain-monitor.c | 70 ++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 132 insertions(+), 5 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index cc4c5ea..0ec256d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -4612,6 +4612,7 @@ qemu-kvm -net nic,model=? /dev/null
   <devices>
     <memballoon model='virtio'>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+      <stats period='10'/>
     </memballoon>
   </devices>
 </domain></pre>
@@ -4629,6 +4630,19 @@ qemu-kvm -net nic,model=? /dev/null
           <li>'xen' — default with Xen</li>
         </ul>
       </dd>
+      <dt><code>period</code></dt>
+      <dd>
+        <p>
+          The optional <code>period</code> allows the QEMU virtio memory
+          balloon driver to provide statistics through the <code>virsh
+          dommemstat [domain]</code> command.  By default, collection is
+          not enabled. In order to enable, use the <code>virsh dommemstat
+          [domain] --period [number]</code> command or <code>virsh edit</code>
+          command to add the option. If the QEMU driver is not at the right
+          revision, the attempt to set the period will fail.
+          <span class='since'>Since 1.1.1, requires QEMU 1.5</span>
+        </p>
+      </dd>
     </dl>
     <h4><a name="elementsRng">Random number generator device</a></h4>
 
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index b791125..1fc6e82 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1844,6 +1844,7 @@ typedef enum {
 
     /* Additionally, these flags may be bitwise-OR'd in.  */
     VIR_DOMAIN_MEM_MAXIMUM = (1 << 2), /* affect Max rather than current */
+    VIR_DOMAIN_MEM_PERIOD = (1 << 3),  /* set dommemstats period */
 } virDomainMemoryModFlags;
 
 
diff --git a/src/libvirt.c b/src/libvirt.c
index bc1694a..81745bb 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -3738,6 +3738,9 @@ error:
  * on whether just live or both live and persistent state is changed.
  * If VIR_DOMAIN_MEM_MAXIMUM is set, the change affects domain's maximum memory
  * size rather than current memory size.
+ * If VIR_DOMAIN_MEM_PERIOD is set, the domain memory statistics collection
+ * period for the balloon driver will be adjusted.  Use 0 to disable and
+ * a positive value to enable.
  * Not all hypervisors can support all flag combinations.
  *
  * Returns 0 in case of success, -1 in case of failure.
@@ -3763,7 +3766,10 @@ virDomainSetMemoryFlags(virDomainPtr domain, unsigned long memory,
         virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
         goto error;
     }
-    virCheckNonZeroArgGoto(memory, error);
+
+    /* This can be non zero only for setting the balloon collection period */
+    if (!(flags & VIR_DOMAIN_MEM_PERIOD))
+       virCheckNonZeroArgGoto(memory, error);
 
     conn = domain->conn;
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c9a66ff..b76e634 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2166,7 +2166,8 @@ static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
 
     virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                   VIR_DOMAIN_AFFECT_CONFIG |
-                  VIR_DOMAIN_MEM_MAXIMUM, -1);
+                  VIR_DOMAIN_MEM_MAXIMUM |
+                  VIR_DOMAIN_MEM_PERIOD, -1);
 
     if (!(vm = qemuDomObjFromDomain(dom)))
         goto cleanup;
@@ -2205,6 +2206,47 @@ static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
             goto endjob;
         }
 
+    } else if (flags & VIR_DOMAIN_MEM_PERIOD) {
+        /* Set the balloon driver collection interval */
+        priv = vm->privateData;
+        if (!priv->balloonpath) {
+            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                           _("memory balloon driver not defined or "
+                             "not virtio model"));
+            goto endjob;
+        }
+
+        if (newmem != (int)newmem) {
+            virReportError(VIR_ERR_OPERATION_INVALID,
+                           _("period value=%lu does not match set value=%d"),
+                           newmem, (int)newmem);
+            goto endjob;
+        }
+
+        if (flags & VIR_DOMAIN_AFFECT_LIVE) {
+            qemuMonitorObjectProperty prop;
+
+            memset(&prop, 0, sizeof(qemuMonitorObjectProperty));
+            prop.type = QEMU_MONITOR_OBJECT_PROPERTY_INT;
+            prop.val.i = newmem;
+
+            qemuDomainObjEnterMonitor(driver, vm);
+            r = qemuMonitorSetObjectProperty(priv->mon, priv->balloonpath,
+                                             "guest-stats-polling-interval",
+                                             &prop);
+            qemuDomainObjExitMonitor(driver, vm);
+            if (r < 0)
+                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                               _("unable to set balloon driver collection "
+                                 "period"));
+        }
+
+        if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
+            sa_assert(persistentDef);
+            persistentDef->memballoon->period = newmem;
+            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
+            goto endjob;
+        }
     } else {
         /* resize the current memory */
 
diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index 3ba829c..f123247 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -306,6 +306,23 @@ static const vshCmdOptDef opts_dommemstat[] = {
      .flags = VSH_OFLAG_REQ,
      .help = N_("domain name, id or uuid")
     },
+    {.name = "period",
+     .type = VSH_OT_DATA,
+     .flags = VSH_OFLAG_EMPTY_OK,
+     .help = N_("period in seconds to set collection")
+    },
+    {.name = "config",
+     .type = VSH_OT_BOOL,
+     .help = N_("affect next boot")
+    },
+    {.name = "live",
+     .type = VSH_OT_BOOL,
+     .help = N_("affect running domain")
+    },
+    {.name = "current",
+     .type = VSH_OT_BOOL,
+     .help = N_("affect current domain")
+    },
     {.name = NULL}
 };
 
@@ -316,15 +333,60 @@ cmdDomMemStat(vshControl *ctl, const vshCmd *cmd)
     const char *name;
     struct _virDomainMemoryStat stats[VIR_DOMAIN_MEMORY_STAT_NR];
     unsigned int nr_stats, i;
+    int ret = false;
+    int rv = 0;
+    int period = -1;
+    bool config = vshCommandOptBool(cmd, "config");
+    bool live = vshCommandOptBool(cmd, "live");
+    bool current = vshCommandOptBool(cmd, "current");
+    unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+
+    VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
+    VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
+    if (config)
+        flags |= VIR_DOMAIN_AFFECT_CONFIG;
+    if (live)
+        flags |= VIR_DOMAIN_AFFECT_LIVE;
 
     if (!(dom = vshCommandOptDomain(ctl, cmd, &name)))
         return false;
 
+    /* none of the options were specified - choose defaults based on state */
+    if (!current && !live && !config) {
+        if (virDomainIsActive(dom) == 1)
+            flags |= VIR_DOMAIN_AFFECT_LIVE;
+        else
+            flags |= VIR_DOMAIN_AFFECT_CONFIG;
+    }
+
+    /* Providing a period will adjust the balloon driver collection period.
+     * This is not really an unsigned long, but it
+     */
+    if ((rv = vshCommandOptInt(cmd, "period", &period)) < 0) {
+        vshError(ctl, "%s",
+                 _("Unable to parse integer parameter."));
+        goto cleanup;
+    }
+    if (rv > 0) {
+        if (period < 0) {
+            vshError(ctl, _("Invalid collection period value '%d'"), period);
+            goto cleanup;
+        }
+
+        flags |= VIR_DOMAIN_MEM_PERIOD;
+        if (virDomainSetMemoryFlags(dom, period, flags) < 0) {
+            vshError(ctl, "%s",
+                     _("Unable to change balloon collection period."));
+        } else {
+            ret = true;
+        }
+        goto cleanup;
+    }
+
     nr_stats = virDomainMemoryStats(dom, stats, VIR_DOMAIN_MEMORY_STAT_NR, 0);
     if (nr_stats == -1) {
         vshError(ctl, _("Failed to get memory statistics for domain %s"), name);
-        virDomainFree(dom);
-        return false;
+        goto cleanup;
     }
 
     for (i = 0; i < nr_stats; i++) {
@@ -346,8 +408,10 @@ cmdDomMemStat(vshControl *ctl, const vshCmd *cmd)
             vshPrint(ctl, "rss %llu\n", stats[i].val);
     }
 
+    ret = true;
+cleanup:
     virDomainFree(dom);
-    return true;
+    return ret;
 }
 
 /*
-- 
1.8.1.4




More information about the libvir-list mailing list