]> xenbits.xensource.com Git - libvirt.git/commitdiff
Qemu arbitrary monitor commands.
authorChris Lalancette <clalance@redhat.com>
Sat, 17 Apr 2010 02:12:45 +0000 (22:12 -0400)
committerChris Lalancette <clalance@redhat.com>
Fri, 23 Jul 2010 21:30:24 +0000 (17:30 -0400)
Implement the qemu driver's virDomainQemuMonitorCommand
and hook it into the API entry point.

Changes since v1:
 - Rename the (external) qemuMonitorCommand to qemuDomainMonitorCommand
 - Add virCheckFlags to qemuDomainMonitorCommand

Changes since v2:
 - Drop ATTRIBUTE_UNUSED from the flags

Changes since v3:
 - Add a flag to priv so we only print out monitor command warning once.  Note
   that this has not been plumbed into qemuDomainObjPrivateXMLFormat or
   qemuDomainObjPrivateXMLParse, which means that if you run a monitor command,
   restart libvirtd, and then run another monitor command, you may get an
   an erroneous VIR_INFO.  It's a pretty minor matter, and I didn't think it
   warranted the additional code.
 - Add BeginJob/EndJob calls around EnterMonitor/ExitMonitor

Signed-off-by: Chris Lalancette <clalance@redhat.com>
src/qemu/qemu_driver.c
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h
src/qemu/qemu_monitor_text.c
src/qemu/qemu_monitor_text.h

index aae4e002cce955a31ec6a70868132eb556524883..875fc42f24cba526d1c8cf6c0e8b1339e9339b33 100644 (file)
@@ -121,6 +121,7 @@ struct _qemuDomainObjPrivate {
     qemuMonitorPtr mon;
     virDomainChrDefPtr monConfig;
     int monJSON;
+    int monitor_warned;
 
     int nvcpupids;
     int *vcpupids;
@@ -3716,6 +3717,8 @@ static int qemudStartVMDaemon(virConnectPtr conn,
 #endif
         priv->monJSON = 0;
 
+    priv->monitor_warned = 0;
+
     if ((ret = virFileDeletePid(driver->stateDir, vm->def->name)) != 0) {
         virReportSystemError(ret,
                              _("Cannot remove stale PID file for %s"),
@@ -12561,6 +12564,57 @@ cleanup:
     return ret;
 }
 
+static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd,
+                                    char **result, unsigned int flags)
+{
+    struct qemud_driver *driver = domain->conn->privateData;
+    virDomainObjPtr vm = NULL;
+    int ret = -1;
+    qemuDomainObjPrivatePtr priv;
+
+    virCheckFlags(0, -1);
+
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, domain->uuid);
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(domain->uuid, uuidstr);
+        qemuReportError(VIR_ERR_NO_DOMAIN,
+                        _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (!virDomainObjIsActive(vm)) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        "%s", _("domain is not running"));
+        goto cleanup;
+   }
+
+    priv = vm->privateData;
+
+    if (!priv->monitor_warned) {
+        VIR_INFO("Qemu monitor command '%s' executed; libvirt results may be unpredictable!",
+                 cmd);
+        priv->monitor_warned = 1;
+    }
+
+    if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
+        goto cleanup;
+    qemuDomainObjEnterMonitorWithDriver(driver, vm);
+    ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result);
+    qemuDomainObjExitMonitorWithDriver(driver, vm);
+    if (qemuDomainObjEndJob(vm) == 0) {
+        vm = NULL;
+        goto cleanup;
+    }
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
+    return ret;
+}
+
 static virDriver qemuDriver = {
     VIR_DRV_QEMU,
     "QEMU",
@@ -12660,7 +12714,7 @@ static virDriver qemuDriver = {
     qemuDomainSnapshotCurrent, /* domainSnapshotCurrent */
     qemuDomainRevertToSnapshot, /* domainRevertToSnapshot */
     qemuDomainSnapshotDelete, /* domainSnapshotDelete */
-    NULL, /* qemuDomainMonitorCommand */
+    qemuDomainMonitorCommand, /* qemuDomainMonitorCommand */
 };
 
 
index b05032aea609a18a66a5349afb762186e106b13a..f1494ff87bab804c8663862ec1bc099436eda0bd 100644 (file)
@@ -1918,3 +1918,16 @@ int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name)
         ret = qemuMonitorTextDeleteSnapshot(mon, name);
     return ret;
 }
