提交 ea960fb7 编写于 作者: D Daniel P. Berrange

Merge all return paths from QEMU driver APIs

上级 8492cd20
Thu Dec 4 21:01:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
* src/qemu_driver.c: Merge all return paths from driver APIs
Thu Dec 4 21:00:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com> Thu Dec 4 21:00:41 GMT 2008 Daniel P. Berrange <berrange@redhat.com>
* src/test.c: Stub out node device APIs to avoid activating * src/test.c: Stub out node device APIs to avoid activating
......
...@@ -1074,7 +1074,7 @@ static int qemudDispatchVMFailure(struct qemud_driver *driver, virDomainObjPtr v ...@@ -1074,7 +1074,7 @@ static int qemudDispatchVMFailure(struct qemud_driver *driver, virDomainObjPtr v
static void static void
qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) { qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
struct qemud_driver *driver = (struct qemud_driver *)opaque; struct qemud_driver *driver = opaque;
virDomainObjPtr vm = NULL; virDomainObjPtr vm = NULL;
unsigned int i; unsigned int i;
...@@ -1236,7 +1236,7 @@ static virDrvOpenStatus qemudOpen(virConnectPtr conn, ...@@ -1236,7 +1236,7 @@ static virDrvOpenStatus qemudOpen(virConnectPtr conn,
} }
static int qemudClose(virConnectPtr conn) { static int qemudClose(virConnectPtr conn) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
/* Get rid of callbacks registered for this conn */ /* Get rid of callbacks registered for this conn */
virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks); virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks);
...@@ -1308,14 +1308,12 @@ static int qemudGetNodeInfo(virConnectPtr conn, ...@@ -1308,14 +1308,12 @@ static int qemudGetNodeInfo(virConnectPtr conn,
static char *qemudGetCapabilities(virConnectPtr conn) { static char *qemudGetCapabilities(virConnectPtr conn) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
char *xml; char *xml;
if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) { if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for capabilities support")); "%s", _("failed to allocate space for capabilities support"));
return NULL;
}
return xml; return xml;
} }
...@@ -1329,11 +1327,12 @@ qemudNodeGetCellsFreeMemory(virConnectPtr conn, ...@@ -1329,11 +1327,12 @@ qemudNodeGetCellsFreeMemory(virConnectPtr conn,
int maxCells) int maxCells)
{ {
int n, lastCell, numCells; int n, lastCell, numCells;
int ret = -1;
if (numa_available() < 0) { if (numa_available() < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT, qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("NUMA not supported on this host")); "%s", _("NUMA not supported on this host"));
return -1; goto cleanup;
} }
lastCell = startCell + maxCells - 1; lastCell = startCell + maxCells - 1;
if (lastCell > numa_max_node()) if (lastCell > numa_max_node())
...@@ -1344,22 +1343,26 @@ qemudNodeGetCellsFreeMemory(virConnectPtr conn, ...@@ -1344,22 +1343,26 @@ qemudNodeGetCellsFreeMemory(virConnectPtr conn,
if (numa_node_size64(n, &mem) < 0) { if (numa_node_size64(n, &mem) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Failed to query NUMA free memory")); "%s", _("Failed to query NUMA free memory"));
return -1; goto cleanup;
} }
freeMems[numCells++] = mem; freeMems[numCells++] = mem;
} }
return numCells; ret = numCells;
cleanup:
return ret;
} }
static unsigned long long static unsigned long long
qemudNodeGetFreeMemory (virConnectPtr conn) qemudNodeGetFreeMemory (virConnectPtr conn)
{ {
unsigned long long freeMem = 0; unsigned long long freeMem = -1;
int n; int n;
if (numa_available() < 0) { if (numa_available() < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT, qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("NUMA not supported on this host")); "%s", _("NUMA not supported on this host"));
return -1; goto cleanup;
} }
for (n = 0 ; n <= numa_max_node() ; n++) { for (n = 0 ; n <= numa_max_node() ; n++) {
...@@ -1367,11 +1370,12 @@ qemudNodeGetFreeMemory (virConnectPtr conn) ...@@ -1367,11 +1370,12 @@ qemudNodeGetFreeMemory (virConnectPtr conn)
if (numa_node_size64(n, &mem) < 0) { if (numa_node_size64(n, &mem) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Failed to query NUMA free memory")); "%s", _("Failed to query NUMA free memory"));
return -1; goto cleanup;
} }
freeMem += mem; freeMem += mem;
} }
cleanup:
return freeMem; return freeMem;
} }
...@@ -1415,57 +1419,72 @@ static int qemudGetProcessInfo(unsigned long long *cpuTime, int pid) { ...@@ -1415,57 +1419,72 @@ static int qemudGetProcessInfo(unsigned long long *cpuTime, int pid) {
static virDomainPtr qemudDomainLookupByID(virConnectPtr conn, static virDomainPtr qemudDomainLookupByID(virConnectPtr conn,
int id) { int id) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
virDomainObjPtr vm = virDomainFindByID(&driver->domains, id); virDomainObjPtr vm;
virDomainPtr dom; virDomainPtr dom = NULL;
vm = virDomainFindByID(&driver->domains, id);
if (!vm) { if (!vm) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
return NULL; goto cleanup;
} }
dom = virGetDomain(conn, vm->def->name, vm->def->uuid); dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id; if (dom) dom->id = vm->def->id;
cleanup:
return dom; return dom;
} }
static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn, static virDomainPtr qemudDomainLookupByUUID(virConnectPtr conn,
const unsigned char *uuid) { const unsigned char *uuid) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, uuid); virDomainObjPtr vm;
virDomainPtr dom; virDomainPtr dom = NULL;
vm = virDomainFindByUUID(&driver->domains, uuid);
if (!vm) { if (!vm) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
return NULL; goto cleanup;
} }
dom = virGetDomain(conn, vm->def->name, vm->def->uuid); dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id; if (dom) dom->id = vm->def->id;
cleanup:
return dom; return dom;
} }
static virDomainPtr qemudDomainLookupByName(virConnectPtr conn, static virDomainPtr qemudDomainLookupByName(virConnectPtr conn,
const char *name) { const char *name) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
virDomainObjPtr vm = virDomainFindByName(&driver->domains, name); virDomainObjPtr vm;
virDomainPtr dom; virDomainPtr dom = NULL;
vm = virDomainFindByName(&driver->domains, name);
if (!vm) { if (!vm) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_DOMAIN, NULL);
return NULL; goto cleanup;
} }
dom = virGetDomain(conn, vm->def->name, vm->def->uuid); dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id; if (dom) dom->id = vm->def->id;
cleanup:
return dom; return dom;
} }
static int qemudGetVersion(virConnectPtr conn, unsigned long *version) { static int qemudGetVersion(virConnectPtr conn, unsigned long *version) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
int ret = -1;
if (qemudExtractVersion(conn, driver) < 0) if (qemudExtractVersion(conn, driver) < 0)
return -1; goto cleanup;
*version = qemu_driver->qemuVersion; *version = qemu_driver->qemuVersion;
return 0; ret = 0;
cleanup:
return ret;
} }
static char * static char *
...@@ -1491,7 +1510,7 @@ qemudGetHostname (virConnectPtr conn) ...@@ -1491,7 +1510,7 @@ qemudGetHostname (virConnectPtr conn)
} }
static int qemudListDomains(virConnectPtr conn, int *ids, int nids) { static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
int got = 0, i; int got = 0, i;
for (i = 0 ; i < driver->domains.count && got < nids ; i++) for (i = 0 ; i < driver->domains.count && got < nids ; i++)
...@@ -1501,7 +1520,7 @@ static int qemudListDomains(virConnectPtr conn, int *ids, int nids) { ...@@ -1501,7 +1520,7 @@ static int qemudListDomains(virConnectPtr conn, int *ids, int nids) {
return got; return got;
} }
static int qemudNumDomains(virConnectPtr conn) { static int qemudNumDomains(virConnectPtr conn) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
int n = 0, i; int n = 0, i;
for (i = 0 ; i < driver->domains.count ; i++) for (i = 0 ; i < driver->domains.count ; i++)
...@@ -1512,21 +1531,20 @@ static int qemudNumDomains(virConnectPtr conn) { ...@@ -1512,21 +1531,20 @@ static int qemudNumDomains(virConnectPtr conn) {
} }
static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
unsigned int flags ATTRIBUTE_UNUSED) { unsigned int flags ATTRIBUTE_UNUSED) {
struct qemud_driver *driver = conn->privateData;
virDomainDefPtr def; virDomainDefPtr def;
virDomainObjPtr vm; virDomainObjPtr vm;
virDomainPtr dom; virDomainPtr dom = NULL;
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
if (!(def = virDomainDefParseString(conn, driver->caps, xml))) if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
return NULL; goto cleanup;
vm = virDomainFindByName(&driver->domains, def->name); vm = virDomainFindByName(&driver->domains, def->name);
if (vm) { if (vm) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("domain '%s' is already defined"), _("domain '%s' is already defined"),
def->name); def->name);
virDomainDefFree(def); goto cleanup;
return NULL;
} }
vm = virDomainFindByUUID(&driver->domains, def->uuid); vm = virDomainFindByUUID(&driver->domains, def->uuid);
if (vm) { if (vm) {
...@@ -1536,21 +1554,20 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, ...@@ -1536,21 +1554,20 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("domain with uuid '%s' is already defined"), _("domain with uuid '%s' is already defined"),
uuidstr); uuidstr);
virDomainDefFree(def); goto cleanup;
return NULL;
} }
if (!(vm = virDomainAssignDef(conn, if (!(vm = virDomainAssignDef(conn,
&driver->domains, &driver->domains,
def))) { def)))
virDomainDefFree(def); goto cleanup;
return NULL;
} def = NULL;
if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0) { if (qemudStartVMDaemon(conn, driver, vm, NULL) < 0) {
virDomainRemoveInactive(&driver->domains, virDomainRemoveInactive(&driver->domains,
vm); vm);
return NULL; goto cleanup;
} }
qemudDomainEventDispatch(driver, vm, qemudDomainEventDispatch(driver, vm,
VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED,
...@@ -1558,30 +1575,35 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, ...@@ -1558,30 +1575,35 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml,
dom = virGetDomain(conn, vm->def->name, vm->def->uuid); dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id; if (dom) dom->id = vm->def->id;
cleanup:
virDomainDefFree(def);
return dom; return dom;
} }
static int qemudDomainSuspend(virDomainPtr dom) { static int qemudDomainSuspend(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
char *info; char *info;
virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); virDomainObjPtr vm;
int ret = -1;
vm = virDomainFindByID(&driver->domains, dom->id);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id); qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, _("no domain with matching id %d"), dom->id);
return -1; goto cleanup;
} }
if (!virDomainIsActive(vm)) { if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running")); "%s", _("domain is not running"));
return -1; goto cleanup;
} }
if (vm->state == VIR_DOMAIN_PAUSED) if (vm->state != VIR_DOMAIN_PAUSED) {
return 0;
if (qemudMonitorCommand(driver, vm, "stop", &info) < 0) { if (qemudMonitorCommand(driver, vm, "stop", &info) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("suspend operation failed")); "%s", _("suspend operation failed"));
return -1; goto cleanup;
} }
vm->state = VIR_DOMAIN_PAUSED; vm->state = VIR_DOMAIN_PAUSED;
qemudDebug("Reply %s", info); qemudDebug("Reply %s", info);
...@@ -1589,30 +1611,36 @@ static int qemudDomainSuspend(virDomainPtr dom) { ...@@ -1589,30 +1611,36 @@ static int qemudDomainSuspend(virDomainPtr dom) {
VIR_DOMAIN_EVENT_SUSPENDED, VIR_DOMAIN_EVENT_SUSPENDED,
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED); VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
VIR_FREE(info); VIR_FREE(info);
return 0; }
ret = 0;
cleanup:
return ret;
} }
static int qemudDomainResume(virDomainPtr dom) { static int qemudDomainResume(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
char *info; char *info;
virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); virDomainObjPtr vm;
int ret = -1;
vm = virDomainFindByID(&driver->domains, dom->id);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id); _("no domain with matching id %d"), dom->id);
return -1; goto cleanup;
} }
if (!virDomainIsActive(vm)) { if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running")); "%s", _("domain is not running"));
return -1; goto cleanup;
} }
if (vm->state == VIR_DOMAIN_RUNNING) if (vm->state == VIR_DOMAIN_PAUSED) {
return 0;
if (qemudMonitorCommand(driver, vm, "cont", &info) < 0) { if (qemudMonitorCommand(driver, vm, "cont", &info) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("resume operation failed")); "%s", _("resume operation failed"));
return -1; goto cleanup;
} }
vm->state = VIR_DOMAIN_RUNNING; vm->state = VIR_DOMAIN_RUNNING;
qemudDebug("Reply %s", info); qemudDebug("Reply %s", info);
...@@ -1620,40 +1648,51 @@ static int qemudDomainResume(virDomainPtr dom) { ...@@ -1620,40 +1648,51 @@ static int qemudDomainResume(virDomainPtr dom) {
VIR_DOMAIN_EVENT_RESUMED, VIR_DOMAIN_EVENT_RESUMED,
VIR_DOMAIN_EVENT_RESUMED_UNPAUSED); VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
VIR_FREE(info); VIR_FREE(info);
return 0; }
ret = 0;
cleanup:
return ret;
} }
static int qemudDomainShutdown(virDomainPtr dom) { static int qemudDomainShutdown(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); virDomainObjPtr vm;
char* info; char* info;
int ret = -1;
vm = virDomainFindByID(&driver->domains, dom->id);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id); _("no domain with matching id %d"), dom->id);
return -1; goto cleanup;
} }
if (qemudMonitorCommand(driver, vm, "system_powerdown", &info) < 0) { if (qemudMonitorCommand(driver, vm, "system_powerdown", &info) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("shutdown operation failed")); "%s", _("shutdown operation failed"));
return -1; goto cleanup;
} }
VIR_FREE(info); VIR_FREE(info);
return 0; ret = 0;
cleanup:
return ret;
} }
static int qemudDomainDestroy(virDomainPtr dom) { static int qemudDomainDestroy(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); virDomainObjPtr vm;
int ret = -1;
vm = virDomainFindByID(&driver->domains, dom->id);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id); _("no domain with matching id %d"), dom->id);
return -1; goto cleanup;
} }
qemudShutdownVMDaemon(dom->conn, driver, vm); qemudShutdownVMDaemon(dom->conn, driver, vm);
...@@ -1663,106 +1702,128 @@ static int qemudDomainDestroy(virDomainPtr dom) { ...@@ -1663,106 +1702,128 @@ static int qemudDomainDestroy(virDomainPtr dom) {
if (!vm->persistent) if (!vm->persistent)
virDomainRemoveInactive(&driver->domains, virDomainRemoveInactive(&driver->domains,
vm); vm);
return 0; ret = 0;
cleanup:
return ret;
} }
static char *qemudDomainGetOSType(virDomainPtr dom) { static char *qemudDomainGetOSType(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
char *type; char *type = NULL;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid")); "%s", _("no domain with matching uuid"));
return NULL; goto cleanup;
} }
if (!(type = strdup(vm->def->os.type))) { if (!(type = strdup(vm->def->os.type)))
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY,
"%s", _("failed to allocate space for ostype")); "%s", _("failed to allocate space for ostype"));
return NULL;
} cleanup:
return type; return type;
} }
/* Returns max memory in kb, 0 if error */ /* Returns max memory in kb, 0 if error */
static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) { static unsigned long qemudDomainGetMaxMemory(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
unsigned long ret = 0;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(dom->uuid, uuidstr); virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr); _("no domain with matching uuid '%s'"), uuidstr);
return 0; goto cleanup;
} }
return vm->def->maxmem; ret = vm->def->maxmem;
cleanup:
return ret;
} }
static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { static int qemudDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(dom->uuid, uuidstr); virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr); _("no domain with matching uuid '%s'"), uuidstr);
return -1; goto cleanup;
} }
if (newmax < vm->def->memory) { if (newmax < vm->def->memory) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("cannot set max memory lower than current memory")); "%s", _("cannot set max memory lower than current memory"));
return -1; goto cleanup;;
} }
vm->def->maxmem = newmax; vm->def->maxmem = newmax;
return 0; ret = 0;
cleanup:
return ret;
} }
static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(dom->uuid, uuidstr); virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr); _("no domain with matching uuid '%s'"), uuidstr);
return -1; goto cleanup;
} }
if (virDomainIsActive(vm)) { if (virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("cannot set memory of an active domain")); "%s", _("cannot set memory of an active domain"));
return -1; goto cleanup;
} }
if (newmem > vm->def->maxmem) { if (newmem > vm->def->maxmem) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("cannot set memory higher than max memory")); "%s", _("cannot set memory higher than max memory"));
return -1; goto cleanup;
} }
vm->def->memory = newmem; vm->def->memory = newmem;
return 0; ret = 0;
cleanup:
return ret;
} }
static int qemudDomainGetInfo(virDomainPtr dom, static int qemudDomainGetInfo(virDomainPtr dom,
virDomainInfoPtr info) { virDomainInfoPtr info) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid")); "%s", _("no domain with matching uuid"));
return -1; goto cleanup;
} }
info->state = vm->state; info->state = vm->state;
...@@ -1772,14 +1833,17 @@ static int qemudDomainGetInfo(virDomainPtr dom, ...@@ -1772,14 +1833,17 @@ static int qemudDomainGetInfo(virDomainPtr dom,
} else { } else {
if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) { if (qemudGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain")); qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, ("cannot read cputime for domain"));
return -1; goto cleanup;
} }
} }
info->maxMem = vm->def->maxmem; info->maxMem = vm->def->maxmem;
info->memory = vm->def->memory; info->memory = vm->def->memory;
info->nrVirtCpu = vm->def->vcpus; info->nrVirtCpu = vm->def->vcpus;
return 0; ret = 0;
cleanup:
return ret;
} }
...@@ -1878,28 +1942,32 @@ struct qemud_save_header { ...@@ -1878,28 +1942,32 @@ struct qemud_save_header {
static int qemudDomainSave(virDomainPtr dom, static int qemudDomainSave(virDomainPtr dom,
const char *path) { const char *path) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); virDomainObjPtr vm;
char *command, *info; char *command = NULL;
int fd; char *info = NULL;
char *safe_path; int fd = -1;
char *xml; char *safe_path = NULL;
char *xml = NULL;
struct qemud_save_header header; struct qemud_save_header header;
int ret = -1;
memset(&header, 0, sizeof(header)); memset(&header, 0, sizeof(header));
memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)); memcpy(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic));
header.version = QEMUD_SAVE_VERSION; header.version = QEMUD_SAVE_VERSION;
vm = virDomainFindByID(&driver->domains, dom->id);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id); _("no domain with matching id %d"), dom->id);
return -1; goto cleanup;
} }
if (!virDomainIsActive(vm)) { if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running")); "%s", _("domain is not running"));
return -1; goto cleanup;
} }
/* Pause */ /* Pause */
...@@ -1908,7 +1976,7 @@ static int qemudDomainSave(virDomainPtr dom, ...@@ -1908,7 +1976,7 @@ static int qemudDomainSave(virDomainPtr dom,
if (qemudDomainSuspend(dom) != 0) { if (qemudDomainSuspend(dom) != 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to pause domain")); "%s", _("failed to pause domain"));
return -1; goto cleanup;
} }
} }
...@@ -1917,7 +1985,7 @@ static int qemudDomainSave(virDomainPtr dom, ...@@ -1917,7 +1985,7 @@ static int qemudDomainSave(virDomainPtr dom,
if (!xml) { if (!xml) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to get domain xml")); "%s", _("failed to get domain xml"));
return -1; goto cleanup;
} }
header.xml_len = strlen(xml) + 1; header.xml_len = strlen(xml) + 1;
...@@ -1925,51 +1993,49 @@ static int qemudDomainSave(virDomainPtr dom, ...@@ -1925,51 +1993,49 @@ static int qemudDomainSave(virDomainPtr dom,
if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) { if ((fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR)) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("failed to create '%s'"), path); _("failed to create '%s'"), path);
VIR_FREE(xml); goto cleanup;
return -1;
} }
if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) { if (safewrite(fd, &header, sizeof(header)) != sizeof(header)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to write save header")); "%s", _("failed to write save header"));
close(fd);
VIR_FREE(xml);
return -1; return -1;
} }
if (safewrite(fd, xml, header.xml_len) != header.xml_len) { if (safewrite(fd, xml, header.xml_len) != header.xml_len) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to write xml")); "%s", _("failed to write xml"));
close(fd); goto cleanup;
VIR_FREE(xml);
return -1;
} }
close(fd); if (close(fd) < 0) {
VIR_FREE(xml); qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("unable to save file %s %s"),
path, strerror(errno));
goto cleanup;
}
fd = -1;
/* Migrate to file */ /* Migrate to file */
safe_path = qemudEscapeShellArg(path); safe_path = qemudEscapeShellArg(path);
if (!safe_path) { if (!safe_path) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("out of memory")); "%s", _("out of memory"));
return -1; goto cleanup;
} }
if (asprintf (&command, "migrate \"exec:" if (asprintf (&command, "migrate \"exec:"
"dd of='%s' oflag=append conv=notrunc 2>/dev/null" "dd of='%s' oflag=append conv=notrunc 2>/dev/null"
"\"", safe_path) == -1) { "\"", safe_path) == -1) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("out of memory")); "%s", _("out of memory"));
VIR_FREE(safe_path); command = NULL;
return -1; goto cleanup;
} }
free(safe_path);
if (qemudMonitorCommand(driver, vm, command, &info) < 0) { if (qemudMonitorCommand(driver, vm, command, &info) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("migrate operation failed")); "%s", _("migrate operation failed"));
VIR_FREE(command); goto cleanup;
return -1;
} }
DEBUG ("migrate reply: %s", info); DEBUG ("migrate reply: %s", info);
...@@ -1980,14 +2046,9 @@ static int qemudDomainSave(virDomainPtr dom, ...@@ -1980,14 +2046,9 @@ static int qemudDomainSave(virDomainPtr dom,
qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", "%s",
_("'migrate' not supported by this qemu")); _("'migrate' not supported by this qemu"));
VIR_FREE(info); goto cleanup;
VIR_FREE(command);
return -1;
} }
VIR_FREE(info);
VIR_FREE(command);
/* Shut it down */ /* Shut it down */
qemudShutdownVMDaemon(dom->conn, driver, vm); qemudShutdownVMDaemon(dom->conn, driver, vm);
qemudDomainEventDispatch(driver, vm, qemudDomainEventDispatch(driver, vm,
...@@ -1996,45 +2057,62 @@ static int qemudDomainSave(virDomainPtr dom, ...@@ -1996,45 +2057,62 @@ static int qemudDomainSave(virDomainPtr dom,
if (!vm->persistent) if (!vm->persistent)
virDomainRemoveInactive(&driver->domains, virDomainRemoveInactive(&driver->domains,
vm); vm);
return 0; ret = 0;
cleanup:
if (fd != -1)
close(fd);
VIR_FREE(xml);
VIR_FREE(safe_path);
VIR_FREE(command);
VIR_FREE(info);
if (ret != 0)
unlink(path);
return ret;
} }
static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
int max; int max;
int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(dom->uuid, uuidstr); virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr); _("no domain with matching uuid '%s'"), uuidstr);
return -1; goto cleanup;
} }
if (virDomainIsActive(vm)) { if (virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s", qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, "%s",
_("cannot change vcpu count of an active domain")); _("cannot change vcpu count of an active domain"));
return -1; goto cleanup;
} }
if ((max = qemudDomainGetMaxVcpus(dom)) < 0) { if ((max = qemudDomainGetMaxVcpus(dom)) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s", qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, "%s",
_("could not determine max vcpus for the domain")); _("could not determine max vcpus for the domain"));
return -1; goto cleanup;
} }
if (nvcpus > max) { if (nvcpus > max) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("requested vcpus is greater than max allowable" _("requested vcpus is greater than max allowable"
" vcpus for the domain: %d > %d"), nvcpus, max); " vcpus for the domain: %d > %d"), nvcpus, max);
return -1; goto cleanup;
} }
vm->def->vcpus = nvcpus; vm->def->vcpus = nvcpus;
return 0; ret = 0;
cleanup:
return ret;
} }
...@@ -2044,27 +2122,29 @@ qemudDomainPinVcpu(virDomainPtr dom, ...@@ -2044,27 +2122,29 @@ qemudDomainPinVcpu(virDomainPtr dom,
unsigned int vcpu, unsigned int vcpu,
unsigned char *cpumap, unsigned char *cpumap,
int maplen) { int maplen) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
cpu_set_t mask; cpu_set_t mask;
int i, maxcpu; int i, maxcpu;
virNodeInfo nodeinfo; virNodeInfo nodeinfo;
int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!virDomainIsActive(vm)) { if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s",_("cannot pin vcpus on an inactive domain")); "%s",_("cannot pin vcpus on an inactive domain"));
return -1; goto cleanup;
} }
if (vcpu > (vm->nvcpupids-1)) { if (vcpu > (vm->nvcpupids-1)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("vcpu number out of range %d > %d"), _("vcpu number out of range %d > %d"),
vcpu, vm->nvcpupids); vcpu, vm->nvcpupids);
return -1; goto cleanup;
} }
if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0) if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
return -1; goto cleanup;
maxcpu = maplen * 8; maxcpu = maplen * 8;
if (maxcpu > nodeinfo.cpus) if (maxcpu > nodeinfo.cpus)
...@@ -2080,15 +2160,17 @@ qemudDomainPinVcpu(virDomainPtr dom, ...@@ -2080,15 +2160,17 @@ qemudDomainPinVcpu(virDomainPtr dom,
if (sched_setaffinity(vm->vcpupids[vcpu], sizeof(mask), &mask) < 0) { if (sched_setaffinity(vm->vcpupids[vcpu], sizeof(mask), &mask) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("cannot set affinity: %s"), strerror(errno)); _("cannot set affinity: %s"), strerror(errno));
return -1; goto cleanup;
} }
} else { } else {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("cpu affinity is not supported")); "%s", _("cpu affinity is not supported"));
return -1; goto cleanup;
} }
ret = 0;
return 0; cleanup:
return ret;
} }
static int static int
...@@ -2097,19 +2179,21 @@ qemudDomainGetVcpus(virDomainPtr dom, ...@@ -2097,19 +2179,21 @@ qemudDomainGetVcpus(virDomainPtr dom,
int maxinfo, int maxinfo,
unsigned char *cpumaps, unsigned char *cpumaps,
int maplen) { int maplen) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
virNodeInfo nodeinfo; virNodeInfo nodeinfo;
int i, v, maxcpu; int i, v, maxcpu;
int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!virDomainIsActive(vm)) { if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s",_("cannot pin vcpus on an inactive domain")); "%s",_("cannot pin vcpus on an inactive domain"));
return -1; goto cleanup;
} }
if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0) if (virNodeInfoPopulate(dom->conn, &nodeinfo) < 0)
return -1; goto cleanup;
maxcpu = maplen * 8; maxcpu = maplen * 8;
if (maxcpu > nodeinfo.cpus) if (maxcpu > nodeinfo.cpus)
...@@ -2119,9 +2203,7 @@ qemudDomainGetVcpus(virDomainPtr dom, ...@@ -2119,9 +2203,7 @@ qemudDomainGetVcpus(virDomainPtr dom,
if (maxinfo > vm->nvcpupids) if (maxinfo > vm->nvcpupids)
maxinfo = vm->nvcpupids; maxinfo = vm->nvcpupids;
if (maxinfo < 1) if (maxinfo >= 1) {
return 0;
if (info != NULL) { if (info != NULL) {
memset(info, 0, sizeof(*info) * maxinfo); memset(info, 0, sizeof(*info) * maxinfo);
for (i = 0 ; i < maxinfo ; i++) { for (i = 0 ; i < maxinfo ; i++) {
...@@ -2142,7 +2224,7 @@ qemudDomainGetVcpus(virDomainPtr dom, ...@@ -2142,7 +2224,7 @@ qemudDomainGetVcpus(virDomainPtr dom,
if (sched_getaffinity(vm->vcpupids[v], sizeof(mask), &mask) < 0) { if (sched_getaffinity(vm->vcpupids[v], sizeof(mask), &mask) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("cannot get affinity: %s"), strerror(errno)); _("cannot get affinity: %s"), strerror(errno));
return -1; goto cleanup;
} }
for (i = 0 ; i < maxcpu ; i++) for (i = 0 ; i < maxcpu ; i++)
...@@ -2152,108 +2234,102 @@ qemudDomainGetVcpus(virDomainPtr dom, ...@@ -2152,108 +2234,102 @@ qemudDomainGetVcpus(virDomainPtr dom,
} else { } else {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("cpu affinity is not available")); "%s", _("cpu affinity is not available"));
return -1; goto cleanup;
}
} }
} }
ret = maxinfo;
return maxinfo; cleanup:
return ret;
} }
#endif /* HAVE_SCHED_GETAFFINITY */ #endif /* HAVE_SCHED_GETAFFINITY */
static int qemudDomainGetMaxVcpus(virDomainPtr dom) { static int qemudDomainGetMaxVcpus(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
const char *type; const char *type;
int ret; int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN]; char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(dom->uuid, uuidstr); virUUIDFormat(dom->uuid, uuidstr);
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr); _("no domain with matching uuid '%s'"), uuidstr);
return -1; goto cleanup;
} }
if (!(type = virDomainVirtTypeToString(vm->def->virtType))) { if (!(type = virDomainVirtTypeToString(vm->def->virtType))) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
_("unknown virt type in domain definition '%d'"), _("unknown virt type in domain definition '%d'"),
vm->def->virtType); vm->def->virtType);
return -1; goto cleanup;
} }
if ((ret = qemudGetMaxVCPUs(dom->conn, type)) < 0) { ret = qemudGetMaxVCPUs(dom->conn, type);
return -1;
}
cleanup:
return ret; return ret;
} }
static int qemudDomainRestore(virConnectPtr conn, static int qemudDomainRestore(virConnectPtr conn,
const char *path) { const char *path) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
virDomainDefPtr def; virDomainDefPtr def = NULL;
virDomainObjPtr vm; virDomainObjPtr vm;
int fd; int fd = -1;
int ret; int ret = -1;
char *xml; char *xml = NULL;
struct qemud_save_header header; struct qemud_save_header header;
/* Verify the header and read the XML */ /* Verify the header and read the XML */
if ((fd = open(path, O_RDONLY)) < 0) { if ((fd = open(path, O_RDONLY)) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("cannot read domain image")); "%s", _("cannot read domain image"));
return -1; goto cleanup;
} }
if (saferead(fd, &header, sizeof(header)) != sizeof(header)) { if (saferead(fd, &header, sizeof(header)) != sizeof(header)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to read qemu header")); "%s", _("failed to read qemu header"));
close(fd); goto cleanup;
return -1;
} }
if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) { if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("image magic is incorrect")); "%s", _("image magic is incorrect"));
close(fd); goto cleanup;
return -1;
} }
if (header.version > QEMUD_SAVE_VERSION) { if (header.version > QEMUD_SAVE_VERSION) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, 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);
close(fd); goto cleanup;
return -1;
} }
if (VIR_ALLOC_N(xml, header.xml_len) < 0) { if (VIR_ALLOC_N(xml, header.xml_len) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("out of memory")); "%s", _("out of memory"));
close(fd); goto cleanup;
return -1;
} }
if (saferead(fd, xml, header.xml_len) != header.xml_len) { if (saferead(fd, xml, header.xml_len) != header.xml_len) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to read XML")); "%s", _("failed to read XML"));
close(fd); goto cleanup;
VIR_FREE(xml);
return -1;
} }
/* Create a domain from this XML */ /* Create a domain from this XML */
if (!(def = virDomainDefParseString(conn, driver->caps, xml))) { if (!(def = virDomainDefParseString(conn, driver->caps, xml))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to parse XML")); "%s", _("failed to parse XML"));
close(fd); goto cleanup;
VIR_FREE(xml);
return -1;
} }
VIR_FREE(xml);
/* Ensure the name and UUID don't already exist in an active VM */ /* Ensure the name and UUID don't already exist in an active VM */
vm = virDomainFindByUUID(&driver->domains, def->uuid); vm = virDomainFindByUUID(&driver->domains, def->uuid);
...@@ -2262,8 +2338,7 @@ static int qemudDomainRestore(virConnectPtr conn, ...@@ -2262,8 +2338,7 @@ static int qemudDomainRestore(virConnectPtr conn,
if (vm && virDomainIsActive(vm)) { if (vm && virDomainIsActive(vm)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("domain is already active as '%s'"), vm->def->name); _("domain is already active as '%s'"), vm->def->name);
close(fd); goto cleanup;
return -1;
} }
if (!(vm = virDomainAssignDef(conn, if (!(vm = virDomainAssignDef(conn,
...@@ -2271,15 +2346,15 @@ static int qemudDomainRestore(virConnectPtr conn, ...@@ -2271,15 +2346,15 @@ static int qemudDomainRestore(virConnectPtr conn,
def))) { def))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to assign new VM")); "%s", _("failed to assign new VM"));
virDomainDefFree(def); goto cleanup;
close(fd);
return -1;
} }
def = NULL;
/* Set the migration source and start it up. */ /* Set the migration source and start it up. */
vm->stdin_fd = fd; vm->stdin_fd = fd;
ret = qemudStartVMDaemon(conn, driver, vm, "stdio"); ret = qemudStartVMDaemon(conn, driver, vm, "stdio");
close(fd); close(fd);
fd = -1;
vm->stdin_fd = -1; vm->stdin_fd = -1;
if (ret < 0) { if (ret < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
...@@ -2287,7 +2362,7 @@ static int qemudDomainRestore(virConnectPtr conn, ...@@ -2287,7 +2362,7 @@ static int qemudDomainRestore(virConnectPtr conn,
if (!vm->persistent) if (!vm->persistent)
virDomainRemoveInactive(&driver->domains, virDomainRemoveInactive(&driver->domains,
vm); vm);
return -1; goto cleanup;
} }
qemudDomainEventDispatch(driver, vm, qemudDomainEventDispatch(driver, vm,
...@@ -2300,36 +2375,49 @@ static int qemudDomainRestore(virConnectPtr conn, ...@@ -2300,36 +2375,49 @@ static int qemudDomainRestore(virConnectPtr conn,
if (qemudMonitorCommand(driver, vm, "cont", &info) < 0) { if (qemudMonitorCommand(driver, vm, "cont", &info) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to resume domain")); "%s", _("failed to resume domain"));
return -1; goto cleanup;
} }
VIR_FREE(info); VIR_FREE(info);
vm->state = VIR_DOMAIN_RUNNING; vm->state = VIR_DOMAIN_RUNNING;
} }
ret = 0;
return 0; cleanup:
virDomainDefFree(def);
VIR_FREE(xml);
if (fd != -1)
close(fd);
return ret;
} }
static char *qemudDomainDumpXML(virDomainPtr dom, static char *qemudDomainDumpXML(virDomainPtr dom,
int flags ATTRIBUTE_UNUSED) { int flags ATTRIBUTE_UNUSED) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
char *ret = NULL;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid")); "%s", _("no domain with matching uuid"));
return NULL; goto cleanup;
} }
return virDomainDefFormat(dom->conn, ret = virDomainDefFormat(dom->conn,
(flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ? (flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
vm->newDef : vm->def, vm->newDef : vm->def,
flags); flags);
cleanup:
return ret;
} }
static int qemudListDefinedDomains(virConnectPtr conn, static int qemudListDefinedDomains(virConnectPtr conn,
char **const names, int nnames) { char **const names, int nnames) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
int got = 0, i; int got = 0, i;
for (i = 0 ; i < driver->domains.count && got < nnames ; i++) { for (i = 0 ; i < driver->domains.count && got < nnames ; i++) {
...@@ -2351,7 +2439,7 @@ static int qemudListDefinedDomains(virConnectPtr conn, ...@@ -2351,7 +2439,7 @@ static int qemudListDefinedDomains(virConnectPtr conn,
} }
static int qemudNumDefinedDomains(virConnectPtr conn) { static int qemudNumDefinedDomains(virConnectPtr conn) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
int n = 0, i; int n = 0, i;
for (i = 0 ; i < driver->domains.count ; i++) for (i = 0 ; i < driver->domains.count ; i++)
...@@ -2363,35 +2451,37 @@ static int qemudNumDefinedDomains(virConnectPtr conn) { ...@@ -2363,35 +2451,37 @@ static int qemudNumDefinedDomains(virConnectPtr conn) {
static int qemudDomainStart(virDomainPtr dom) { static int qemudDomainStart(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
int ret; int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid")); "%s", _("no domain with matching uuid"));
return -1; goto cleanup;
} }
ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL); ret = qemudStartVMDaemon(dom->conn, driver, vm, NULL);
if (ret < 0) if (ret != -1)
return ret;
qemudDomainEventDispatch(driver, vm, qemudDomainEventDispatch(driver, vm,
VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED,
VIR_DOMAIN_EVENT_STARTED_BOOTED); VIR_DOMAIN_EVENT_STARTED_BOOTED);
return 0;
cleanup:
return ret;
} }
static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
virDomainDefPtr def; virDomainDefPtr def;
virDomainObjPtr vm; virDomainObjPtr vm;
virDomainPtr dom; virDomainPtr dom = NULL;
int newVM = 1; int newVM = 1;
if (!(def = virDomainDefParseString(conn, driver->caps, xml))) if (!(def = virDomainDefParseString(conn, driver->caps, xml)))
return NULL; goto cleanup;
vm = virDomainFindByName(&driver->domains, def->name); vm = virDomainFindByName(&driver->domains, def->name);
if (vm) if (vm)
...@@ -2401,7 +2491,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { ...@@ -2401,7 +2491,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
&driver->domains, &driver->domains,
def))) { def))) {
virDomainDefFree(def); virDomainDefFree(def);
return NULL; goto cleanup;
} }
vm->persistent = 1; vm->persistent = 1;
...@@ -2410,7 +2500,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { ...@@ -2410,7 +2500,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
vm->newDef ? vm->newDef : vm->def) < 0) { vm->newDef ? vm->newDef : vm->def) < 0) {
virDomainRemoveInactive(&driver->domains, virDomainRemoveInactive(&driver->domains,
vm); vm);
return NULL; goto cleanup;
} }
qemudDomainEventDispatch(driver, vm, qemudDomainEventDispatch(driver, vm,
...@@ -2421,33 +2511,37 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { ...@@ -2421,33 +2511,37 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
dom = virGetDomain(conn, vm->def->name, vm->def->uuid); dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
if (dom) dom->id = vm->def->id; if (dom) dom->id = vm->def->id;
cleanup:
return dom; return dom;
} }
static int qemudDomainUndefine(virDomainPtr dom) { static int qemudDomainUndefine(virDomainPtr dom) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid")); "%s", _("no domain with matching uuid"));
return -1; goto cleanup;
} }
if (virDomainIsActive(vm)) { if (virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot delete active domain")); "%s", _("cannot delete active domain"));
return -1; goto cleanup;
} }
if (!vm->persistent) { if (!vm->persistent) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot undefine transient domain")); "%s", _("cannot undefine transient domain"));
return -1; goto cleanup;
} }
if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm) < 0) if (virDomainDeleteConfig(dom->conn, driver->configDir, driver->autostartDir, vm) < 0)
return -1; goto cleanup;
qemudDomainEventDispatch(driver, vm, qemudDomainEventDispatch(driver, vm,
VIR_DOMAIN_EVENT_UNDEFINED, VIR_DOMAIN_EVENT_UNDEFINED,
...@@ -2455,12 +2549,14 @@ static int qemudDomainUndefine(virDomainPtr dom) { ...@@ -2455,12 +2549,14 @@ static int qemudDomainUndefine(virDomainPtr dom) {
virDomainRemoveInactive(&driver->domains, virDomainRemoveInactive(&driver->domains,
vm); vm);
ret = 0;
return 0; cleanup:
return ret;
} }
/* Return the disks name for use in monitor commands */ /* Return the disks name for use in monitor commands */
static char *qemudDiskDeviceName(const virDomainPtr dom, static char *qemudDiskDeviceName(const virConnectPtr conn,
const virDomainDiskDefPtr disk) { const virDomainDiskDefPtr disk) {
int busid, devid; int busid, devid;
...@@ -2468,7 +2564,7 @@ static char *qemudDiskDeviceName(const virDomainPtr dom, ...@@ -2468,7 +2564,7 @@ static char *qemudDiskDeviceName(const virDomainPtr dom,
char *devname; char *devname;
if (virDiskNameToBusDeviceIndex(disk, &busid, &devid) < 0) { if (virDiskNameToBusDeviceIndex(disk, &busid, &devid) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("cannot convert disk '%s' to bus/device index"), _("cannot convert disk '%s' to bus/device index"),
disk->dst); disk->dst);
return NULL; return NULL;
...@@ -2494,37 +2590,31 @@ static char *qemudDiskDeviceName(const virDomainPtr dom, ...@@ -2494,37 +2590,31 @@ static char *qemudDiskDeviceName(const virDomainPtr dom,
ret = asprintf(&devname, "virtio%d", devid); ret = asprintf(&devname, "virtio%d", devid);
break; break;
default: default:
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
_("Unsupported disk name mapping for bus '%s'"), _("Unsupported disk name mapping for bus '%s'"),
virDomainDiskBusTypeToString(disk->bus)); virDomainDiskBusTypeToString(disk->bus));
return NULL; return NULL;
} }
if (ret == -1) { if (ret == -1) {
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return NULL; return NULL;
} }
return devname; return devname;
} }
static int qemudDomainChangeEjectableMedia(virDomainPtr dom, static int qemudDomainChangeEjectableMedia(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev) virDomainDeviceDefPtr dev)
{ {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
virDomainDiskDefPtr origdisk = NULL, newdisk; virDomainDiskDefPtr origdisk = NULL, newdisk;
char *cmd, *reply, *safe_path; char *cmd, *reply, *safe_path;
char *devname = NULL; char *devname = NULL;
unsigned int qemuCmdFlags; unsigned int qemuCmdFlags;
int i; int i;
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
return -1;
}
origdisk = NULL; origdisk = NULL;
newdisk = dev->data.disk; newdisk = dev->data.disk;
for (i = 0 ; i < vm->def->ndisks ; i++) { for (i = 0 ; i < vm->def->ndisks ; i++) {
...@@ -2536,7 +2626,7 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom, ...@@ -2536,7 +2626,7 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom,
} }
if (!origdisk) { if (!origdisk) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
_("No device with bus '%s' and target '%s'"), _("No device with bus '%s' and target '%s'"),
virDomainDiskBusTypeToString(newdisk->bus), virDomainDiskBusTypeToString(newdisk->bus),
newdisk->dst); newdisk->dst);
...@@ -2546,14 +2636,14 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom, ...@@ -2546,14 +2636,14 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom,
if (qemudExtractVersionInfo(vm->def->emulator, if (qemudExtractVersionInfo(vm->def->emulator,
NULL, NULL,
&qemuCmdFlags) < 0) { &qemuCmdFlags) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
_("Cannot determine QEMU argv syntax %s"), _("Cannot determine QEMU argv syntax %s"),
vm->def->emulator); vm->def->emulator);
return -1; return -1;
} }
if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) { if (qemuCmdFlags & QEMUD_CMD_FLAG_DRIVE) {
if (!(devname = qemudDiskDeviceName(dom, newdisk))) if (!(devname = qemudDiskDeviceName(conn, newdisk)))
return -1; return -1;
} else { } else {
/* Back compat for no -drive option */ /* Back compat for no -drive option */
...@@ -2563,7 +2653,7 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom, ...@@ -2563,7 +2653,7 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom,
STREQ(newdisk->dst, "hdc")) STREQ(newdisk->dst, "hdc"))
devname = strdup("cdrom"); devname = strdup("cdrom");
else { else {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
_("Emulator version does not support removable " _("Emulator version does not support removable "
"media for device '%s' and target '%s'"), "media for device '%s' and target '%s'"),
virDomainDiskDeviceTypeToString(newdisk->device), virDomainDiskDeviceTypeToString(newdisk->device),
...@@ -2572,7 +2662,7 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom, ...@@ -2572,7 +2662,7 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom,
} }
if (!devname) { if (!devname) {
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return -1; return -1;
} }
} }
...@@ -2580,12 +2670,12 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom, ...@@ -2580,12 +2670,12 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom,
if (newdisk->src) { if (newdisk->src) {
safe_path = qemudEscapeMonitorArg(newdisk->src); safe_path = qemudEscapeMonitorArg(newdisk->src);
if (!safe_path) { if (!safe_path) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL);
VIR_FREE(devname); VIR_FREE(devname);
return -1; return -1;
} }
if (asprintf (&cmd, "change %s \"%s\"", devname, safe_path) == -1) { if (asprintf (&cmd, "change %s \"%s\"", devname, safe_path) == -1) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL);
VIR_FREE(safe_path); VIR_FREE(safe_path);
VIR_FREE(devname); VIR_FREE(devname);
return -1; return -1;
...@@ -2593,14 +2683,14 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom, ...@@ -2593,14 +2683,14 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom,
VIR_FREE(safe_path); VIR_FREE(safe_path);
} else if (asprintf(&cmd, "eject %s", devname) == -1) { } else if (asprintf(&cmd, "eject %s", devname) == -1) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, dom, NULL, VIR_ERR_NO_MEMORY, NULL);
VIR_FREE(devname); VIR_FREE(devname);
return -1; return -1;
} }
VIR_FREE(devname); VIR_FREE(devname);
if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("cannot change cdrom media")); "%s", _("cannot change cdrom media"));
VIR_FREE(cmd); VIR_FREE(cmd);
return -1; return -1;
...@@ -2611,7 +2701,7 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom, ...@@ -2611,7 +2701,7 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom,
* No message is printed on success it seems */ * No message is printed on success it seems */
DEBUG ("ejectable media change reply: %s", reply); DEBUG ("ejectable media change reply: %s", reply);
if (strstr(reply, "\ndevice ")) { if (strstr(reply, "\ndevice ")) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("changing cdrom media failed")); "%s", _("changing cdrom media failed"));
VIR_FREE(reply); VIR_FREE(reply);
VIR_FREE(cmd); VIR_FREE(cmd);
...@@ -2627,37 +2717,32 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom, ...@@ -2627,37 +2717,32 @@ static int qemudDomainChangeEjectableMedia(virDomainPtr dom,
return 0; return 0;
} }
static int qemudDomainAttachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPtr dev) static int qemudDomainAttachPciDiskDevice(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev)
{ {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
int ret, i; int ret, i;
char *cmd, *reply, *s; char *cmd, *reply, *s;
char *safe_path; char *safe_path;
const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus); const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus);
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
return -1;
}
for (i = 0 ; i < vm->def->ndisks ; i++) { for (i = 0 ; i < vm->def->ndisks ; i++) {
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) { if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("target %s already exists"), dev->data.disk->dst); _("target %s already exists"), dev->data.disk->dst);
return -1; return -1;
} }
} }
if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) { if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return -1; return -1;
} }
safe_path = qemudEscapeMonitorArg(dev->data.disk->src); safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
if (!safe_path) { if (!safe_path) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("out of memory")); "%s", _("out of memory"));
return -1; return -1;
} }
...@@ -2666,12 +2751,12 @@ static int qemudDomainAttachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPt ...@@ -2666,12 +2751,12 @@ static int qemudDomainAttachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPt
safe_path, type); safe_path, type);
VIR_FREE(safe_path); VIR_FREE(safe_path);
if (ret == -1) { if (ret == -1) {
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return ret; return ret;
} }
if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("cannot attach %s disk"), type); _("cannot attach %s disk"), type);
VIR_FREE(cmd); VIR_FREE(cmd);
return -1; return -1;
...@@ -2688,7 +2773,7 @@ static int qemudDomainAttachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPt ...@@ -2688,7 +2773,7 @@ static int qemudDomainAttachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPt
if (virStrToLong_i ((const char*)s, &dummy, 10, &dev->data.disk->slotnum) == -1) if (virStrToLong_i ((const char*)s, &dummy, 10, &dev->data.disk->slotnum) == -1)
qemudLog(QEMUD_WARN, "%s", _("Unable to parse slot number\n")); qemudLog(QEMUD_WARN, "%s", _("Unable to parse slot number\n"));
} else { } else {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("adding %s disk failed"), type); _("adding %s disk failed"), type);
VIR_FREE(reply); VIR_FREE(reply);
VIR_FREE(cmd); VIR_FREE(cmd);
...@@ -2704,36 +2789,31 @@ static int qemudDomainAttachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPt ...@@ -2704,36 +2789,31 @@ static int qemudDomainAttachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPt
return 0; return 0;
} }
static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDeviceDefPtr dev) static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev)
{ {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
int ret, i; int ret, i;
char *safe_path; char *safe_path;
char *cmd, *reply; char *cmd, *reply;
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
return -1;
}
for (i = 0 ; i < vm->def->ndisks ; i++) { for (i = 0 ; i < vm->def->ndisks ; i++) {
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) { if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("target %s already exists"), dev->data.disk->dst); _("target %s already exists"), dev->data.disk->dst);
return -1; return -1;
} }
} }
if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) { if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return -1; return -1;
} }
safe_path = qemudEscapeMonitorArg(dev->data.disk->src); safe_path = qemudEscapeMonitorArg(dev->data.disk->src);
if (!safe_path) { if (!safe_path) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("out of memory")); "%s", _("out of memory"));
return -1; return -1;
} }
...@@ -2741,12 +2821,12 @@ static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDevi ...@@ -2741,12 +2821,12 @@ static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDevi
ret = asprintf(&cmd, "usb_add disk:%s", safe_path); ret = asprintf(&cmd, "usb_add disk:%s", safe_path);
VIR_FREE(safe_path); VIR_FREE(safe_path);
if (ret == -1) { if (ret == -1) {
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return ret; return ret;
} }
if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("cannot attach usb disk")); "%s", _("cannot attach usb disk"));
VIR_FREE(cmd); VIR_FREE(cmd);
return -1; return -1;
...@@ -2756,7 +2836,7 @@ static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDevi ...@@ -2756,7 +2836,7 @@ static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDevi
/* If the command failed qemu prints: /* If the command failed qemu prints:
* Could not add ... */ * Could not add ... */
if (strstr(reply, "Could not add ")) { if (strstr(reply, "Could not add ")) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", "%s",
_("adding usb disk failed")); _("adding usb disk failed"));
VIR_FREE(reply); VIR_FREE(reply);
...@@ -2773,20 +2853,16 @@ static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDevi ...@@ -2773,20 +2853,16 @@ static int qemudDomainAttachUsbMassstorageDevice(virDomainPtr dom, virDomainDevi
return 0; return 0;
} }
static int qemudDomainAttachHostDevice(virDomainPtr dom, virDomainDeviceDefPtr dev) static int qemudDomainAttachHostDevice(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev)
{ {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
int ret; int ret;
char *cmd, *reply; char *cmd, *reply;
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
return -1;
}
if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) { if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) {
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return -1; return -1;
} }
...@@ -2800,12 +2876,12 @@ static int qemudDomainAttachHostDevice(virDomainPtr dom, virDomainDeviceDefPtr d ...@@ -2800,12 +2876,12 @@ static int qemudDomainAttachHostDevice(virDomainPtr dom, virDomainDeviceDefPtr d
dev->data.hostdev->source.subsys.usb.device); dev->data.hostdev->source.subsys.usb.device);
} }
if (ret == -1) { if (ret == -1) {
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
return -1; return -1;
} }
if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("cannot attach usb device")); "%s", _("cannot attach usb device"));
VIR_FREE(cmd); VIR_FREE(cmd);
return -1; return -1;
...@@ -2815,7 +2891,7 @@ static int qemudDomainAttachHostDevice(virDomainPtr dom, virDomainDeviceDefPtr d ...@@ -2815,7 +2891,7 @@ static int qemudDomainAttachHostDevice(virDomainPtr dom, virDomainDeviceDefPtr d
/* If the command failed qemu prints: /* If the command failed qemu prints:
* Could not add ... */ * Could not add ... */
if (strstr(reply, "Could not add ")) { if (strstr(reply, "Could not add ")) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", "%s",
_("adding usb device failed")); _("adding usb device failed"));
VIR_FREE(reply); VIR_FREE(reply);
...@@ -2832,79 +2908,74 @@ static int qemudDomainAttachHostDevice(virDomainPtr dom, virDomainDeviceDefPtr d ...@@ -2832,79 +2908,74 @@ static int qemudDomainAttachHostDevice(virDomainPtr dom, virDomainDeviceDefPtr d
static int qemudDomainAttachDevice(virDomainPtr dom, static int qemudDomainAttachDevice(virDomainPtr dom,
const char *xml) { const char *xml) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
virDomainDeviceDefPtr dev; virDomainDeviceDefPtr dev = NULL;
int ret = 0, supported = 0; int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid")); "%s", _("no domain with matching uuid"));
return -1; goto cleanup;
} }
if (!virDomainIsActive(vm)) { if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot attach device on inactive domain")); "%s", _("cannot attach device on inactive domain"));
return -1; goto cleanup;
} }
dev = virDomainDeviceDefParse(dom->conn, dev = virDomainDeviceDefParse(dom->conn,
driver->caps, driver->caps,
vm->def, xml); vm->def, xml);
if (dev == NULL) { if (dev == NULL)
return -1; goto cleanup;
}
if (dev->type == VIR_DOMAIN_DEVICE_DISK) { if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
switch (dev->data.disk->device) { switch (dev->data.disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM: case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY: case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
supported = 1; ret = qemudDomainChangeEjectableMedia(dom->conn, driver, vm, dev);
ret = qemudDomainChangeEjectableMedia(dom, dev);
break; break;
case VIR_DOMAIN_DISK_DEVICE_DISK: case VIR_DOMAIN_DISK_DEVICE_DISK:
if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) { if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_USB) {
supported = 1; ret = qemudDomainAttachUsbMassstorageDevice(dom->conn, driver, vm, dev);
ret = qemudDomainAttachUsbMassstorageDevice(dom, dev);
} else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI || } else if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
supported = 1; ret = qemudDomainAttachPciDiskDevice(dom->conn, driver, vm, dev);
ret = qemudDomainAttachPciDiskDevice(dom, dev);
} }
break; break;
default:
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("this disk device type cannot be attached"));
goto cleanup;
} }
} else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV && } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
supported = 1; ret = qemudDomainAttachHostDevice(dom->conn, driver, vm, dev);
ret = qemudDomainAttachHostDevice(dom, dev); } else {
}
if (!supported) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("this device type cannot be attached")); "%s", _("this device type cannot be attached"));
ret = -1; goto cleanup;
} }
VIR_FREE(dev); cleanup:
virDomainDeviceDefFree(dev);
return ret; return ret;
} }
static int qemudDomainDetachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPtr dev) static int qemudDomainDetachPciDiskDevice(virConnectPtr conn,
struct qemud_driver *driver,
virDomainObjPtr vm, virDomainDeviceDefPtr dev)
{ {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid);
int i, ret = -1; int i, ret = -1;
char *cmd, *reply; char *cmd = NULL;
char *reply = NULL;
virDomainDiskDefPtr detach = NULL; virDomainDiskDefPtr detach = NULL;
if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid"));
return -1;
}
for (i = 0 ; i < vm->def->ndisks ; i++) { for (i = 0 ; i < vm->def->ndisks ; i++) {
if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) { if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
detach = vm->def->disks[i]; detach = vm->def->disks[i];
...@@ -2913,48 +2984,45 @@ static int qemudDomainDetachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPt ...@@ -2913,48 +2984,45 @@ static int qemudDomainDetachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPt
} }
if (!detach) { if (!detach) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("disk %s not found"), dev->data.disk->dst); _("disk %s not found"), dev->data.disk->dst);
return -1; goto cleanup;
} }
if (detach->slotnum < 1) { if (detach->slotnum < 1) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("disk %s cannot be detached - invalid slot number %d"), _("disk %s cannot be detached - invalid slot number %d"),
detach->dst, detach->slotnum); detach->dst, detach->slotnum);
return -1; goto cleanup;
} }
ret = asprintf(&cmd, "pci_del 0 %d", detach->slotnum); if (asprintf(&cmd, "pci_del 0 %d", detach->slotnum) < 0) {
if (ret == -1) { qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); cmd = NULL;
return ret; goto cleanup;
} }
if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) { if (qemudMonitorCommand(driver, vm, cmd, &reply) < 0) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("failed to execute detach disk %s command"), detach->dst); _("failed to execute detach disk %s command"), detach->dst);
VIR_FREE(cmd); goto cleanup;
return -1;
} }
DEBUG ("pci_del reply: %s", reply); DEBUG ("pci_del reply: %s", reply);
/* If the command fails due to a wrong slot qemu prints: invalid slot, /* If the command fails due to a wrong slot qemu prints: invalid slot,
* nothing is printed on success */ * nothing is printed on success */
if (strstr(reply, "invalid slot")) { if (strstr(reply, "invalid slot")) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("failed to detach disk %s: invalid slot %d"), _("failed to detach disk %s: invalid slot %d"),
detach->dst, detach->slotnum); detach->dst, detach->slotnum);
ret = -1; goto cleanup;
goto out;
} }
if (vm->def->ndisks > 1) { if (vm->def->ndisks > 1) {
vm->def->disks[i] = vm->def->disks[--vm->def->ndisks]; vm->def->disks[i] = vm->def->disks[--vm->def->ndisks];
if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks) < 0) { if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks) < 0) {
qemudReportError(dom->conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL); qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, NULL);
ret = -1; goto cleanup;
goto out;
} }
qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks), qsort(vm->def->disks, vm->def->ndisks, sizeof(*vm->def->disks),
virDomainDiskQSort); virDomainDiskQSort);
...@@ -2963,7 +3031,8 @@ static int qemudDomainDetachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPt ...@@ -2963,7 +3031,8 @@ static int qemudDomainDetachPciDiskDevice(virDomainPtr dom, virDomainDeviceDefPt
vm->def->ndisks = 0; vm->def->ndisks = 0;
} }
ret = 0; ret = 0;
out:
cleanup:
VIR_FREE(reply); VIR_FREE(reply);
VIR_FREE(cmd); VIR_FREE(cmd);
return ret; return ret;
...@@ -2971,83 +3040,86 @@ out: ...@@ -2971,83 +3040,86 @@ out:
static int qemudDomainDetachDevice(virDomainPtr dom, static int qemudDomainDetachDevice(virDomainPtr dom,
const char *xml) { const char *xml) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
virDomainDeviceDefPtr dev; virDomainDeviceDefPtr dev = NULL;
int ret = 0; int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid")); "%s", _("no domain with matching uuid"));
return -1; goto cleanup;
} }
if (!virDomainIsActive(vm)) { if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot attach device on inactive domain")); "%s", _("cannot attach device on inactive domain"));
return -1; goto cleanup;
} }
dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml); dev = virDomainDeviceDefParse(dom->conn, driver->caps, vm->def, xml);
if (dev == NULL) { if (dev == NULL)
return -1; goto cleanup;
}
if (dev->type == VIR_DOMAIN_DEVICE_DISK && if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK && dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
(dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI || (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_SCSI ||
dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO)) dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO))
ret = qemudDomainDetachPciDiskDevice(dom, dev); ret = qemudDomainDetachPciDiskDevice(dom->conn, driver, vm, dev);
else { else
qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", _("only SCSI or virtio disk device can be detached dynamically")); "%s", _("only SCSI or virtio disk device can be detached dynamically"));
ret = -1;
}
VIR_FREE(dev); cleanup:
virDomainDeviceDefFree(dev);
return ret; return ret;
} }
static int qemudDomainGetAutostart(virDomainPtr dom, static int qemudDomainGetAutostart(virDomainPtr dom,
int *autostart) { int *autostart) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid")); "%s", _("no domain with matching uuid"));
return -1; goto cleanup;
} }
*autostart = vm->autostart; *autostart = vm->autostart;
ret = 0;
return 0; cleanup:
return ret;
} }
static int qemudDomainSetAutostart(virDomainPtr dom, static int qemudDomainSetAutostart(virDomainPtr dom,
int autostart) { int autostart) {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
char *configFile = NULL, *autostartLink = NULL; char *configFile = NULL, *autostartLink = NULL;
int ret = -1; int ret = -1;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid")); "%s", _("no domain with matching uuid"));
return -1; goto cleanup;
} }
if (!vm->persistent) { if (!vm->persistent) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot set autostart for transient domain")); "%s", _("cannot set autostart for transient domain"));
return -1; goto cleanup;
} }
autostart = (autostart != 0); autostart = (autostart != 0);
if (vm->autostart == autostart) if (vm->autostart != autostart) {
return 0;
if ((configFile = virDomainConfigFile(dom->conn, driver->configDir, vm->def->name)) == NULL) if ((configFile = virDomainConfigFile(dom->conn, driver->configDir, vm->def->name)) == NULL)
goto cleanup; goto cleanup;
if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir, vm->def->name)) == NULL) if ((autostartLink = virDomainConfigFile(dom->conn, driver->autostartDir, vm->def->name)) == NULL)
...@@ -3079,6 +3151,7 @@ static int qemudDomainSetAutostart(virDomainPtr dom, ...@@ -3079,6 +3151,7 @@ static int qemudDomainSetAutostart(virDomainPtr dom,
} }
vm->autostart = autostart; vm->autostart = autostart;
}
ret = 0; ret = 0;
cleanup: cleanup:
...@@ -3097,25 +3170,25 @@ qemudDomainBlockStats (virDomainPtr dom, ...@@ -3097,25 +3170,25 @@ qemudDomainBlockStats (virDomainPtr dom,
const char *path, const char *path,
struct _virDomainBlockStats *stats) struct _virDomainBlockStats *stats)
{ {
struct qemud_driver *driver = struct qemud_driver *driver = dom->conn->privateData;
(struct qemud_driver *)dom->conn->privateData;
char *dummy, *info = NULL; char *dummy, *info = NULL;
const char *p, *eol; const char *p, *eol;
const char *qemu_dev_name = NULL; const char *qemu_dev_name = NULL;
size_t len; size_t len;
int i, ret = -1; int i, ret = -1;
const virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); virDomainObjPtr vm;
virDomainDiskDefPtr disk = NULL; virDomainDiskDefPtr disk = NULL;
vm = virDomainFindByID(&driver->domains, dom->id);
if (!vm) { if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id); _("no domain with matching id %d"), dom->id);
return -1; goto cleanup;
} }
if (!virDomainIsActive (vm)) { if (!virDomainIsActive (vm)) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running")); "%s", _("domain is not running"));
return -1; goto cleanup;
} }
for (i = 0 ; i < vm->def->ndisks ; i++) { for (i = 0 ; i < vm->def->ndisks ; i++) {
...@@ -3128,18 +3201,18 @@ qemudDomainBlockStats (virDomainPtr dom, ...@@ -3128,18 +3201,18 @@ qemudDomainBlockStats (virDomainPtr dom,
if (!disk) { if (!disk) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("invalid path: %s"), path); _("invalid path: %s"), path);
return -1; goto cleanup;
} }
qemu_dev_name = qemudDiskDeviceName(dom, disk); qemu_dev_name = qemudDiskDeviceName(dom->conn, disk);
if (!qemu_dev_name) if (!qemu_dev_name)
return -1; goto cleanup;
len = strlen (qemu_dev_name); len = strlen (qemu_dev_name);
if (qemudMonitorCommand (driver, vm, "info blockstats", &info) < 0) { if (qemudMonitorCommand (driver, vm, "info blockstats", &info) < 0) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("'info blockstats' command failed")); "%s", _("'info blockstats' command failed"));
goto out; goto cleanup;
} }
DEBUG ("info blockstats reply: %s", info); DEBUG ("info blockstats reply: %s", info);
...@@ -3152,7 +3225,7 @@ qemudDomainBlockStats (virDomainPtr dom, ...@@ -3152,7 +3225,7 @@ qemudDomainBlockStats (virDomainPtr dom,
qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", "%s",
_("'info blockstats' not supported by this qemu")); _("'info blockstats' not supported by this qemu"));
goto out; goto cleanup;
} }
stats->rd_req = -1; stats->rd_req = -1;
...@@ -3204,7 +3277,7 @@ qemudDomainBlockStats (virDomainPtr dom, ...@@ -3204,7 +3277,7 @@ qemudDomainBlockStats (virDomainPtr dom,
p++; p++;
} }
ret = 0; ret = 0;
goto out; goto cleanup;
} }
/* Skip to next line. */ /* Skip to next line. */
...@@ -3216,59 +3289,70 @@ qemudDomainBlockStats (virDomainPtr dom, ...@@ -3216,59 +3289,70 @@ qemudDomainBlockStats (virDomainPtr dom,
/* If we reach here then the device was not found. */ /* If we reach here then the device was not found. */
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("device not found: %s (%s)"), path, qemu_dev_name); _("device not found: %s (%s)"), path, qemu_dev_name);
out: cleanup:
VIR_FREE(qemu_dev_name); VIR_FREE(qemu_dev_name);
VIR_FREE(info); VIR_FREE(info);
return ret; return ret;
} }
#ifdef __linux__
static int static int
qemudDomainInterfaceStats (virDomainPtr dom, qemudDomainInterfaceStats (virDomainPtr dom,
const char *path, const char *path,
struct _virDomainInterfaceStats *stats) struct _virDomainInterfaceStats *stats)
{ {
#ifdef __linux__ struct qemud_driver *driver = dom->conn->privateData;
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; virDomainObjPtr vm;
virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id);
int i; int i;
int ret = -1;
vm = virDomainFindByID(&driver->domains, dom->id);
if (!vm) { if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id); _("no domain with matching id %d"), dom->id);
return -1; goto cleanup;
} }
if (!virDomainIsActive(vm)) { if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running")); "%s", _("domain is not running"));
return -1; goto cleanup;
} }
if (!path || path[0] == '\0') { if (!path || path[0] == '\0') {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("NULL or empty path")); "%s", _("NULL or empty path"));
return -1; goto cleanup;
} }
/* Check the path is one of the domain's network interfaces. */ /* Check the path is one of the domain's network interfaces. */
for (i = 0 ; i < vm->def->nnets ; i++) { for (i = 0 ; i < vm->def->nnets ; i++) {
if (vm->def->nets[i]->ifname && if (vm->def->nets[i]->ifname &&
STREQ (vm->def->nets[i]->ifname, path)) STREQ (vm->def->nets[i]->ifname, path)) {
goto ok; ret = 0;
break;
}
} }
if (ret == 0)
ret = linuxDomainInterfaceStats (dom->conn, path, stats);
else
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
_("invalid path, '%s' is not a known interface"), path); _("invalid path, '%s' is not a known interface"), path);
return -1;
ok:
return linuxDomainInterfaceStats (dom->conn, path, stats); cleanup:
return ret;
}
#else #else
static int
qemudDomainInterfaceStats (virDomainPtr dom,
const char *path ATTRIBUTE_UNUSED,
struct _virDomainInterfaceStats *stats ATTRIBUTE_UNUSED)
qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT, qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
"%s", __FUNCTION__); "%s", __FUNCTION__);
return -1; return -1;
#endif
} }
#endif
static int static int
qemudDomainBlockPeek (virDomainPtr dom, qemudDomainBlockPeek (virDomainPtr dom,
...@@ -3277,39 +3361,40 @@ qemudDomainBlockPeek (virDomainPtr dom, ...@@ -3277,39 +3361,40 @@ qemudDomainBlockPeek (virDomainPtr dom,
void *buffer, void *buffer,
unsigned int flags ATTRIBUTE_UNUSED) unsigned int flags ATTRIBUTE_UNUSED)
{ {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByUUID(&driver->domains, dom->uuid); virDomainObjPtr vm;
int fd, ret = -1, i; int fd = -1, ret = -1, i;
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) { if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
"%s", _("no domain with matching uuid")); "%s", _("no domain with matching uuid"));
return -1; goto cleanup;
} }
if (!path || path[0] == '\0') { if (!path || path[0] == '\0') {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG, qemudReportError(dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("NULL or empty path")); "%s", _("NULL or empty path"));
return -1; goto cleanup;
} }
/* Check the path belongs to this domain. */ /* Check the path belongs to this domain. */
for (i = 0 ; i < vm->def->ndisks ; i++) { for (i = 0 ; i < vm->def->ndisks ; i++) {
if (vm->def->disks[i]->src != NULL && if (vm->def->disks[i]->src != NULL &&
STREQ (vm->def->disks[i]->src, path)) STREQ (vm->def->disks[i]->src, path)) {
goto found; ret = 0;
break;
}
} }
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("invalid path"));
return -1;
found: if (ret == 0) {
ret = -1;
/* The path is correct, now try to open it and get its size. */ /* The path is correct, now try to open it and get its size. */
fd = open (path, O_RDONLY); fd = open (path, O_RDONLY);
if (fd == -1) { if (fd == -1) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR,
"%s", strerror (errno)); "%s", strerror (errno));
goto done; goto cleanup;
} }
/* Seek and read. */ /* Seek and read. */
...@@ -3320,12 +3405,18 @@ found: ...@@ -3320,12 +3405,18 @@ found:
saferead (fd, buffer, size) == (ssize_t) -1) { saferead (fd, buffer, size) == (ssize_t) -1) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR,
"%s", strerror (errno)); "%s", strerror (errno));
goto done; goto cleanup;
} }
ret = 0; ret = 0;
done: } else {
if (fd >= 0) close (fd); qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("invalid path"));
}
cleanup:
if (fd >= 0)
close (fd);
return ret; return ret;
} }
...@@ -3335,35 +3426,37 @@ qemudDomainMemoryPeek (virDomainPtr dom, ...@@ -3335,35 +3426,37 @@ qemudDomainMemoryPeek (virDomainPtr dom,
void *buffer, void *buffer,
unsigned int flags) unsigned int flags)
{ {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); virDomainObjPtr vm;
char cmd[256], *info; char cmd[256], *info = NULL;
char tmp[] = TEMPDIR "/qemu.mem.XXXXXX"; char tmp[] = TEMPDIR "/qemu.mem.XXXXXX";
int fd = -1, ret = -1; int fd = -1, ret = -1;
if (flags != VIR_MEMORY_VIRTUAL) { vm = virDomainFindByID(&driver->domains, dom->id);
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("QEMU driver only supports virtual memory addrs"));
return -1;
}
if (!vm) { if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id); _("no domain with matching id %d"), dom->id);
return -1; goto cleanup;
}
if (flags != VIR_MEMORY_VIRTUAL) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
"%s", _("QEMU driver only supports virtual memory addrs"));
goto cleanup;
} }
if (!virDomainIsActive(vm)) { if (!virDomainIsActive(vm)) {
qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running")); "%s", _("domain is not running"));
return -1; goto cleanup;
} }
/* Create a temporary filename. */ /* Create a temporary filename. */
if ((fd = mkstemp (tmp)) == -1) { if ((fd = mkstemp (tmp)) == -1) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR,
"%s", strerror (errno)); "%s", strerror (errno));
return -1; goto cleanup;
} }
/* Issue the memsave command. */ /* Issue the memsave command. */
...@@ -3371,21 +3464,22 @@ qemudDomainMemoryPeek (virDomainPtr dom, ...@@ -3371,21 +3464,22 @@ qemudDomainMemoryPeek (virDomainPtr dom,
if (qemudMonitorCommand (driver, vm, cmd, &info) < 0) { if (qemudMonitorCommand (driver, vm, cmd, &info) < 0) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("'memsave' command failed")); "%s", _("'memsave' command failed"));
goto done; goto cleanup;
} }
DEBUG ("memsave reply: %s", info); DEBUG ("memsave reply: %s", info);
free (info);
/* Read the memory file into buffer. */ /* Read the memory file into buffer. */
if (saferead (fd, buffer, size) == (ssize_t) -1) { if (saferead (fd, buffer, size) == (ssize_t) -1) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR,
"%s", strerror (errno)); "%s", strerror (errno));
goto done; goto cleanup;
} }
ret = 0; ret = 0;
done:
cleanup:
VIR_FREE(info);
if (fd >= 0) close (fd); if (fd >= 0) close (fd);
unlink (tmp); unlink (tmp);
return ret; return ret;
...@@ -3398,20 +3492,26 @@ qemudDomainEventRegister (virConnectPtr conn, ...@@ -3398,20 +3492,26 @@ qemudDomainEventRegister (virConnectPtr conn,
void *opaque, void *opaque,
virFreeCallback freecb) virFreeCallback freecb)
{ {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
int ret;
return virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks, ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
callback, opaque, freecb); callback, opaque, freecb);
return ret;
} }
static int static int
qemudDomainEventDeregister (virConnectPtr conn, qemudDomainEventDeregister (virConnectPtr conn,
void *callback) void *callback)
{ {
struct qemud_driver *driver = (struct qemud_driver *)conn->privateData; struct qemud_driver *driver = conn->privateData;
int ret;
return virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks, ret = virDomainEventCallbackListRemove(conn, driver->domainEventCallbacks,
callback); callback);
return ret;
} }
static void qemudDomainEventDispatch (struct qemud_driver *driver, static void qemudDomainEventDispatch (struct qemud_driver *driver,
...@@ -3462,18 +3562,21 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ...@@ -3462,18 +3562,21 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
const char *dom_xml) const char *dom_xml)
{ {
static int port = 0; static int port = 0;
struct qemud_driver *driver = (struct qemud_driver *)dconn->privateData; struct qemud_driver *driver = dconn->privateData;
virDomainDefPtr def; virDomainDefPtr def = NULL;
virDomainObjPtr vm = NULL; virDomainObjPtr vm = NULL;
int this_port; int this_port;
char hostname [HOST_NAME_MAX+1]; char hostname [HOST_NAME_MAX+1];
char migrateFrom [64]; char migrateFrom [64];
const char *p; const char *p;
int ret = -1;;
*uri_out = NULL;
if (!dom_xml) { if (!dom_xml) {
qemudReportError (dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, qemudReportError (dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("no domain XML passed")); "%s", _("no domain XML passed"));
return -1; goto cleanup;
} }
/* The URI passed in may be NULL or a string "tcp://somehostname:port". /* The URI passed in may be NULL or a string "tcp://somehostname:port".
...@@ -3494,14 +3597,15 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ...@@ -3494,14 +3597,15 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
if (gethostname (hostname, HOST_NAME_MAX+1) == -1) { if (gethostname (hostname, HOST_NAME_MAX+1) == -1) {
qemudReportError (dconn, NULL, NULL, VIR_ERR_SYSTEM_ERROR, qemudReportError (dconn, NULL, NULL, VIR_ERR_SYSTEM_ERROR,
"%s", strerror (errno)); "%s", strerror (errno));
return -1; goto cleanup;
} }
/* Caller frees */ /* Caller frees */
if (asprintf(uri_out, "tcp:%s:%d", hostname, this_port) < 0) { if (asprintf(uri_out, "tcp:%s:%d", hostname, this_port) < 0) {
qemudReportError (dconn, NULL, NULL, VIR_ERR_NO_MEMORY, qemudReportError (dconn, NULL, NULL, VIR_ERR_NO_MEMORY,
"%s", strerror (errno)); "%s", strerror (errno));
return -1; *uri_out = NULL;
goto cleanup;
} }
} else { } else {
/* Check the URI starts with "tcp:". We will escape the /* Check the URI starts with "tcp:". We will escape the
...@@ -3511,7 +3615,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ...@@ -3511,7 +3615,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
if (!STREQLEN (uri_in, "tcp:", 6)) { if (!STREQLEN (uri_in, "tcp:", 6)) {
qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_ARG, qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_ARG,
"%s", _("only tcp URIs are supported for KVM migrations")); "%s", _("only tcp URIs are supported for KVM migrations"));
return -1; goto cleanup;
} }
/* Get the port number. */ /* Get the port number. */
...@@ -3521,7 +3625,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ...@@ -3521,7 +3625,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
if (this_port == -1 || p-uri_in != strlen (uri_in)) { if (this_port == -1 || p-uri_in != strlen (uri_in)) {
qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_ARG, qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_ARG,
"%s", _("URI did not have ':port' at the end")); "%s", _("URI did not have ':port' at the end"));
return -1; goto cleanup;
} }
} }
...@@ -3529,7 +3633,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ...@@ -3529,7 +3633,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
if (!(def = virDomainDefParseString(dconn, driver->caps, dom_xml))) { if (!(def = virDomainDefParseString(dconn, driver->caps, dom_xml))) {
qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to parse XML")); "%s", _("failed to parse XML"));
return -1; goto cleanup;
} }
/* Target domain name, maybe renamed. */ /* Target domain name, maybe renamed. */
...@@ -3546,6 +3650,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ...@@ -3546,6 +3650,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
if (virUUIDGenerate (def->uuid) == -1) { if (virUUIDGenerate (def->uuid) == -1) {
qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("could not generate random UUID")); _("could not generate random UUID"));
goto cleanup;
} }
#endif #endif
...@@ -3555,8 +3660,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ...@@ -3555,8 +3660,7 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
_("domain with the same name or UUID already exists as '%s'"), _("domain with the same name or UUID already exists as '%s'"),
vm->def->name); vm->def->name);
virDomainDefFree(def); goto cleanup;
return -1;
} }
} }
...@@ -3565,9 +3669,9 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ...@@ -3565,9 +3669,9 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
def))) { def))) {
qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (dconn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("failed to assign new VM")); "%s", _("failed to assign new VM"));
virDomainDefFree(def); goto cleanup;
return -1;
} }
def = NULL;
/* Domain starts inactive, even if the domain XML had an id field. */ /* Domain starts inactive, even if the domain XML had an id field. */
vm->def->id = -1; vm->def->id = -1;
...@@ -3582,13 +3686,20 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn, ...@@ -3582,13 +3686,20 @@ qemudDomainMigratePrepare2 (virConnectPtr dconn,
if (!vm->persistent) if (!vm->persistent)
virDomainRemoveInactive(&driver->domains, vm); virDomainRemoveInactive(&driver->domains, vm);
return -1; goto cleanup;
} }
qemudDomainEventDispatch(driver, vm, qemudDomainEventDispatch(driver, vm,
VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED,
VIR_DOMAIN_EVENT_STARTED_MIGRATED); VIR_DOMAIN_EVENT_STARTED_MIGRATED);
ret = 0;
return 0; cleanup:
virDomainDefFree(def);
if (ret != 0) {
VIR_FREE(*uri_out);
}
return ret;
} }
/* Perform is the second step, and it runs on the source host. */ /* Perform is the second step, and it runs on the source host. */
...@@ -3601,22 +3712,24 @@ qemudDomainMigratePerform (virDomainPtr dom, ...@@ -3601,22 +3712,24 @@ qemudDomainMigratePerform (virDomainPtr dom,
const char *dname ATTRIBUTE_UNUSED, const char *dname ATTRIBUTE_UNUSED,
unsigned long resource) unsigned long resource)
{ {
struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm = virDomainFindByID(&driver->domains, dom->id); virDomainObjPtr vm;
char *safe_uri; char *safe_uri;
char cmd[HOST_NAME_MAX+50]; char cmd[HOST_NAME_MAX+50];
char *info; char *info = NULL;
int ret = -1;
vm = virDomainFindByID(&driver->domains, dom->id);
if (!vm) { if (!vm) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching id %d"), dom->id); _("no domain with matching id %d"), dom->id);
return -1; goto cleanup;
} }
if (!virDomainIsActive(vm)) { if (!virDomainIsActive(vm)) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("domain is not running")); "%s", _("domain is not running"));
return -1; goto cleanup;
} }
if (!(flags & VIR_MIGRATE_LIVE)) { if (!(flags & VIR_MIGRATE_LIVE)) {
...@@ -3645,7 +3758,7 @@ qemudDomainMigratePerform (virDomainPtr dom, ...@@ -3645,7 +3758,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
if (!safe_uri) { if (!safe_uri) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR, qemudReportError (dom->conn, dom, NULL, VIR_ERR_SYSTEM_ERROR,
"%s", strerror (errno)); "%s", strerror (errno));
return -1; goto cleanup;
} }
snprintf (cmd, sizeof cmd, "migrate \"%s\"", safe_uri); snprintf (cmd, sizeof cmd, "migrate \"%s\"", safe_uri);
VIR_FREE (safe_uri); VIR_FREE (safe_uri);
...@@ -3653,7 +3766,7 @@ qemudDomainMigratePerform (virDomainPtr dom, ...@@ -3653,7 +3766,7 @@ qemudDomainMigratePerform (virDomainPtr dom,
if (qemudMonitorCommand (driver, vm, cmd, &info) < 0) { if (qemudMonitorCommand (driver, vm, cmd, &info) < 0) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
"%s", _("migrate operation failed")); "%s", _("migrate operation failed"));
return -1; goto cleanup;
} }
DEBUG ("migrate reply: %s", info); DEBUG ("migrate reply: %s", info);
...@@ -3662,12 +3775,9 @@ qemudDomainMigratePerform (virDomainPtr dom, ...@@ -3662,12 +3775,9 @@ qemudDomainMigratePerform (virDomainPtr dom,
if (strstr(info, "fail") != NULL) { if (strstr(info, "fail") != NULL) {
qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
_("migrate failed: %s"), info); _("migrate failed: %s"), info);
VIR_FREE(info); goto cleanup;
return -1;
} }
VIR_FREE (info);
/* Clean up the source domain. */ /* Clean up the source domain. */
qemudShutdownVMDaemon (dom->conn, driver, vm); qemudShutdownVMDaemon (dom->conn, driver, vm);
qemudDomainEventDispatch(driver, vm, qemudDomainEventDispatch(driver, vm,
...@@ -3675,8 +3785,11 @@ qemudDomainMigratePerform (virDomainPtr dom, ...@@ -3675,8 +3785,11 @@ qemudDomainMigratePerform (virDomainPtr dom,
VIR_DOMAIN_EVENT_STOPPED_MIGRATED); VIR_DOMAIN_EVENT_STOPPED_MIGRATED);
if (!vm->persistent) if (!vm->persistent)
virDomainRemoveInactive(&driver->domains, vm); virDomainRemoveInactive(&driver->domains, vm);
ret = 0;
return 0; cleanup:
VIR_FREE(info);
return ret;
} }
/* Finish is the third and final step, and it runs on the destination host. */ /* Finish is the third and final step, and it runs on the destination host. */
...@@ -3689,15 +3802,16 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn, ...@@ -3689,15 +3802,16 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
unsigned long flags ATTRIBUTE_UNUSED, unsigned long flags ATTRIBUTE_UNUSED,
int retcode) int retcode)
{ {
struct qemud_driver *driver = (struct qemud_driver *)dconn->privateData; struct qemud_driver *driver = dconn->privateData;
virDomainObjPtr vm = virDomainFindByName(&driver->domains, dname); virDomainObjPtr vm;
virDomainPtr dom; virDomainPtr dom = NULL;
char *info = NULL; char *info = NULL;
vm = virDomainFindByName(&driver->domains, dname);
if (!vm) { if (!vm) {
qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_DOMAIN, qemudReportError (dconn, NULL, NULL, VIR_ERR_INVALID_DOMAIN,
_("no domain with matching name %s"), dname); _("no domain with matching name %s"), dname);
return NULL; goto cleanup;
} }
/* Did the migration go as planned? If yes, return the domain /* Did the migration go as planned? If yes, return the domain
...@@ -3710,7 +3824,6 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn, ...@@ -3710,7 +3824,6 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
qemudDomainEventDispatch(driver, vm, qemudDomainEventDispatch(driver, vm,
VIR_DOMAIN_EVENT_RESUMED, VIR_DOMAIN_EVENT_RESUMED,
VIR_DOMAIN_EVENT_RESUMED_MIGRATED); VIR_DOMAIN_EVENT_RESUMED_MIGRATED);
return dom;
} else { } else {
qemudShutdownVMDaemon (dconn, driver, vm); qemudShutdownVMDaemon (dconn, driver, vm);
qemudDomainEventDispatch(driver, vm, qemudDomainEventDispatch(driver, vm,
...@@ -3718,8 +3831,10 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn, ...@@ -3718,8 +3831,10 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
VIR_DOMAIN_EVENT_STOPPED_FAILED); VIR_DOMAIN_EVENT_STOPPED_FAILED);
if (!vm->persistent) if (!vm->persistent)
virDomainRemoveInactive(&driver->domains, vm); virDomainRemoveInactive(&driver->domains, vm);
return NULL;
} }
cleanup:
return dom;
} }
static virDriver qemuDriver = { static virDriver qemuDriver = {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册