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

Implement virDomainUpdateDeviceFlags API in all drivers with media change

To allow the new virDomainUpdateDeviceFlags() API to be universally
used with all drivers, this patch adds an impl to all the current
drivers which support CDROM or Floppy disk media change via the
current virDomainAttachDeviceFlags API

* src/qemu/qemu_driver.c, src/vbox/vbox_tmpl.c,
  src/xen/proxy_internal.c, src/xen/xen_driver.c,
  src/xen/xend_internal.c: Implement media change via the
  virDomainUpdateDeviceFlags API
* src/xen/xen_driver.h, src/xen/xen_hypervisor.c,
  src/xen/xen_inotify.c, src/xen/xm_internal.c,
  src/xen/xs_internal.c: Stubs for Xen driver entry points
上级 ee9083ab
......@@ -7045,6 +7045,121 @@ static int qemudDomainAttachDeviceFlags(virDomainPtr dom,
return qemudDomainAttachDevice(dom, xml);
}
static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
const char *xml,
unsigned int flags)
{
struct qemud_driver *driver = dom->conn->privateData;
virDomainObjPtr vm;
virDomainDeviceDefPtr dev = NULL;
unsigned long long qemuCmdFlags;
virCgroupPtr cgroup = NULL;
int ret = -1;
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("cannot modify the persistent configuration of a domain"));
return -1;
}
qemuDriverLock(driver);
vm = virDomainFindByUUID(&driver->domains, dom->uuid);
if (!vm) {
char uuidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(dom->uuid, uuidstr);
qemuReportError(VIR_ERR_NO_DOMAIN,
_("no domain with matching uuid '%s'"), uuidstr);
goto cleanup;
}
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
goto cleanup;
if (!virDomainObjIsActive(vm)) {
qemuReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("cannot attach device on inactive domain"));
goto endjob;
}
dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
VIR_DOMAIN_XML_INACTIVE);
if (dev == NULL)
goto endjob;
if (qemudExtractVersionInfo(vm->def->emulator,
NULL,
&qemuCmdFlags) < 0)
goto endjob;
switch (dev->type) {
case VIR_DOMAIN_DEVICE_DISK:
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) !=0 ) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s\n"),
vm->def->name);
goto endjob;
}
if (dev->data.disk->src != NULL &&
dev->data.disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
virCgroupAllowDevicePath(cgroup,
dev->data.disk->src) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("unable to allow device %s"),
dev->data.disk->src);
goto endjob;
}
}
switch (dev->data.disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
ret = qemudDomainChangeEjectableMedia(driver, vm, dev->data.disk);
if (ret == 0)
dev->data.disk = NULL;
break;
default:
qemuReportError(VIR_ERR_NO_SUPPORT,
_("disk bus '%s' cannot be updated."),
virDomainDiskBusTypeToString(dev->data.disk->bus));
break;
}
if (ret != 0 && cgroup) {
virCgroupDenyDevicePath(cgroup,
dev->data.disk->src);
}
break;
default:
qemuReportError(VIR_ERR_NO_SUPPORT,
_("disk device type '%s' cannot be updated"),
virDomainDiskDeviceTypeToString(dev->data.disk->device));
break;
}
if (!ret && virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
ret = -1;
endjob:
if (qemuDomainObjEndJob(vm) == 0)
vm = NULL;
cleanup:
if (cgroup)
virCgroupFree(&cgroup);
virDomainDeviceDefFree(dev);
if (vm)
virDomainObjUnlock(vm);
qemuDriverUnlock(driver);
return ret;
}
static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev,
......@@ -9914,7 +10029,7 @@ static virDriver qemuDriver = {
qemudDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
qemudDomainDetachDevice, /* domainDetachDevice */
qemudDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
qemuDomainUpdateDeviceFlags, /* domainUpdateDeviceFlags */
qemudDomainGetAutostart, /* domainGetAutostart */
qemudDomainSetAutostart, /* domainSetAutostart */
qemuGetSchedulerType, /* domainGetSchedulerType */
......
......@@ -4642,7 +4642,9 @@ cleanup:
return ret;
}
static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) {
static int vboxDomainAttachDeviceImpl(virDomainPtr dom,
const char *xml,
int mediaChangeOnly ATTRIBUTE_UNUSED) {
VBOX_OBJECT_CHECK(dom->conn, int, -1);
IMachine *machine = NULL;
vboxIID *iid = NULL;
......@@ -4842,6 +4844,10 @@ cleanup:
return ret;
}
static int vboxDomainAttachDevice(virDomainPtr dom, const char *xml) {
return vboxDomainAttachDeviceImpl(dom, xml, 0);
}
static int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
unsigned int flags) {
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
......@@ -4850,7 +4856,18 @@ static int vboxDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
return -1;
}
return vboxDomainAttachDevice(dom, xml);
return vboxDomainAttachDeviceImpl(dom, xml, 0);
}
static int vboxDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
unsigned int flags) {
if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
vboxError(dom->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("cannot modify the persistent configuration of a domain"));
return -1;
}
return vboxDomainAttachDeviceImpl(dom, xml, 1);
}
static int vboxDomainDetachDevice(virDomainPtr dom, const char *xml) {
......@@ -7126,7 +7143,7 @@ virDriver NAME(Driver) = {
vboxDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
vboxDomainDetachDevice, /* domainDetachDevice */
vboxDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
vboxDomainUpdateDeviceFlags, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
......
......@@ -78,6 +78,7 @@ struct xenUnifiedDriver xenProxyDriver = {
NULL, /* domainUndefine */
NULL, /* domainAttachDeviceFlags */
NULL, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
......
......@@ -1488,6 +1488,21 @@ xenUnifiedDomainDetachDeviceFlags (virDomainPtr dom, const char *xml,
return -1;
}
static int
xenUnifiedDomainUpdateDeviceFlags (virDomainPtr dom, const char *xml,
unsigned int flags)
{
GET_PRIVATE(dom->conn);
int i;
for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
if (priv->opened[i] && drivers[i]->domainUpdateDeviceFlags &&
drivers[i]->domainUpdateDeviceFlags(dom, xml, flags) == 0)
return 0;
return -1;
}
static int
xenUnifiedDomainGetAutostart (virDomainPtr dom, int *autostart)
{
......@@ -1930,7 +1945,7 @@ static virDriver xenUnifiedDriver = {
xenUnifiedDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
xenUnifiedDomainDetachDevice, /* domainDetachDevice */
xenUnifiedDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
xenUnifiedDomainUpdateDeviceFlags, /* domainUpdateDeviceFlags */
xenUnifiedDomainGetAutostart, /* domainGetAutostart */
xenUnifiedDomainSetAutostart, /* domainSetAutostart */
xenUnifiedDomainGetSchedulerType, /* domainGetSchedulerType */
......
......@@ -95,6 +95,7 @@ struct xenUnifiedDriver {
virDrvDomainUndefine domainUndefine;
virDrvDomainAttachDeviceFlags domainAttachDeviceFlags;
virDrvDomainDetachDeviceFlags domainDetachDeviceFlags;
virDrvDomainUpdateDeviceFlags domainUpdateDeviceFlags;
virDrvDomainGetAutostart domainGetAutostart;
virDrvDomainSetAutostart domainSetAutostart;
virDrvDomainGetSchedulerType domainGetSchedulerType;
......
......@@ -795,6 +795,7 @@ struct xenUnifiedDriver xenHypervisorDriver = {
NULL, /* domainUndefine */
NULL, /* domainAttachDeviceFlags */
NULL, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
xenHypervisorGetSchedulerType, /* domainGetSchedulerType */
......
......@@ -82,6 +82,7 @@ struct xenUnifiedDriver xenInotifyDriver = {
NULL, /* domainUndefine */
NULL, /* domainAttachDeviceFlags */
NULL, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
......
......@@ -4128,7 +4128,7 @@ xenDaemonAttachDeviceFlags(virDomainPtr domain, const char *xml,
if (priv->xendConfigVersion < 3) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("Xend version does not support modifying "
"persisted config"));
"persistent config"));
return -1;
}
/* Cannot modify live config if domain is inactive */
......@@ -4144,17 +4144,17 @@ xenDaemonAttachDeviceFlags(virDomainPtr domain, const char *xml,
flags != VIR_DOMAIN_DEVICE_MODIFY_LIVE)) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("Xend version does not support modifying "
"persisted config"));
"persistent config"));
return -1;
}
/* Xen only supports modifying both live and persisted config if
/* Xen only supports modifying both live and persistent config if
* xendConfigVersion >= 3
*/
if (flags != (VIR_DOMAIN_DEVICE_MODIFY_LIVE |
VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("Xend only supports modifying both live and "
"persisted config"));
"persistent config"));
return -1;
}
}
......@@ -4229,6 +4229,119 @@ cleanup:
return ret;
}
/**
* xenDaemonUpdateDeviceFlags:
* @domain: pointer to domain object
* @xml: pointer to XML description of device
* @flags: an OR'ed set of virDomainDeviceModifyFlags
*
* Create a virtual device attachment to backend.
* XML description is translated into S-expression.
*
* Returns 0 in case of success, -1 in case of failure.
*/
static int
xenDaemonUpdateDeviceFlags(virDomainPtr domain, const char *xml,
unsigned int flags)
{
xenUnifiedPrivatePtr priv;
char *sexpr = NULL;
int ret = -1;
virDomainDeviceDefPtr dev = NULL;
virDomainDefPtr def = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
char class[8], ref[80];
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
virXendError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
__FUNCTION__);
return -1;
}
priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
if (domain->id < 0) {
/* If xendConfigVersion < 3 only live config can be changed */
if (priv->xendConfigVersion < 3) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("Xend version does not support modifying "
"persistent config"));
return -1;
}
/* Cannot modify live config if domain is inactive */
if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("Cannot modify live config if domain is inactive"));
return -1;
}
} else {
/* Only live config can be changed if xendConfigVersion < 3 */
if (priv->xendConfigVersion < 3 &&
(flags != VIR_DOMAIN_DEVICE_MODIFY_CURRENT ||
flags != VIR_DOMAIN_DEVICE_MODIFY_LIVE)) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("Xend version does not support modifying "
"persistent config"));
return -1;
}
/* Xen only supports modifying both live and persistent config if
* xendConfigVersion >= 3
*/
if (flags != (VIR_DOMAIN_DEVICE_MODIFY_LIVE |
VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("Xend only supports modifying both live and "
"persistent config"));
return -1;
}
}
if (!(def = xenDaemonDomainFetch(domain->conn,
domain->id,
domain->name,
NULL)))
goto cleanup;
if (!(dev = virDomainDeviceDefParse(priv->caps,
def, xml, VIR_DOMAIN_XML_INACTIVE)))
goto cleanup;
switch (dev->type) {
case VIR_DOMAIN_DEVICE_DISK:
if (xenDaemonFormatSxprDisk(domain->conn,
dev->data.disk,
&buf,
STREQ(def->os.type, "hvm") ? 1 : 0,
priv->xendConfigVersion, 1) < 0)
goto cleanup;
break;
default:
virXendError(domain->conn, VIR_ERR_NO_SUPPORT, "%s",
_("unsupported device type"));
goto cleanup;
}
sexpr = virBufferContentAndReset(&buf);
if (virDomainXMLDevID(domain, dev, class, ref, sizeof(ref))) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("requested device does not exist"));
goto cleanup;
} else {
/* device exists, attempt to modify it */
ret = xend_op(domain->conn, domain->name, "op", "device_configure",
"config", sexpr, "dev", ref, NULL);
}
cleanup:
VIR_FREE(sexpr);
virDomainDefFree(def);
virDomainDeviceDefFree(dev);
return ret;
}
/**
* xenDaemonDetachDeviceFlags:
* @domain: pointer to domain object
......@@ -4264,7 +4377,7 @@ xenDaemonDetachDeviceFlags(virDomainPtr domain, const char *xml,
if (priv->xendConfigVersion < 3) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("Xend version does not support modifying "
"persisted config"));
"persistent config"));
return -1;
}
/* Cannot modify live config if domain is inactive */
......@@ -4280,17 +4393,17 @@ xenDaemonDetachDeviceFlags(virDomainPtr domain, const char *xml,
flags != VIR_DOMAIN_DEVICE_MODIFY_LIVE)) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("Xend version does not support modifying "
"persisted config"));
"persistent config"));
return -1;
}
/* Xen only supports modifying both live and persisted config if
/* Xen only supports modifying both live and persistent config if
* xendConfigVersion >= 3
*/
if (flags != (VIR_DOMAIN_DEVICE_MODIFY_LIVE |
VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
virXendError(domain->conn, VIR_ERR_OPERATION_INVALID, "%s",
_("Xend only supports modifying both live and "
"persisted config"));
"persistent config"));
return -1;
}
}
......@@ -5224,6 +5337,7 @@ struct xenUnifiedDriver xenDaemonDriver = {
xenDaemonDomainUndefine, /* domainUndefine */
xenDaemonAttachDeviceFlags, /* domainAttachDeviceFlags */
xenDaemonDetachDeviceFlags, /* domainDetachDeviceFlags */
xenDaemonUpdateDeviceFlags, /* domainUpdateDeviceFlags */
xenDaemonDomainGetAutostart, /* domainGetAutostart */
xenDaemonDomainSetAutostart, /* domainSetAutostart */
xenDaemonGetSchedulerType, /* domainGetSchedulerType */
......
......@@ -113,6 +113,7 @@ struct xenUnifiedDriver xenXMDriver = {
xenXMDomainUndefine, /* domainUndefine */
xenXMDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
xenXMDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
......
......@@ -78,6 +78,7 @@ struct xenUnifiedDriver xenStoreDriver = {
NULL, /* domainUndefine */
NULL, /* domainAttachDeviceFlags */
NULL, /* domainDetachDeviceFlags */
NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册