Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 632064 Details for
Bug 869259
Add device operations support for libvirt (lxc)
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Add device operations support for libvirt lxc.
add-device-operations-support-for-libvirt-lxc.diff (text/plain), 16.78 KB, created by
Heiher
on 2012-10-23 12:27:41 UTC
(
hide
)
Description:
Add device operations support for libvirt lxc.
Filename:
MIME Type:
Creator:
Heiher
Created:
2012-10-23 12:27:41 UTC
Size:
16.78 KB
patch
obsolete
>diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c >index 87305db..45407ee 100644 >--- a/src/lxc/lxc_driver.c >+++ b/src/lxc/lxc_driver.c >@@ -71,6 +71,8 @@ > > static int lxcStartup(int privileged); > static int lxcShutdown(void); >+static bool lxcCgroupControllerActive(virLXCDriverPtr driver, >+ int controller); > virLXCDriverPtr lxc_driver = NULL; > > /* callbacks for nwfilter */ >@@ -516,6 +518,467 @@ static int lxcDomainUndefine(virDomainPtr dom) > return lxcDomainUndefineFlags(dom, 0); > } > >+ >+/* Actions for lxcDomainModifyDeviceFlags */ >+enum { >+ LXC_DEVICE_ATTACH, >+ LXC_DEVICE_DETACH, >+ LXC_DEVICE_UPDATE, >+}; >+ >+static int >+lxcDomainAttachDeviceDiskLive(virLXCDriverPtr driver, >+ virDomainObjPtr vm, virDomainDeviceDefPtr dev) >+{ >+ virDomainDiskDefPtr l_disk = dev->data.disk; >+ virCgroupPtr group = NULL; >+ int ret = -1; >+ >+ switch (l_disk->device) { >+ case VIR_DOMAIN_DISK_DEVICE_DISK: >+ if (l_disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { >+ if (virDomainDiskIndexByName(vm->def, l_disk->dst, true) >= 0) { >+ virReportError(VIR_ERR_OPERATION_FAILED, >+ _("target %s already exists"), l_disk->dst); >+ goto cleanup; >+ } >+ >+ if (!l_disk->src) { >+ virReportError(VIR_ERR_INTERNAL_ERROR, >+ "%s", _("disk source path is missing")); >+ goto cleanup; >+ } >+ >+ if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { >+ virReportError(VIR_ERR_OPERATION_INVALID, "%s", >+ _("devices cgroup isn't mounted")); >+ goto cleanup; >+ } >+ >+ if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) { >+ virReportError(VIR_ERR_INTERNAL_ERROR, >+ _("cannot find cgroup for domain %s"), vm->def->name); >+ goto cleanup; >+ } >+ >+ if (virCgroupAllowDevicePath(group, l_disk->src, VIR_CGROUP_DEVICE_RWM) != 0) { >+ virReportError(VIR_ERR_INTERNAL_ERROR, >+ _("cannot allow device %s for domain %s"), >+ l_disk->src, vm->def->name); >+ goto cleanup; >+ } >+ >+ ret = virDomainDiskInsert(vm->def, l_disk); >+ >+ } else { >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, >+ _("disk bus '%s' cannot be hotplugged."), >+ virDomainDiskBusTypeToString(l_disk->bus)); >+ } >+ break; >+ default: >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, >+ _("disk device type '%s' cannot be hotplugged"), >+ virDomainDiskDeviceTypeToString(l_disk->device)); >+ break; >+ } >+ >+cleanup: >+ return ret; >+} >+ >+static int >+lxcDomainAttachDeviceLive(virLXCDriverPtr driver, virDomainObjPtr vm, >+ virDomainDeviceDefPtr dev) >+{ >+ int ret = -1; >+ >+ switch (dev->type) { >+ case VIR_DOMAIN_DEVICE_DISK: >+ ret = lxcDomainAttachDeviceDiskLive(driver, vm, dev); >+ if (!ret) >+ dev->data.disk = NULL; >+ break; >+ >+ default: >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, >+ _("device type '%s' cannot be attached"), >+ virDomainDeviceTypeToString(dev->type)); >+ break; >+ } >+ >+ return ret; >+} >+ >+static int >+lxcDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) >+{ >+ virDomainDiskDefPtr disk; >+ >+ switch (dev->type) { >+ case VIR_DOMAIN_DEVICE_DISK: >+ disk = dev->data.disk; >+ if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) { >+ virReportError(VIR_ERR_INVALID_ARG, >+ _("target %s already exists."), disk->dst); >+ return -1; >+ } >+ if (virDomainDiskInsert(vmdef, disk)) { >+ virReportOOMError(); >+ return -1; >+ } >+ /* vmdef has the pointer. Generic codes for vmdef will do all jobs */ >+ dev->data.disk = NULL; >+ break; >+ >+ default: >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", >+ _("persistent attach of device is not supported")); >+ return -1; >+ } >+ return 0; >+} >+ >+static int >+lxcDomainDetachDeviceDiskLive(virLXCDriverPtr driver, >+ virDomainObjPtr vm, virDomainDeviceDefPtr dev) >+{ >+ virDomainDiskDefPtr l_disk = NULL; >+ virCgroupPtr group = NULL; >+ int i, ret = -1; >+ >+ switch (dev->data.disk->device) { >+ case VIR_DOMAIN_DISK_DEVICE_DISK: >+ if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { >+ >+ if ((i = virDomainDiskIndexByName(vm->def, >+ dev->data.disk->dst, >+ false)) < 0) { >+ virReportError(VIR_ERR_OPERATION_FAILED, >+ _("disk %s not found"), dev->data.disk->dst); >+ goto cleanup; >+ } >+ >+ l_disk = vm->def->disks[i]; >+ >+ if (!l_disk->src) { >+ virReportError(VIR_ERR_INTERNAL_ERROR, >+ "%s", _("disk source path is missing")); >+ goto cleanup; >+ } >+ >+ if (!lxcCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) { >+ virReportError(VIR_ERR_OPERATION_INVALID, "%s", >+ _("devices cgroup isn't mounted")); >+ goto cleanup; >+ } >+ >+ if (virCgroupForDomain(driver->cgroup, vm->def->name, &group, 0) != 0) { >+ virReportError(VIR_ERR_INTERNAL_ERROR, >+ _("cannot find cgroup for domain %s"), vm->def->name); >+ goto cleanup; >+ } >+ >+ if (virCgroupDenyDevicePath(group, l_disk->src, VIR_CGROUP_DEVICE_RWM) != 0) { >+ virReportError(VIR_ERR_INTERNAL_ERROR, >+ _("cannot allow device %s for domain %s"), >+ l_disk->src, vm->def->name); >+ goto cleanup; >+ } >+ >+ virDomainDiskRemove(vm->def, i); >+ virDomainDiskDefFree(l_disk); >+ >+ ret = 0; >+ } else { >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, >+ _("disk bus '%s' cannot be hot unplugged."), >+ virDomainDiskBusTypeToString(dev->data.disk->bus)); >+ } >+ break; >+ default: >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, >+ _("device type '%s' cannot hot unplugged"), >+ virDomainDiskDeviceTypeToString(dev->data.disk->device)); >+ break; >+ } >+ >+cleanup: >+ return ret; >+} >+ >+static int >+lxcDomainDetachDeviceLive(virLXCDriverPtr driver, virDomainObjPtr vm, >+ virDomainDeviceDefPtr dev) >+{ >+ int ret = -1; >+ >+ switch (dev->type) { >+ case VIR_DOMAIN_DEVICE_DISK: >+ ret = lxcDomainDetachDeviceDiskLive(driver, vm, dev); >+ break; >+ >+ default: >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, >+ _("device type '%s' cannot be detached"), >+ virDomainDeviceTypeToString(dev->type)); >+ break; >+ } >+ >+ return ret; >+} >+ >+static int >+lxcDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) >+{ >+ virDomainDiskDefPtr disk, detach; >+ int ret = -1; >+ >+ switch (dev->type) { >+ case VIR_DOMAIN_DEVICE_DISK: >+ disk = dev->data.disk; >+ if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) { >+ virReportError(VIR_ERR_INVALID_ARG, >+ _("no target device %s"), disk->dst); >+ break; >+ } >+ virDomainDiskDefFree(detach); >+ ret = 0; >+ break; >+ default: >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", >+ _("persistent detach of device is not supported")); >+ break; >+ } >+ >+ return ret; >+} >+ >+static int >+lxcDomainUpdateDeviceLive(virLXCDriverPtr driver, >+ virDomainObjPtr vm, virDomainDeviceDefPtr dev) >+{ >+ virDomainDiskDefPtr disk; >+ int ret = -1; >+ >+ switch (dev->type) { >+ case VIR_DOMAIN_DEVICE_DISK: >+ disk = dev->data.disk; >+ switch (disk->device) { >+ default: >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, >+ _("disk bus '%s' cannot be updated."), >+ virDomainDiskBusTypeToString(disk->bus)); >+ break; >+ } >+ ret = 0; >+ break; >+ default: >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, >+ _("device type '%s' cannot be updated"), >+ virDomainDeviceTypeToString(dev->type)); >+ break; >+ } >+ >+ return ret; >+} >+ >+static int >+lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev) >+{ >+ virDomainDiskDefPtr orig; >+ virDomainDiskDefPtr disk; >+ int i; >+ int ret = -1; >+ >+ switch (dev->type) { >+ case VIR_DOMAIN_DEVICE_DISK: >+ disk = dev->data.disk; >+ if ((i = virDomainDiskIndexByName(vmdef, disk->dst, false)) < 0) { >+ virReportError(VIR_ERR_INVALID_ARG, >+ _("target %s doesn't exist."), disk->dst); >+ goto cleanup; >+ } >+ orig = vmdef->disks[i]; >+ if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM)) { >+ virReportError(VIR_ERR_INVALID_ARG, "%s", >+ _("this disk doesn't support update")); >+ goto cleanup; >+ } >+ >+ VIR_FREE(orig->src); >+ orig->src = disk->src; >+ orig->type = disk->type; >+ if (disk->driverName) { >+ VIR_FREE(orig->driverName); >+ orig->driverName = disk->driverName; >+ disk->driverName = NULL; >+ } >+ orig->format = disk->format; >+ disk->src = NULL; >+ break; >+ default: >+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", >+ _("persistent update of device is not supported")); >+ goto cleanup; >+ } >+ >+ ret = 0; >+ >+cleanup: >+ return ret; >+} >+ >+static int >+lxcDomainModifyDeviceFlags(virDomainPtr dom, const char *xml, >+ unsigned int flags, int action) >+{ >+ virLXCDriverPtr driver = dom->conn->privateData; >+ virDomainObjPtr vm = NULL; >+ virDomainDefPtr vmdef = NULL; >+ virDomainDeviceDefPtr dev = NULL; >+ int ret = -1; >+ >+ virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE | >+ VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1); >+ >+ lxcDriverLock(driver); >+ vm = virDomainFindByUUID(&driver->domains, dom->uuid); >+ >+ if (!vm) { >+ virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); >+ goto cleanup; >+ } >+ >+ if (virDomainObjIsActive(vm)) { >+ if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT) >+ flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE; >+ } else { >+ if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT) >+ flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG; >+ /* check consistency between flags and the vm state */ >+ if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { >+ virReportError(VIR_ERR_OPERATION_INVALID, >+ "%s", _("Domain is not running")); >+ goto cleanup; >+ } >+ } >+ >+ if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) { >+ virReportError(VIR_ERR_OPERATION_INVALID, >+ "%s", _("cannot modify device on transient domain")); >+ goto cleanup; >+ } >+ >+ if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) { >+ if (!(dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, >+ VIR_DOMAIN_XML_INACTIVE))) >+ goto cleanup; >+ >+ /* Make a copy for updated domain. */ >+ if (!(vmdef = virDomainObjCopyPersistentDef(driver->caps, vm))) >+ goto cleanup; >+ >+ switch (action) { >+ case LXC_DEVICE_ATTACH: >+ ret = lxcDomainAttachDeviceConfig(vmdef, dev); >+ break; >+ case LXC_DEVICE_DETACH: >+ ret = lxcDomainDetachDeviceConfig(vmdef, dev); >+ break; >+ case LXC_DEVICE_UPDATE: >+ ret = lxcDomainUpdateDeviceConfig(vmdef, dev); >+ default: >+ virReportError(VIR_ERR_INTERNAL_ERROR, >+ _("unknown domain modify action %d"), action); >+ break; >+ } >+ } else >+ ret = 0; >+ >+ if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) { >+ /* If dev exists it was created to modify the domain config. Free it. */ >+ virDomainDeviceDefFree(dev); >+ if (!(dev = virDomainDeviceDefParse(driver->caps, vm->def, xml, >+ VIR_DOMAIN_XML_INACTIVE))) >+ goto cleanup; >+ >+ switch (action) { >+ case LXC_DEVICE_ATTACH: >+ ret = lxcDomainAttachDeviceLive(driver, vm, dev); >+ break; >+ case LXC_DEVICE_DETACH: >+ ret = lxcDomainDetachDeviceLive(driver, vm, dev); >+ break; >+ case LXC_DEVICE_UPDATE: >+ ret = lxcDomainUpdateDeviceLive(driver, vm, dev); >+ default: >+ virReportError(VIR_ERR_INTERNAL_ERROR, >+ _("unknown domain modify action %d"), action); >+ break; >+ } >+ /* >+ * update domain status forcibly because the domain status may be >+ * changed even if we attach the device failed. >+ */ >+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) >+ ret = -1; >+ } >+ >+ /* Finally, if no error until here, we can save config. */ >+ if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) { >+ ret = virDomainSaveConfig(driver->configDir, vmdef); >+ if (!ret) { >+ virDomainObjAssignDef(vm, vmdef, false); >+ vmdef = NULL; >+ } >+ } >+ >+cleanup: >+ virDomainDefFree(vmdef); >+ virDomainDeviceDefFree(dev); >+ if (vm) >+ virDomainObjUnlock(vm); >+ lxcDriverUnlock(driver); >+ return ret; >+} >+ >+static int >+lxcDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, >+ unsigned int flags) >+{ >+ return lxcDomainModifyDeviceFlags(dom, xml, flags, LXC_DEVICE_ATTACH); >+} >+ >+static int >+lxcDomainAttachDevice(virDomainPtr dom, const char *xml) >+{ >+ return lxcDomainAttachDeviceFlags(dom, xml, >+ VIR_DOMAIN_DEVICE_MODIFY_LIVE); >+} >+ >+static int >+lxcDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, >+ unsigned int flags) >+{ >+ return lxcDomainModifyDeviceFlags(dom, xml, flags, LXC_DEVICE_DETACH); >+} >+ >+static int >+lxcDomainDetachDevice(virDomainPtr dom, const char *xml) >+{ >+ return lxcDomainDetachDeviceFlags(dom, xml, >+ VIR_DOMAIN_DEVICE_MODIFY_LIVE); >+} >+ >+static int >+lxcDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, >+ unsigned int flags) >+{ >+ return lxcDomainModifyDeviceFlags(dom, xml, flags, LXC_DEVICE_UPDATE); >+} >+ >+ > static int lxcDomainGetInfo(virDomainPtr dom, > virDomainInfoPtr info) > { >@@ -2724,6 +3187,11 @@ static virDriver lxcDriver = { > .domainDefineXML = lxcDomainDefine, /* 0.4.2 */ > .domainUndefine = lxcDomainUndefine, /* 0.4.2 */ > .domainUndefineFlags = lxcDomainUndefineFlags, /* 0.9.4 */ >+ .domainAttachDevice = lxcDomainAttachDevice, /* 0.10.2 */ >+ .domainAttachDeviceFlags = lxcDomainAttachDeviceFlags, /* 0.10.2 */ >+ .domainDetachDevice = lxcDomainDetachDevice, /* 0.10.2 */ >+ .domainDetachDeviceFlags = lxcDomainDetachDeviceFlags, /* 0.10.2 */ >+ .domainUpdateDeviceFlags = lxcDomainUpdateDeviceFlags, /* 0.10.2 */ > .domainGetAutostart = lxcDomainGetAutostart, /* 0.7.0 */ > .domainSetAutostart = lxcDomainSetAutostart, /* 0.7.0 */ > .domainGetSchedulerType = lxcGetSchedulerType, /* 0.5.0 */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 869259
: 632064