Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/qemu/qemu_driver.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_process.c | 31 ++++++++++++++++++---------
src/qemu/qemu_process.h | 1 +
3 files changed, 79 insertions(+), 10 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 97b194b057..fea1f24250 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -16300,6 +16300,62 @@ static virDomainPtr qemuDomainQemuAttach(virConnectPtr conn,
}
+static virDomainPtr qemuDomainQemuReconnect(virConnectPtr conn,
+ const char *name,
+ unsigned int flags)
+{
+ virQEMUDriverPtr driver = conn->privateData;
+ virDomainObjPtr vm = NULL;
+ virDomainPtr dom = NULL;
+ virCapsPtr caps = NULL;
+ virQEMUDriverConfigPtr cfg;
+
+ virCheckFlags(0, NULL);
+
+ cfg = virQEMUDriverGetConfig(driver);
+
+ if (strchr(name, '/')) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("name %s cannot contain '/'"), name);
+ goto cleanup;
+ }
+
+ vm = virDomainObjListFindByName(driver->domains, name);
+ if (vm) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ _("Domain '%s' already exists"), name);
+ goto cleanup;
+ }
+
+ if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
+ goto cleanup;
+
+ if (!(vm = virDomainObjListLoadStatus(driver->domains,
+ cfg->stateDir,
+ name,
+ caps,
+ driver->xmlopt,
+ NULL, NULL))) {
+ goto cleanup;
+ }
+
+ if (virDomainQemuReconnectEnsureACL(conn, vm->def) < 0) {
+ qemuDomainRemoveInactive(driver, vm);
+ goto cleanup;
+ }
+
+ dom = virGetDomain(conn, vm->def->name, vm->def->uuid,
vm->def->id);
+
+ qemuDomainObjEndJob(driver, vm);
+
+ cleanup:
+ virDomainObjEndAPI(&vm);
+ virObjectUnref(caps);
+ virObjectUnref(cfg);
+ return dom;
+}
+
+
static int
qemuDomainOpenConsole(virDomainPtr dom,
const char *dev_name,
@@ -21262,6 +21318,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
.domainSnapshotDelete = qemuDomainSnapshotDelete, /* 0.8.0 */
.domainQemuMonitorCommand = qemuDomainQemuMonitorCommand, /* 0.8.3 */
.domainQemuAttach = qemuDomainQemuAttach, /* 0.9.4 */
+ .domainQemuReconnect = qemuDomainQemuReconnect, /* 4.1.0 */
.domainQemuAgentCommand = qemuDomainQemuAgentCommand, /* 0.10.0 */
.connectDomainQemuMonitorEventRegister = qemuConnectDomainQemuMonitorEventRegister,
/* 1.2.3 */
.connectDomainQemuMonitorEventDeregister =
qemuConnectDomainQemuMonitorEventDeregister, /* 1.2.3 */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index a0f430f89f..ea924cf9b6 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7088,14 +7088,10 @@ struct qemuProcessReconnectData {
* We can't do normal MonitorEnter & MonitorExit because these two lock the
* monitor lock, which does not exists in this early phase.
*/
-static void
-qemuProcessReconnect(void *opaque)
+int
+qemuProcessReconnect(virQEMUDriverPtr driver, virDomainObjPtr obj, virConnectPtr conn)
{
- struct qemuProcessReconnectData *data = opaque;
- virQEMUDriverPtr driver = data->driver;
- virDomainObjPtr obj = data->obj;
qemuDomainObjPrivatePtr priv;
- virConnectPtr conn = data->conn;
struct qemuDomainJobObj oldjob;
int state;
int reason;
@@ -7104,8 +7100,7 @@ qemuProcessReconnect(void *opaque)
unsigned int stopFlags = 0;
bool jobStarted = false;
virCapsPtr caps = NULL;
-
- VIR_FREE(data);
+ int ret = -1;
qemuDomainObjRestoreJob(obj, &oldjob);
if (oldjob.asyncJob == QEMU_ASYNC_JOB_MIGRATION_IN)
@@ -7297,6 +7292,7 @@ qemuProcessReconnect(void *opaque)
if (virAtomicIntInc(&driver->nactive) == 1 &&
driver->inhibitCallback)
driver->inhibitCallback(true, driver->inhibitOpaque);
+ ret = 0;
cleanup:
if (jobStarted) {
if (!virDomainObjIsActive(obj))
@@ -7311,7 +7307,7 @@ qemuProcessReconnect(void *opaque)
virObjectUnref(cfg);
virObjectUnref(caps);
virNWFilterUnlockFilterUpdates();
- return;
+ return ret;
error:
if (virDomainObjIsActive(obj)) {
@@ -7338,6 +7334,21 @@ qemuProcessReconnect(void *opaque)
goto cleanup;
}
+
+static void
+qemuProcessReconnectThread(void *opaque)
+{
+ struct qemuProcessReconnectData *data = opaque;
+ virQEMUDriverPtr driver = data->driver;
+ virDomainObjPtr obj = data->obj;
+ virConnectPtr conn = data->conn;
+
+ qemuProcessReconnect(driver, obj, conn);
+
+ VIR_FREE(data);
+}
+
+
static int
qemuProcessReconnectHelper(virDomainObjPtr obj,
void *opaque)
@@ -7369,7 +7380,7 @@ qemuProcessReconnectHelper(virDomainObjPtr obj,
*/
virObjectRef(data->conn);
- if (virThreadCreate(&thread, false, qemuProcessReconnect, data) < 0) {
+ if (virThreadCreate(&thread, false, qemuProcessReconnectThread, data) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not create thread. QEMU initialization "
"might be incomplete"));
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index cd9a720313..846577d341 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -45,6 +45,7 @@ int qemuProcessBuildDestroyMemoryPaths(virQEMUDriverPtr driver,
void qemuProcessAutostartAll(virQEMUDriverPtr driver);
void qemuProcessReconnectAll(virConnectPtr conn, virQEMUDriverPtr driver);
+int qemuProcessReconnect(virQEMUDriverPtr driver, virDomainObjPtr obj, virConnectPtr
conn);
typedef struct _qemuProcessIncomingDef qemuProcessIncomingDef;
typedef qemuProcessIncomingDef *qemuProcessIncomingDefPtr;
--
2.14.3