提交 de5a60e1 编写于 作者: J Jiri Denemark

Refactor qemudDomainRestore

We need to be able to restore a domain which we already locked and
started a job for it without undoing these steps. This patch factors
out internals of qemudDomainRestore into separate functions which work
for locked objects.
上级 b8ed797c
...@@ -5992,29 +5992,44 @@ child_cleanup: ...@@ -5992,29 +5992,44 @@ child_cleanup:
_exit(exit_code); _exit(exit_code);
} }
/* TODO: check seclabel restore */ static int qemudDomainSaveImageClose(int fd, pid_t read_pid, int *status)
static int qemudDomainRestore(virConnectPtr conn, {
const char *path) { int ret = 0;
struct qemud_driver *driver = conn->privateData;
virDomainDefPtr def = NULL; if (fd != -1)
virDomainObjPtr vm = NULL; close(fd);
int fd = -1;
if (read_pid != -1) {
/* reap the process that read the file */
while ((ret = waitpid(read_pid, status, 0)) == -1
&& errno == EINTR) {
/* empty */
}
} else if (status) {
*status = 0;
}
return ret;
}
static int ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5)
qemudDomainSaveImageOpen(struct qemud_driver *driver,
const char *path,
virDomainDefPtr *ret_def,
struct qemud_save_header *ret_header,
pid_t *ret_read_pid)
{
int fd;
pid_t read_pid = -1; pid_t read_pid = -1;
int ret = -1;
char *xml = NULL;
struct qemud_save_header header; struct qemud_save_header header;
virDomainEventPtr event = NULL; char *xml = NULL;
int intermediatefd = -1; virDomainDefPtr def = NULL;
pid_t intermediate_pid = -1;
int childstat;
qemuDriverLock(driver);
/* Verify the header and read the XML */
if ((fd = open(path, O_RDONLY)) < 0) { if ((fd = open(path, O_RDONLY)) < 0) {
if ((driver->user == 0) || (getuid() != 0)) { if ((driver->user == 0) || (getuid() != 0)) {
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("cannot read domain image")); "%s", _("cannot read domain image"));
goto cleanup; goto error;
} }
/* Opening as root failed, but qemu runs as a different user /* Opening as root failed, but qemu runs as a different user
...@@ -6023,44 +6038,44 @@ static int qemudDomainRestore(virConnectPtr conn, ...@@ -6023,44 +6038,44 @@ static int qemudDomainRestore(virConnectPtr conn,
have the necessary authority to read the file. */ have the necessary authority to read the file. */
if ((fd = qemudOpenAsUID(path, driver->user, &read_pid)) < 0) { if ((fd = qemudOpenAsUID(path, driver->user, &read_pid)) < 0) {
/* error already reported */ /* error already reported */
goto cleanup; goto error;
} }
} }
if (saferead(fd, &header, sizeof(header)) != sizeof(header)) { if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to read qemu header")); "%s", _("failed to read qemu header"));
goto cleanup; goto error;
} }
if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) { if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) {
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("image magic is incorrect")); "%s", _("image magic is incorrect"));
goto cleanup; goto error;
} }
if (header.version > QEMUD_SAVE_VERSION) { if (header.version > QEMUD_SAVE_VERSION) {
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
_("image version is not supported (%d > %d)"), _("image version is not supported (%d > %d)"),
header.version, QEMUD_SAVE_VERSION); header.version, QEMUD_SAVE_VERSION);
goto cleanup; goto error;
} }
if (header.xml_len <= 0) { if (header.xml_len <= 0) {
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
_("invalid XML length: %d"), header.xml_len); _("invalid XML length: %d"), header.xml_len);
goto cleanup; goto error;
} }
if (VIR_ALLOC_N(xml, header.xml_len) < 0) { if (VIR_ALLOC_N(xml, header.xml_len) < 0) {
virReportOOMError(); virReportOOMError();
goto cleanup; goto error;
} }
if (saferead(fd, xml, header.xml_len) != header.xml_len) { if (saferead(fd, xml, header.xml_len) != header.xml_len) {
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to read XML")); "%s", _("failed to read XML"));
goto cleanup; goto error;
} }
/* Create a domain from this XML */ /* Create a domain from this XML */
...@@ -6068,35 +6083,54 @@ static int qemudDomainRestore(virConnectPtr conn, ...@@ -6068,35 +6083,54 @@ static int qemudDomainRestore(virConnectPtr conn,
VIR_DOMAIN_XML_INACTIVE))) { VIR_DOMAIN_XML_INACTIVE))) {
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to parse XML")); "%s", _("failed to parse XML"));
goto cleanup; goto error;
} }
if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) VIR_FREE(xml);
goto cleanup;
if (!(vm = virDomainAssignDef(driver->caps, *ret_def = def;
&driver->domains, *ret_header = header;
def, true))) { *ret_read_pid = read_pid;
qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to assign new VM"));
goto cleanup;
}
def = NULL;
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) return fd;
goto cleanup;
error:
virDomainDefFree(def);
VIR_FREE(xml);
qemudDomainSaveImageClose(fd, read_pid, NULL);
return -1;
}
/* TODO: check seclabel restore */
static int ATTRIBUTE_NONNULL(6)
qemudDomainSaveImageStartVM(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm,
int fd,
pid_t read_pid,
const struct qemud_save_header *header,
const char *path)
{
int ret = -1;
virDomainEventPtr event;
int intermediatefd = -1;
pid_t intermediate_pid = -1;
int childstat;
int wait_ret;
int status;
if (header.version == 2) { if (header->version == 2) {
const char *intermediate_argv[3] = { NULL, "-dc", NULL }; const char *intermediate_argv[3] = { NULL, "-dc", NULL };
const char *prog = qemudSaveCompressionTypeToString(header.compressed); const char *prog = qemudSaveCompressionTypeToString(header->compressed);
if (prog == NULL) { if (prog == NULL) {
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
_("Invalid compressed save format %d"), _("Invalid compressed save format %d"),
header.compressed); header->compressed);
goto endjob; goto out;
} }
if (header.compressed != QEMUD_SAVE_FORMAT_RAW) { if (header->compressed != QEMUD_SAVE_FORMAT_RAW) {
intermediate_argv[0] = prog; intermediate_argv[0] = prog;
intermediatefd = fd; intermediatefd = fd;
fd = -1; fd = -1;
...@@ -6105,29 +6139,27 @@ static int qemudDomainRestore(virConnectPtr conn, ...@@ -6105,29 +6139,27 @@ static int qemudDomainRestore(virConnectPtr conn,
qemuReportError(VIR_ERR_INTERNAL_ERROR, qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("Failed to start decompression binary %s"), _("Failed to start decompression binary %s"),
intermediate_argv[0]); intermediate_argv[0]);
goto endjob; goto out;
} }
} }
} }
/* Set the migration source and start it up. */ /* Set the migration source and start it up. */
ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd); ret = qemudStartVMDaemon(conn, driver, vm, "stdio", fd);
if (intermediate_pid != -1) { if (intermediate_pid != -1) {
/* Wait for intermediate process to exit */ /* Wait for intermediate process to exit */
while (waitpid(intermediate_pid, &childstat, 0) == -1 && while (waitpid(intermediate_pid, &childstat, 0) == -1 &&
errno == EINTR); errno == EINTR) {
/* empty */
}
} }
if (intermediatefd != -1) if (intermediatefd != -1)
close(intermediatefd); close(intermediatefd);
close(fd);
wait_ret = qemudDomainSaveImageClose(fd, read_pid, &status);
fd = -1; fd = -1;
if (read_pid != -1) { if (read_pid != -1) {
int wait_ret;
int status;
/* reap the process that read the file */
while (((wait_ret = waitpid(read_pid, &status, 0)) == -1)
&& (errno == EINTR)) {
/* empty */
}
read_pid = -1; read_pid = -1;
if (wait_ret == -1) { if (wait_ret == -1) {
virReportSystemError(errno, virReportSystemError(errno,
...@@ -6149,22 +6181,19 @@ static int qemudDomainRestore(virConnectPtr conn, ...@@ -6149,22 +6181,19 @@ static int qemudDomainRestore(virConnectPtr conn,
} }
} }
} }
if (ret < 0) {
if (!vm->persistent) { if (ret < 0)
if (qemuDomainObjEndJob(vm) > 0) goto out;
virDomainRemoveInactive(&driver->domains,
vm);
vm = NULL;
}
goto endjob;
}
event = virDomainEventNewFromObj(vm, event = virDomainEventNewFromObj(vm,
VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED,
VIR_DOMAIN_EVENT_STARTED_RESTORED); VIR_DOMAIN_EVENT_STARTED_RESTORED);
if (event)
qemuDomainEventQueue(driver, event);
/* If it was running before, resume it now. */ /* If it was running before, resume it now. */
if (header.was_running) { if (header->was_running) {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuDomainObjEnterMonitorWithDriver(driver, vm);
if (qemuMonitorStartCPUs(priv->mon, conn) < 0) { if (qemuMonitorStartCPUs(priv->mon, conn) < 0) {
...@@ -6172,38 +6201,68 @@ static int qemudDomainRestore(virConnectPtr conn, ...@@ -6172,38 +6201,68 @@ static int qemudDomainRestore(virConnectPtr conn,
qemuReportError(VIR_ERR_OPERATION_FAILED, qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to resume domain")); "%s", _("failed to resume domain"));
qemuDomainObjExitMonitorWithDriver(driver,vm); qemuDomainObjExitMonitorWithDriver(driver,vm);
goto endjob; goto out;
} }
qemuDomainObjExitMonitorWithDriver(driver, vm); qemuDomainObjExitMonitorWithDriver(driver, vm);
vm->state = VIR_DOMAIN_RUNNING; vm->state = VIR_DOMAIN_RUNNING;
if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) { if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
VIR_WARN("Failed to save status on vm %s", vm->def->name); VIR_WARN("Failed to save status on vm %s", vm->def->name);
goto endjob; goto out;
} }
} }
ret = 0; ret = 0;
endjob: out:
if (vm && return ret;
qemuDomainObjEndJob(vm) == 0) }
static int qemudDomainRestore(virConnectPtr conn,
const char *path) {
struct qemud_driver *driver = conn->privateData;
virDomainDefPtr def = NULL;
virDomainObjPtr vm = NULL;
int fd = -1;
pid_t read_pid = -1;
int ret = -1;
struct qemud_save_header header;
qemuDriverLock(driver);
fd = qemudDomainSaveImageOpen(driver, path, &def, &header, &read_pid);
if (fd < 0)
goto cleanup;
if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
goto cleanup;
if (!(vm = virDomainAssignDef(driver->caps,
&driver->domains,
def, true))) {
qemuReportError(VIR_ERR_OPERATION_FAILED,
"%s", _("failed to assign new VM"));
goto cleanup;
}
def = NULL;
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
goto cleanup;
ret = qemudDomainSaveImageStartVM(conn, driver, vm, fd,
read_pid, &header, path);
if (qemuDomainObjEndJob(vm) == 0)
vm = NULL;
else if (ret < 0 && !vm->persistent) {
virDomainRemoveInactive(&driver->domains, vm);
vm = NULL; vm = NULL;
}
cleanup: cleanup:
virDomainDefFree(def); virDomainDefFree(def);
VIR_FREE(xml); qemudDomainSaveImageClose(fd, read_pid, NULL);
if (fd != -1)
close(fd);
if (read_pid != 0) {
/* reap the process that read the file */
while ((waitpid(read_pid, NULL, 0) == -1)
&& (errno == EINTR)) {
/* empty */
}
}
if (vm) if (vm)
virDomainObjUnlock(vm); virDomainObjUnlock(vm);
if (event)
qemuDomainEventQueue(driver, event);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册