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,
qemudDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
qemudDomainDetachDevice, /* domainDetachDevice */
qemudDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
- NULL, /* domainUpdateDeviceFlags */
+ qemuDomainUpdateDeviceFlags, /* domainUpdateDeviceFlags */
qemudDomainGetAutostart, /* domainGetAutostart */
qemudDomainSetAutostart, /* domainSetAutostart */
qemuGetSchedulerType, /* domainGetSchedulerType */
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;
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) {
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) {
vboxDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
vboxDomainDetachDevice, /* domainDetachDevice */
vboxDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
- NULL, /* domainUpdateDeviceFlags */
+ vboxDomainUpdateDeviceFlags, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
NULL, /* domainUndefine */
NULL, /* domainAttachDeviceFlags */
NULL, /* domainDetachDeviceFlags */
+ NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
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)
{
xenUnifiedDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
xenUnifiedDomainDetachDevice, /* domainDetachDevice */
xenUnifiedDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
- NULL, /* domainUpdateDeviceFlags */
+ xenUnifiedDomainUpdateDeviceFlags, /* domainUpdateDeviceFlags */
xenUnifiedDomainGetAutostart, /* domainGetAutostart */
xenUnifiedDomainSetAutostart, /* domainSetAutostart */
xenUnifiedDomainGetSchedulerType, /* domainGetSchedulerType */
virDrvDomainUndefine domainUndefine;
virDrvDomainAttachDeviceFlags domainAttachDeviceFlags;
virDrvDomainDetachDeviceFlags domainDetachDeviceFlags;
+ virDrvDomainUpdateDeviceFlags domainUpdateDeviceFlags;
virDrvDomainGetAutostart domainGetAutostart;
virDrvDomainSetAutostart domainSetAutostart;
virDrvDomainGetSchedulerType domainGetSchedulerType;
NULL, /* domainUndefine */
NULL, /* domainAttachDeviceFlags */
NULL, /* domainDetachDeviceFlags */
+ NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
xenHypervisorGetSchedulerType, /* domainGetSchedulerType */
NULL, /* domainUndefine */
NULL, /* domainAttachDeviceFlags */
NULL, /* domainDetachDeviceFlags */
+ NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
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 */
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;
}
}
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
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 */
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;
}
}
xenDaemonDomainUndefine, /* domainUndefine */
xenDaemonAttachDeviceFlags, /* domainAttachDeviceFlags */
xenDaemonDetachDeviceFlags, /* domainDetachDeviceFlags */
+ xenDaemonUpdateDeviceFlags, /* domainUpdateDeviceFlags */
xenDaemonDomainGetAutostart, /* domainGetAutostart */
xenDaemonDomainSetAutostart, /* domainSetAutostart */
xenDaemonGetSchedulerType, /* domainGetSchedulerType */
xenXMDomainUndefine, /* domainUndefine */
xenXMDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
xenXMDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
+ NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */
NULL, /* domainUndefine */
NULL, /* domainAttachDeviceFlags */
NULL, /* domainDetachDeviceFlags */
+ NULL, /* domainUpdateDeviceFlags */
NULL, /* domainGetAutostart */
NULL, /* domainSetAutostart */
NULL, /* domainGetSchedulerType */