+
+int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply)
+{
+    int ret;
+
+    DEBUG("mon=%p, cmd=%s, reply=%p", mon, cmd, reply);
+
+    if (mon->json)
+        ret = qemuMonitorJSONArbitraryCommand(mon, cmd, reply);
+    else
+        ret = qemuMonitorTextArbitraryCommand(mon, cmd, reply);
+    return ret;
+}
index 459ccb70bdda902eff26a4303e97ae774e07f714..48f4c20beb9e6fe4f062fe2d4f789a87670feed2 100644 (file)
@@ -389,4 +389,6 @@ int qemuMonitorCreateSnapshot(qemuMonitorPtr mon, const char *name);
 int qemuMonitorLoadSnapshot(qemuMonitorPtr mon, const char *name);
 int qemuMonitorDeleteSnapshot(qemuMonitorPtr mon, const char *name);
 
+int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, const char *cmd, char **reply);
+
 #endif /* QEMU_MONITOR_H */
index 4487ff54dd06145e3644e449f5d413459784d09f..e8609aa718a3cae0b723dffea46b1ccd0d0dcd5e 100644 (file)
@@ -2345,3 +2345,31 @@ int qemuMonitorJSONDeleteSnapshot(qemuMonitorPtr mon, const char *name)
     virJSONValueFree(reply);
     return ret;
 }
+
+int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
+                                    const char *cmd_str,
+                                    char **reply_str)
+{
+    virJSONValuePtr cmd = NULL;
+    virJSONValuePtr reply = NULL;
+    int ret = -1;
+
+    cmd = virJSONValueFromString(cmd_str);
+    if (!cmd)
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        goto cleanup;
+
+    *reply_str = virJSONValueToString(reply);
+    if (!(*reply_str))
+        goto cleanup;
+
+    ret = 0;
+
+cleanup:
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+
+    return ret;
+}
index 6fa8d83549d2697b94a16ed53d24d31244cb858e..94806c1063704f2f5057df7191841b7167b74e59 100644 (file)
@@ -196,4 +196,8 @@ int qemuMonitorJSONCreateSnapshot(qemuMonitorPtr mon, const char *name);
 int qemuMonitorJSONLoadSnapshot(qemuMonitorPtr mon, const char *name);
 int qemuMonitorJSONDeleteSnapshot(qemuMonitorPtr mon, const char *name);
 
+int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
+                                    const char *cmd_str,
+                                    char **reply_str);
+
 #endif /* QEMU_MONITOR_JSON_H */
index 569742a42d145b0288703285d9e505aae7473136..69971a656ea757cbb9fb54a11ba667e170927dc7 100644 (file)
@@ -2567,3 +2567,24 @@ cleanup:
     VIR_FREE(reply);
     return ret;
 }
+
+int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
+                                    char **reply)
+{
+    char *safecmd = NULL;
+    int ret;
+
+    if (!(safecmd = qemuMonitorEscapeArg(cmd))) {
+        virReportOOMError();
+        return -1;
+    }
+
+    ret = qemuMonitorCommand(mon, safecmd, reply);
+    if (ret != 0)
+        qemuReportError(VIR_ERR_OPERATION_FAILED,
+                        _("failed to run cmd '%s'"), safecmd);
+
+    VIR_FREE(safecmd);
+
+    return ret;
+}
index 9926d34723bde049dafcfb558d86a984a928b124..c0175092981b92cdf4acdfcfecbdbc3d91d59ba7 100644 (file)
@@ -194,4 +194,7 @@ int qemuMonitorTextCreateSnapshot(qemuMonitorPtr mon, const char *name);
 int qemuMonitorTextLoadSnapshot(qemuMonitorPtr mon, const char *name);
 int qemuMonitorTextDeleteSnapshot(qemuMonitorPtr mon, const char *name);
 
+int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
+                                    char **reply);
+
 #endif /* QEMU_MONITOR_TEXT_H */