[libvirt] [PATCH] qemu: Translate boot config into bootindex if possible
by Jiri Denemark
Prefer bootindex=N option for -device over the old way -boot ORDER
possibly accompanied with boot=on option for -drive. This gives us full
control over which device will actually be used for booting guest OS.
Moreover, if qemu doesn't support boot=on, this is the only way to boot
of certain disks in some configurations (such as virtio disks when used
together IDE disks) without transforming domain XML to use per device
boot elements.
---
src/qemu/qemu_command.c | 141 +++++++++++++-------
src/qemu/qemu_command.h | 4 +-
src/qemu/qemu_hotplug.c | 14 +-
.../qemuxml2argv-boot-complex-bootindex.args | 30 ++++
.../qemuxml2argv-boot-complex-bootindex.xml | 65 +++++++++
.../qemuxml2argv-boot-complex.args | 30 ++++
.../qemuxml2argvdata/qemuxml2argv-boot-complex.xml | 65 +++++++++
...xml2argv-boot-menu-disable-drive-bootindex.args | 13 ++
...uxml2argv-boot-menu-disable-drive-bootindex.xml | 27 ++++
.../qemuxml2argv-boot-menu-disable-drive.args | 14 ++
.../qemuxml2argv-boot-menu-disable-drive.xml | 27 ++++
.../qemuxml2argv-boot-menu-enable.args | 14 ++
.../qemuxml2argv-boot-menu-enable.xml | 27 ++++
.../qemuxml2argv-disk-drive-no-boot.args | 18 +++
.../qemuxml2argv-disk-drive-no-boot.xml | 38 ++++++
tests/qemuxml2argvtest.c | 17 +++
16 files changed, 489 insertions(+), 55 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-complex.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-complex.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.xml
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index ef2d002..277fa99 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1189,7 +1189,7 @@ qemuSafeSerialParamValue(const char *value)
char *
qemuBuildDriveStr(virDomainDiskDefPtr disk,
- int bootable,
+ bool bootable,
virBitmapPtr qemuCaps)
{
virBuffer opt = VIR_BUFFER_INITIALIZER;
@@ -1343,6 +1343,7 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
}
}
if (bootable &&
+ qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_BOOT) &&
disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
disk->bus != VIR_DOMAIN_DISK_BUS_IDE)
virBufferAddLit(&opt, ",boot=on");
@@ -1406,6 +1407,7 @@ error:
char *
qemuBuildDriveDevStr(virDomainDiskDefPtr disk,
+ int bootindex,
virBitmapPtr qemuCaps)
{
virBuffer opt = VIR_BUFFER_INITIALIZER;
@@ -1446,8 +1448,8 @@ qemuBuildDriveDevStr(virDomainDiskDefPtr disk,
}
virBufferAsprintf(&opt, ",drive=%s%s", QEMU_DRIVE_HOST_PREFIX, disk->info.alias);
virBufferAsprintf(&opt, ",id=%s", disk->info.alias);
- if (disk->bootIndex && qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX))
- virBufferAsprintf(&opt, ",bootindex=%d", disk->bootIndex);
+ if (bootindex && qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX))
+ virBufferAsprintf(&opt, ",bootindex=%d", bootindex);
if (virBufferError(&opt)) {
virReportOOMError();
@@ -1615,6 +1617,7 @@ qemuBuildNicStr(virDomainNetDefPtr net,
char *
qemuBuildNicDevStr(virDomainNetDefPtr net,
int vlan,
+ int bootindex,
virBitmapPtr qemuCaps)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
@@ -1667,8 +1670,8 @@ qemuBuildNicDevStr(virDomainNetDefPtr net,
net->mac[4], net->mac[5]);
if (qemuBuildDeviceAddressStr(&buf, &net->info, qemuCaps) < 0)
goto error;
- if (net->bootIndex && qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX))
- virBufferAsprintf(&buf, ",bootindex=%d", net->bootIndex);
+ if (bootindex && qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX))
+ virBufferAsprintf(&buf, ",bootindex=%d", bootindex);
if (virBufferError(&buf)) {
virReportOOMError();
@@ -2684,7 +2687,6 @@ qemuBuildCommandLine(virConnectPtr conn,
enum virVMOperationType vmop)
{
int i;
- char boot[VIR_DOMAIN_BOOT_LAST+1];
struct utsname ut;
int disableKQEMU = 0;
int enableKQEMU = 0;
@@ -2699,6 +2701,7 @@ qemuBuildCommandLine(virConnectPtr conn,
virCommandPtr cmd;
bool has_rbd_hosts = false;
virBuffer rbd_hosts = VIR_BUFFER_INITIALIZER;
+ bool emitBootindex = false;
uname_normalize(&ut);
@@ -3090,31 +3093,54 @@ qemuBuildCommandLine(virConnectPtr conn,
virCommandAddArg(cmd, "-no-acpi");
if (!def->os.bootloader) {
- for (i = 0 ; i < def->os.nBootDevs ; i++) {
- switch (def->os.bootDevs[i]) {
- case VIR_DOMAIN_BOOT_CDROM:
- boot[i] = 'd';
- break;
- case VIR_DOMAIN_BOOT_FLOPPY:
- boot[i] = 'a';
- break;
- case VIR_DOMAIN_BOOT_DISK:
- boot[i] = 'c';
- break;
- case VIR_DOMAIN_BOOT_NET:
- boot[i] = 'n';
- break;
- default:
- boot[i] = 'c';
- break;
+ /*
+ * We prefer using explicit bootindex=N parameters for predictable
+ * results even though domain XML doesn't use per device boot elements.
+ * However, we can't use bootindex if boot menu was requested.
+ */
+ if (!def->os.nBootDevs) {
+ /* def->os.nBootDevs is guaranteed to be > 0 unless per-device boot
+ * configuration is used
+ */
+ if (!qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX)) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("hypervisor lacks deviceboot feature"));
+ goto error;
}
+ emitBootindex = true;
+ } else if (qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX) &&
+ (def->os.bootmenu != VIR_DOMAIN_BOOT_MENU_ENABLED ||
+ !qemuCapsGet(qemuCaps, QEMU_CAPS_BOOT_MENU))) {
+ emitBootindex = true;
}
- if (def->os.nBootDevs) {
+
+ if (!emitBootindex) {
virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
- virCommandAddArg(cmd, "-boot");
+ char boot[VIR_DOMAIN_BOOT_LAST+1];
+ for (i = 0 ; i < def->os.nBootDevs ; i++) {
+ switch (def->os.bootDevs[i]) {
+ case VIR_DOMAIN_BOOT_CDROM:
+ boot[i] = 'd';
+ break;
+ case VIR_DOMAIN_BOOT_FLOPPY:
+ boot[i] = 'a';
+ break;
+ case VIR_DOMAIN_BOOT_DISK:
+ boot[i] = 'c';
+ break;
+ case VIR_DOMAIN_BOOT_NET:
+ boot[i] = 'n';
+ break;
+ default:
+ boot[i] = 'c';
+ break;
+ }
+ }
boot[def->os.nBootDevs] = '\0';
+ virCommandAddArg(cmd, "-boot");
+
if (qemuCapsGet(qemuCaps, QEMU_CAPS_BOOT_MENU) &&
def->os.bootmenu != VIR_DOMAIN_BOOT_MENU_DEFAULT) {
if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_ENABLED)
@@ -3126,13 +3152,6 @@ qemuBuildCommandLine(virConnectPtr conn,
}
virCommandAddArgBuffer(cmd, &boot_buf);
- } else if (!qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX)) {
- /* def->os.nBootDevs is guaranteed to be > 0 unless per-device boot
- * configuration is used
- */
- qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("hypervisor lacks deviceboot feature"));
- goto error;
}
if (def->os.kernel)
@@ -3190,19 +3209,20 @@ qemuBuildCommandLine(virConnectPtr conn,
if (qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE)) {
int bootCD = 0, bootFloppy = 0, bootDisk = 0;
- /* If QEMU supports boot=on for -drive param... */
- if (qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_BOOT) &&
+ if ((qemuCapsGet(qemuCaps, QEMU_CAPS_DRIVE_BOOT) || emitBootindex) &&
!def->os.kernel) {
+ /* bootDevs will get translated into either bootindex=N or boot=on
+ * depending on what qemu supports */
for (i = 0 ; i < def->os.nBootDevs ; i++) {
switch (def->os.bootDevs[i]) {
case VIR_DOMAIN_BOOT_CDROM:
- bootCD = 1;
+ bootCD = i + 1;
break;
case VIR_DOMAIN_BOOT_FLOPPY:
- bootFloppy = 1;
+ bootFloppy = i + 1;
break;
case VIR_DOMAIN_BOOT_DISK:
- bootDisk = 1;
+ bootDisk = i + 1;
break;
}
}
@@ -3210,7 +3230,7 @@ qemuBuildCommandLine(virConnectPtr conn,
for (i = 0 ; i < def->ndisks ; i++) {
char *optstr;
- int bootable = 0;
+ int bootindex = 0;
virDomainDiskDefPtr disk = def->disks[i];
int withDeviceArg = 0;
bool deviceFlagMasked = false;
@@ -3234,15 +3254,15 @@ qemuBuildCommandLine(virConnectPtr conn,
switch (disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM:
- bootable = bootCD;
+ bootindex = bootCD;
bootCD = 0;
break;
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
- bootable = bootFloppy;
+ bootindex = bootFloppy;
bootFloppy = 0;
break;
case VIR_DOMAIN_DISK_DEVICE_DISK:
- bootable = bootDisk;
+ bootindex = bootDisk;
bootDisk = 0;
break;
}
@@ -3262,7 +3282,9 @@ qemuBuildCommandLine(virConnectPtr conn,
deviceFlagMasked = true;
}
}
- optstr = qemuBuildDriveStr(disk, bootable, qemuCaps);
+ optstr = qemuBuildDriveStr(disk,
+ emitBootindex ? false : !!bootindex,
+ qemuCaps);
if (deviceFlagMasked)
qemuCapsSet(qemuCaps, QEMU_CAPS_DEVICE);
if (!optstr)
@@ -3290,6 +3312,11 @@ qemuBuildCommandLine(virConnectPtr conn,
}
}
+ if (!emitBootindex)
+ bootindex = 0;
+ else if (disk->bootIndex)
+ bootindex = disk->bootIndex;
+
if (withDeviceArg) {
if (disk->bus == VIR_DOMAIN_DISK_BUS_FDC) {
virCommandAddArg(cmd, "-global");
@@ -3298,18 +3325,18 @@ qemuBuildCommandLine(virConnectPtr conn,
? 'B' : 'A',
disk->info.alias);
- if (disk->bootIndex &&
- qemuCapsGet(qemuCaps, QEMU_CAPS_BOOTINDEX)) {
+ if (bootindex) {
virCommandAddArg(cmd, "-global");
virCommandAddArgFormat(cmd, "isa-fdc.bootindex%c=%d",
disk->info.addr.drive.unit
? 'B' : 'A',
- disk->bootIndex);
+ bootindex);
}
} else {
virCommandAddArg(cmd, "-device");
- if (!(optstr = qemuBuildDriveDevStr(disk, qemuCaps)))
+ if (!(optstr = qemuBuildDriveDevStr(disk, bootindex,
+ qemuCaps)))
goto error;
virCommandAddArg(cmd, optstr);
VIR_FREE(optstr);
@@ -3470,12 +3497,31 @@ qemuBuildCommandLine(virConnectPtr conn,
if (!qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE))
virCommandAddArgList(cmd, "-net", "none", NULL);
} else {
+ int bootNet = 0;
+
+ if (emitBootindex) {
+ /* convert <boot dev='network'/> to bootindex since we didn't emit
+ * -boot n
+ */
+ for (i = 0 ; i < def->os.nBootDevs ; i++) {
+ if (def->os.bootDevs[i] == VIR_DOMAIN_BOOT_NET) {
+ bootNet = i + 1;
+ break;
+ }
+ }
+ }
+
for (i = 0 ; i < def->nnets ; i++) {
virDomainNetDefPtr net = def->nets[i];
char *nic, *host;
char tapfd_name[50];
char vhostfd_name[50] = "";
int vlan;
+ int bootindex = bootNet;
+
+ bootNet = 0;
+ if (!bootindex)
+ bootindex = net->bootIndex;
/* VLANs are not used with -netdev, so don't record them */
if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) &&
@@ -3547,7 +3593,8 @@ qemuBuildCommandLine(virConnectPtr conn,
}
if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
virCommandAddArg(cmd, "-device");
- if (!(nic = qemuBuildNicDevStr(net, vlan, qemuCaps)))
+ nic = qemuBuildNicDevStr(net, vlan, bootindex, qemuCaps);
+ if (!nic)
goto error;
virCommandAddArg(cmd, nic);
VIR_FREE(nic);
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 528031d..d6e5dcb 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -68,6 +68,7 @@ char * qemuBuildNicStr(virDomainNetDefPtr net,
/* Current, best practice */
char * qemuBuildNicDevStr(virDomainNetDefPtr net,
int vlan,
+ int bootindex,
virBitmapPtr qemuCaps);
char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
@@ -75,13 +76,14 @@ char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk,
/* Both legacy & current support */
char *qemuBuildDriveStr(virDomainDiskDefPtr disk,
- int bootable,
+ bool bootable,
virBitmapPtr qemuCaps);
char *qemuBuildFSStr(virDomainFSDefPtr fs,
virBitmapPtr qemuCaps);
/* Current, best practice */
char * qemuBuildDriveDevStr(virDomainDiskDefPtr disk,
+ int bootindex,
virBitmapPtr qemuCaps);
char * qemuBuildFSDevStr(virDomainFSDefPtr fs,
virBitmapPtr qemuCaps);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index fe47896..b605b3a 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -186,10 +186,10 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver,
if (qemuAssignDeviceDiskAlias(disk, priv->qemuCaps) < 0)
goto error;
- if (!(drivestr = qemuBuildDriveStr(disk, 0, priv->qemuCaps)))
+ if (!(drivestr = qemuBuildDriveStr(disk, false, priv->qemuCaps)))
goto error;
- if (!(devstr = qemuBuildDriveDevStr(disk, priv->qemuCaps)))
+ if (!(devstr = qemuBuildDriveDevStr(disk, 0, priv->qemuCaps)))
goto error;
}
@@ -409,11 +409,11 @@ int qemuDomainAttachSCSIDisk(struct qemud_driver *driver,
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
if (qemuAssignDeviceDiskAlias(disk, priv->qemuCaps) < 0)
goto error;
- if (!(devstr = qemuBuildDriveDevStr(disk, priv->qemuCaps)))
+ if (!(devstr = qemuBuildDriveDevStr(disk, 0, priv->qemuCaps)))
goto error;
}
- if (!(drivestr = qemuBuildDriveStr(disk, 0, priv->qemuCaps)))
+ if (!(drivestr = qemuBuildDriveStr(disk, false, priv->qemuCaps)))
goto error;
for (i = 0 ; i <= disk->info.addr.drive.controller ; i++) {
@@ -529,9 +529,9 @@ int qemuDomainAttachUsbMassstorageDevice(struct qemud_driver *driver,
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
if (qemuAssignDeviceDiskAlias(disk, priv->qemuCaps) < 0)
goto error;
- if (!(drivestr = qemuBuildDriveStr(disk, 0, priv->qemuCaps)))
+ if (!(drivestr = qemuBuildDriveStr(disk, false, priv->qemuCaps)))
goto error;
- if (!(devstr = qemuBuildDriveDevStr(disk, priv->qemuCaps)))
+ if (!(devstr = qemuBuildDriveDevStr(disk, 0, priv->qemuCaps)))
goto error;
}
@@ -702,7 +702,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
}
if (qemuCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
- if (!(nicstr = qemuBuildNicDevStr(net, vlan, priv->qemuCaps)))
+ if (!(nicstr = qemuBuildNicDevStr(net, vlan, 0, priv->qemuCaps)))
goto try_remove;
} else {
if (!(nicstr = qemuBuildNicStr(net, NULL, vlan)))
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.args
new file mode 100644
index 0000000..ae0b2b1
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.args
@@ -0,0 +1,30 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-drive file=/tmp/vda.img,if=none,id=drive-virtio-disk0 \
+-device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0,bootindex=3 \
+-drive file=/tmp/vdb.img,if=none,id=drive-virtio-disk1 \
+-device virtio-blk-pci,bus=pci.0,addr=0x6,drive=drive-virtio-disk1,id=virtio-disk1 \
+-drive file=/dev/HostVG/hda,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-drive file=/dev/HostVG/hdb,if=none,id=drive-ide0-0-1 \
+-device ide-drive,bus=ide.0,unit=1,drive=drive-ide0-0-1,id=ide0-0-1 \
+-drive file=/dev/HostVG/hdc,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,bootindex=1 \
+-drive file=/dev/fd0,if=none,id=drive-fdc0-0-0 \
+-global isa-fdc.driveA=drive-fdc0-0-0 \
+-global isa-fdc.bootindexA=4 \
+-drive file=/dev/fd1,if=none,id=drive-fdc0-0-1 \
+-global isa-fdc.driveB=drive-fdc0-0-1 \
+-device virtio-net-pci,vlan=0,id=net0,mac=00:11:22:33:44:11,bus=pci.0,addr=0x3,bootindex=2 \
+-net user,vlan=0,name=hostnet0 \
+-device virtio-net-pci,vlan=1,id=net1,mac=00:11:22:33:44:22,bus=pci.0,addr=0x4 \
+-net user,vlan=1,name=hostnet1 \
+-usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.xml
new file mode 100644
index 0000000..b4d6f4f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex-bootindex.xml
@@ -0,0 +1,65 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='cdrom'/>
+ <boot dev='network'/>
+ <boot dev='hd'/>
+ <boot dev='fd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='file' device='disk'>
+ <source file='/tmp/vdb.img'/>
+ <target dev='vdb' bus='virtio'/>
+ </disk>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/hdb'/>
+ <target dev='hdb' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='1'/>
+ </disk>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/hda'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <source file='/tmp/vda.img'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ <disk type='block' device='cdrom'>
+ <source dev='/dev/HostVG/hdc'/>
+ <target dev='hdc' bus='ide'/>
+ <address type='drive' controller='0' bus='1' unit='0'/>
+ </disk>
+ <disk type='block' device='floppy'>
+ <source dev='/dev/fd1'/>
+ <target dev='fdb' bus='fdc'/>
+ <address type='drive' controller='0' bus='0' unit='1'/>
+ </disk>
+ <disk type='block' device='floppy'>
+ <source dev='/dev/fd0'/>
+ <target dev='fda' bus='fdc'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <controller type='fdc' index='0'/>
+ <controller type='ide' index='0'/>
+ <interface type='user'>
+ <mac address='00:11:22:33:44:11'/>
+ <model type='virtio'/>
+ </interface>
+ <interface type='user'>
+ <mac address='00:11:22:33:44:22'/>
+ <model type='virtio'/>
+ </interface>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.args
new file mode 100644
index 0000000..c8d32ec
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.args
@@ -0,0 +1,30 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-boot dnca \
+-drive file=/tmp/vda.img,if=none,id=drive-virtio-disk0,boot=on \
+-device virtio-blk-pci,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,id=virtio-disk0 \
+-drive file=/tmp/vdb.img,if=none,id=drive-virtio-disk1 \
+-device virtio-blk-pci,bus=pci.0,addr=0x6,drive=drive-virtio-disk1,id=virtio-disk1 \
+-drive file=/dev/HostVG/hda,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-drive file=/dev/HostVG/hdb,if=none,id=drive-ide0-0-1 \
+-device ide-drive,bus=ide.0,unit=1,drive=drive-ide0-0-1,id=ide0-0-1 \
+-drive file=/dev/HostVG/hdc,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \
+-drive file=/dev/fd0,if=none,id=drive-fdc0-0-0 \
+-global isa-fdc.driveA=drive-fdc0-0-0 \
+-drive file=/dev/fd1,if=none,id=drive-fdc0-0-1 \
+-global isa-fdc.driveB=drive-fdc0-0-1 \
+-device virtio-net-pci,vlan=0,id=net0,mac=00:11:22:33:44:11,bus=pci.0,addr=0x3 \
+-net user,vlan=0,name=hostnet0 \
+-device virtio-net-pci,vlan=1,id=net1,mac=00:11:22:33:44:22,bus=pci.0,addr=0x4 \
+-net user,vlan=1,name=hostnet1 \
+-usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.xml
new file mode 100644
index 0000000..b4d6f4f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-complex.xml
@@ -0,0 +1,65 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='cdrom'/>
+ <boot dev='network'/>
+ <boot dev='hd'/>
+ <boot dev='fd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='file' device='disk'>
+ <source file='/tmp/vdb.img'/>
+ <target dev='vdb' bus='virtio'/>
+ </disk>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/hdb'/>
+ <target dev='hdb' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='1'/>
+ </disk>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/hda'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <source file='/tmp/vda.img'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ <disk type='block' device='cdrom'>
+ <source dev='/dev/HostVG/hdc'/>
+ <target dev='hdc' bus='ide'/>
+ <address type='drive' controller='0' bus='1' unit='0'/>
+ </disk>
+ <disk type='block' device='floppy'>
+ <source dev='/dev/fd1'/>
+ <target dev='fdb' bus='fdc'/>
+ <address type='drive' controller='0' bus='0' unit='1'/>
+ </disk>
+ <disk type='block' device='floppy'>
+ <source dev='/dev/fd0'/>
+ <target dev='fda' bus='fdc'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <controller type='fdc' index='0'/>
+ <controller type='ide' index='0'/>
+ <interface type='user'>
+ <mac address='00:11:22:33:44:11'/>
+ <model type='virtio'/>
+ </interface>
+ <interface type='user'>
+ <mac address='00:11:22:33:44:22'/>
+ <model type='virtio'/>
+ </interface>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.args
new file mode 100644
index 0000000..5074e32
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.args
@@ -0,0 +1,13 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-drive file=/dev/cdrom,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,bootindex=1 \
+-usb \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.xml
new file mode 100644
index 0000000..bc1da8a
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive-bootindex.xml
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='cdrom'/>
+ <bootmenu enable='no'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='cdrom'>
+ <source dev='/dev/cdrom'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='1' unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.args
new file mode 100644
index 0000000..42b48e5
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.args
@@ -0,0 +1,14 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-boot order=d,menu=off \
+-drive file=/dev/cdrom,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \
+-usb \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.xml
new file mode 100644
index 0000000..bc1da8a
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-disable-drive.xml
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='cdrom'/>
+ <bootmenu enable='no'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='cdrom'>
+ <source dev='/dev/cdrom'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='1' unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.args b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.args
new file mode 100644
index 0000000..5d7c4a4
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.args
@@ -0,0 +1,14 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-boot order=d,menu=on \
+-drive file=/dev/cdrom,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \
+-usb \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.xml b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.xml
new file mode 100644
index 0000000..c35b2bd
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable.xml
@@ -0,0 +1,27 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='cdrom'/>
+ <bootmenu enable='yes'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='cdrom'>
+ <source dev='/dev/cdrom'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='1' unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.args
new file mode 100644
index 0000000..357723f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.args
@@ -0,0 +1,18 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test \
+/usr/bin/qemu \
+-S \
+-M pc \
+-m 214 \
+-smp 1 \
+-nographic \
+-nodefaults \
+-monitor unix:/tmp/test-monitor,server,nowait \
+-no-acpi \
+-drive file=/dev/HostVG/QEMUGuest1,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=2 \
+-drive file=/dev/HostVG/QEMUGuest2,if=none,media=cdrom,id=drive-ide0-1-0 \
+-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,bootindex=1 \
+-drive file=/dev/fd0,if=none,id=drive-fdc0-0-0 \
+-global isa-fdc.driveA=drive-fdc0-0-0 \
+-global isa-fdc.bootindexA=3 \
+-usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.xml
new file mode 100644
index 0000000..a7e08fd
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-no-boot.xml
@@ -0,0 +1,38 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219100</memory>
+ <currentMemory>219100</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='cdrom'/>
+ <boot dev='hd'/>
+ <boot dev='fd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <disk type='block' device='cdrom'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hdc' bus='ide'/>
+ <address type='drive' controller='0' bus='1' unit='0'/>
+ </disk>
+ <disk type='block' device='floppy'>
+ <source dev='/dev/fd0'/>
+ <target dev='fda' bus='fdc'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <controller type='fdc' index='0'/>
+ <controller type='ide' index='0'/>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index cbd9a5f..a0f3354 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -265,9 +265,24 @@ mymain(void)
DO_TEST("boot-network", false, NONE);
DO_TEST("boot-floppy", false, NONE);
DO_TEST("boot-multi", false, QEMU_CAPS_BOOT_MENU);
+ DO_TEST("boot-menu-enable", false,
+ QEMU_CAPS_BOOT_MENU, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE);
+ DO_TEST("boot-menu-enable", false,
+ QEMU_CAPS_BOOT_MENU, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+ QEMU_CAPS_BOOTINDEX);
DO_TEST("boot-menu-disable", false, QEMU_CAPS_BOOT_MENU);
+ DO_TEST("boot-menu-disable-drive", false,
+ QEMU_CAPS_BOOT_MENU, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE);
+ DO_TEST("boot-menu-disable-drive-bootindex", false,
+ QEMU_CAPS_BOOT_MENU, QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE,
+ QEMU_CAPS_BOOTINDEX);
DO_TEST("boot-order", false,
QEMU_CAPS_BOOTINDEX, QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE);
+ DO_TEST("boot-complex", false,
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_BOOT);
+ DO_TEST("boot-complex-bootindex", false,
+ QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_BOOT,
+ QEMU_CAPS_BOOTINDEX);
DO_TEST("bootloader", true, QEMU_CAPS_DOMID);
DO_TEST("clock-utc", false, NONE);
DO_TEST("clock-localtime", false, NONE);
@@ -323,6 +338,8 @@ mymain(void)
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT);
DO_TEST("disk-drive-network-sheepdog", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_FORMAT);
+ DO_TEST("disk-drive-no-boot", false,
+ QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_BOOTINDEX);
DO_TEST("disk-usb", false, NONE);
DO_TEST("disk-usb-device", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
--
1.7.5.3
13 years, 10 months
[libvirt] [libvirt-php] - zend_mm_heap corrupted
by Henrik Jönsson
[libvirt-php]
Hello!
I am using Libvirt-php for a private project, i do however have a problem
that seems to occur when i call any function that returns a domain resource.
I have gotten 3 different errors so far. First i had a problem with php
memory usage going extreme(2gb), then i have had some apache segmentation
fault ending up in apache killing the process. I have also had zend_mm_heap
corrupted which i think is the most common one.
I have tried with Ubuntu 10.04, 10.10 and 11.04 repository versions of
Apache. Other than that i am using libvirt version 0.9.1 and libvirt-php
version 0.4.1. This is within the contexts of Drupal as i am using the code
in a Drupal module.
I have checked out the source code for libvirt-php but since i am no C/C++
developer i have a hard time figuring out what the issue might be. Some help
would be greatly appreciated. :)
Best Regards!
/Henrik
13 years, 10 months
[libvirt] RFC (v3): Add virDomainBlockPull API family to libvirt
by Adam Litke
I didn't receive too many comments on the last round. That probably means
everybody has been busy with the 0.9.2 release. I think this is ready to be
committed but we can wait until the qemu side has gone up (which should happen
any day now).
Changes since V2:
- Rebased
- Ensure error messages are consistent between JSON and Text interfaces
- Added additional tests to the sample test bucket
Changes since V1:
- Rebased to incorporate changes to generator and
removal of static driver structure initializers
- Other small fixups suggested by Matthias Bolte
To help speed the provisioning process for large domains, new QED disks are
created with backing to a template image. These disks are configured with copy
on read such that blocks that are read from the backing file are copied to the
new disk. This reduces I/O over a potentially costly path to the backing
image.
In such a configuration, there is a desire to remove the dependency on the
backing image as the domain runs. To accomplish this, qemu will provide an
interface to perform sequential copy on read operations during normal VM
operation. Once all data has been copied, the disk image's link to the backing
file is removed.
The virDomainBlockPull API family brings this functionality to libvirt.
virDomainBlockPullAll() instructs the hypervisor to stream the entire device in
the background. Progress of this operation can be checked with the function
virDomainBlockPullInfo(). An ongoing stream can be cancelled with
virDomainBlockPullAbort(). If a more controlled IO rate is desired,
virDomainBlockPull() can be used to perform a single increment of IO.
Subsequent calls to this function will automatically stream the appropriate
next increment until the disk has been fully populated.
An event (VIR_DOMAIN_EVENT_ID_BLOCK_PULL) will be emitted when a disk has been
fully populated or if a BlockPullAll() operation was terminated due to an
error. This event is useful to avoid polling on virDomainBlockPullInfo() for
completion and could also be used by the security driver to revoke access to
the backing file when it is no longer needed.
make check: PASS
make syntax-check: PASS
make -C tests valgrind: PASS
I am testing this API with Python Unittest (see the last patch).
[PATCH 1/8] Add new API virDomainBlockPull* to headers
[PATCH 2/8] virDomainBlockPull: Implement the main entry points
[PATCH 3/8] Add virDomainBlockPull support to the remote driver
[PATCH 4/8] Implement virDomainBlockPull for the qemu driver
[PATCH 5/8] Enable the virDomainBlockPull API in virsh
[PATCH 6/8] Enable virDomainBlockPull in the python API.
[PATCH 7/8] Asynchronous event for BlockPull completion
[PATCH 8/8] test: Python Unittests for DomainBlockPull API
13 years, 10 months
[libvirt] [PATCH] spice: add disableCopyPaste property
by Eric Blake
From: Marc-André Lureau <marcandre.lureau(a)redhat.com>
>From a security pov copy and paste between the guest and the client is not
always desirable. So we need to be able to enable/disable this. The best place
to do this from an administration pov is on the hypervisor, so the qemu cmdline
is getting a spice disable-copy-paste option, see bug 693645. Example qemu
invocation:
qemu -spice port=5932,disable-ticketing,disable-copy-paste
https://bugzilla.redhat.com/show_bug.cgi?id=693661
---
docs/formatdomain.html.in | 8 +++++++-
docs/schemas/domain.rng | 8 ++++++++
src/conf/domain_conf.c | 11 +++++++++++
src/conf/domain_conf.h | 1 +
src/qemu/qemu_command.c | 2 ++
.../qemuxml2argv-graphics-spice-compression.xml | 2 +-
.../qemuxml2argv-graphics-spice-qxl-vga.xml | 2 +-
.../qemuxml2argv-graphics-spice-timeout.xml | 2 +-
.../qemuxml2argv-graphics-spice.args | 2 +-
.../qemuxml2argv-graphics-spice.xml | 2 +-
10 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 98fb2b4..61af08e 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1833,7 +1833,7 @@ qemu-kvm -net nic,model=? /dev/null
and <span class="since">since 0.8.8</span>: <code>smartcard</code>.
</p>
<pre>
- <graphics type='spice' port='-1' tlsPort='-1' autoport='yes'>
+ <graphics type='spice' port='-1' tlsPort='-1' autoport='yes' disableCopyPaste='no'>
<channel name='main' mode='secure'/>
<channel name='record' mode='insecure'/>
<image compression='auto_glz'/>
@@ -1862,6 +1862,12 @@ qemu-kvm -net nic,model=? /dev/null
of <code>filter</code>, <code>all</code>
or <code>off</code>, <span class="since">since 0.9.2</span>.
</p>
+ <p>
+ Copy & Paste from guest to client (via Spice agent)
+ can be disabled by setting
+ the <code>disableCopyPaste</code> property
+ to <code>yes</code>, <span class="since">since 0.9.2</span>.
+ </>
</dd>
<dt><code>"rdp"</code></dt>
<dd>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 0be0371..b2333d5 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1293,6 +1293,14 @@
<data type="dateTime"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="disableCopyPaste">
+ <choice>
+ <value>yes</value>
+ <value>no</value>
+ </choice>
+ </attribute>
+ </optional>
<interleave>
<zeroOrMore>
<element name="channel">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 65d4f89..61377c3 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4099,6 +4099,7 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) {
char *port = virXMLPropString(node, "port");
char *tlsPort;
char *autoport;
+ char *disableCopyPaste;
if (port) {
if (virStrToLong_i(port, NULL, 10, &def->data.spice.port) < 0) {
@@ -4143,6 +4144,13 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) {
!def->data.spice.listenAddr[0])
VIR_FREE(def->data.spice.listenAddr);
+ if ((disableCopyPaste = virXMLPropString(node, "disableCopyPaste")) != NULL) {
+ if (STREQ(disableCopyPaste, "yes")) {
+ def->data.spice.disableCopyPaste = true;
+ }
+ VIR_FREE(disableCopyPaste);
+ }
+
if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth) < 0)
goto error;
@@ -9190,6 +9198,9 @@ virDomainGraphicsDefFormat(virBufferPtr buf,
virBufferEscapeString(buf, " keymap='%s'",
def->data.spice.keymap);
+ virBufferAsprintf(buf, " disableCopyPaste='%s'",
+ def->data.spice.disableCopyPaste ? "yes" : "no");
+
virDomainGraphicsAuthDefFormatAttr(buf, &def->data.spice.auth, flags);
break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 41c8136..9566d51 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -757,6 +757,7 @@ struct _virDomainGraphicsDef {
int zlib;
int playback;
int streaming;
+ bool disableCopyPaste;
} spice;
} data;
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index cb81354..8261088 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4161,6 +4161,8 @@ qemuBuildCommandLine(virConnectPtr conn,
if (def->graphics[0]->data.spice.streaming)
virBufferAsprintf(&opt, ",streaming-video=%s",
virDomainGraphicsSpiceStreamingModeTypeToString(def->graphics[0]->data.spice.streaming));
+ if (def->graphics[0]->data.spice.disableCopyPaste)
+ virBufferAddLit(&opt, ",disable-copy-paste");
virCommandAddArg(cmd, "-spice");
virCommandAddArgBuffer(cmd, &opt);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-compression.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-compression.xml
index 64a6890..e502216 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-compression.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-compression.xml
@@ -21,7 +21,7 @@
</disk>
<controller type='ide' index='0'/>
<input type='mouse' bus='ps2'/>
- <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'>
+ <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1' disableCopyPaste='no'>
<image compression='auto_glz'/>
<jpeg compression='auto'/>
<zlib compression='auto'/>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.xml
index a38550c..0075d26 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-qxl-vga.xml
@@ -21,7 +21,7 @@
</disk>
<controller type='ide' index='0'/>
<input type='mouse' bus='ps2'/>
- <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'>
+ <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1' disableCopyPaste='no'>
<channel name='main' mode='secure'/>
<channel name='inputs' mode='insecure'/>
</graphics>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml
index 4c0c57e..6b13d6b 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-timeout.xml
@@ -71,7 +71,7 @@
</console>
<input type='tablet' bus='usb'/>
<input type='mouse' bus='ps2'/>
- <graphics type='spice' port='5900' autoport='no' passwd='sercet' passwdValidTo='2011-05-31T16:11:22'/>
+ <graphics type='spice' port='5900' autoport='no' disableCopyPaste='no' passwd='sercet' passwdValidTo='2011-05-31T16:11:22'/>
<sound model='ac97'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</sound>
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
index 084a100..c9fdb99 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
@@ -4,6 +4,6 @@ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \
/dev/HostVG/QEMUGuest1 -usb -spice port=5903,tls-port=5904,addr=127.0.0.1,\
x509-dir=/etc/pki/libvirt-spice,tls-channel=main,plaintext-channel=inputs,\
image-compression=auto_glz,jpeg-wan-compression=auto,zlib-glz-wan-compression=auto,\
-playback-compression=on,streaming-video=filter -vga \
+playback-compression=on,streaming-video=filter,disable-copy-paste -vga \
qxl -global qxl.vram_size=18874368 -device qxl,id=video1,vram_size=33554432,bus=pci.0,addr=0x4 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml
index 0d3dd48..4b5840c 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml
@@ -21,7 +21,7 @@
</disk>
<controller type='ide' index='0'/>
<input type='mouse' bus='ps2'/>
- <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'>
+ <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1' disableCopyPaste='yes'>
<channel name='main' mode='secure'/>
<channel name='inputs' mode='insecure'/>
<image compression='auto_glz'/>
--
1.7.1
13 years, 10 months
[libvirt] [PATCHv7 0/12] Add virNodeGet{CPU,Memory}Stats() API
by Minoru Usui
Hi, everyone.
I re-wrote virNodeGetCPUStats(), virNodeGetMemoryStats().
This time, I merged two APIs to same patch series.
Changes
v6->v7
- Add cpuNum/cellNum arguments to return specified cpu/cell statistics only.
v5->v6
- Rename API name to virNodeGetCPUStats()
- virsh nodecpustats subcommand returns raw/absolute cputime value by default,
and add --percent option for printing utilization.
v4->v5
- Rebase latest libvirt GIT tree.
v3->v4
- Rebase this patch like virDomainGetMemoryParameters() from v2 patches.
(drop v3 patches except virsh subcommand)
- Rename API name to virNodeGetCPUTimeParameters()
v2->v3
- Change user I/F. It is able to request what the user want by the @flags.
- Minor change of virsh nodecputime I/F.
v1->v2
- Change user I/F like virDomainGetMemoryStats()
- It can return either cpu utilization or cumulative cpu time of the node
depends on each driver.
Minoru Usui (12):
[v7] virNodeGetCPUStats: Expose new API
[v7] virNodeGetCPUStats: Define internal driver API
[v7] virNodeGetCPUTime: Implement public API
[v7] virNodeGetCPUStats: Implement remote protocol
[v7] virNodeGetCPUStats: Implement virsh support
[v7] virNodeGetCPUStats: Implement linux support
[v2] virNodeGetMemoryStats: Expose new API
[v2] virNodeGetMemoryStats: Define internal driver API
[v2] virNodeGetMemoryStats: Implement public API
[v2] virNodeGetMemoryStats: Implement remote protocol
[v2] virNodeGetMemoryStats: Implement virsh support
[v2] virNodeGetMemoryStats: Implement linux support
daemon/remote.c | 154 ++++++++++++++++++++++
include/libvirt/libvirt.h.in | 153 +++++++++++++++++++++-
src/driver.h | 18 +++
src/libvirt.c | 178 +++++++++++++++++++++++++
src/libvirt_private.syms | 2 +
src/libvirt_public.syms | 6 +
src/lxc/lxc_driver.c | 2 +
src/nodeinfo.c | 299 ++++++++++++++++++++++++++++++++++++++++++
src/nodeinfo.h | 11 ++-
src/qemu/qemu_driver.c | 2 +
src/remote/remote_driver.c | 132 +++++++++++++++++++
src/remote/remote_protocol.x | 42 ++++++-
src/uml/uml_driver.c | 2 +
tools/virsh.c | 196 +++++++++++++++++++++++++++
tools/virsh.pod | 12 ++
15 files changed, 1206 insertions(+), 3 deletions(-)
--
Minoru Usui <usui(a)mxm.nes.nec.co.jp>
13 years, 10 months
[libvirt] [PATCH] Skip nodeinfo test on non intel architectures
by Guido Günther
since the testfiles assume a /proc/cpuinfo specific to this
architecture. We e.g. can't parse the number of cores on other
architectures.
O.k. to apply?
Cheers,
-- Guido
---
tests/nodeinfotest.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/tests/nodeinfotest.c b/tests/nodeinfotest.c
index b4e81b3..71e2926 100644
--- a/tests/nodeinfotest.c
+++ b/tests/nodeinfotest.c
@@ -11,7 +11,9 @@
#include "util.h"
#include "files.h"
-#ifndef __linux__
+#if ! (defined __linux__ && (defined(__x86_64__) || \
+ defined(__amd64__) || \
+ defined(__i386__)))
static int
mymain(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
--
1.7.5.3
13 years, 10 months
[libvirt] [PATCH v2] Fix autostart flag when loading running domains
by Michael Chapman
Drivers load running persistent and transient domain configs before
inactive persistent domain configs, however only the latter would set a
domain's autostart flag. This mismatch between the loaded and on-disk
state could later cause problems with "virsh autostart":
# virsh autostart example
error: Failed to mark domain example as autostarted
error: Failed to create symlink '/etc/libvirt/qemu/autostart/example.xml to '/etc/libvirt/qemu/example.xml': File exists
This patch ensures the autostart flag is set correctly even when the
domain is already defined.
Fixes:
https://bugzilla.redhat.com/show_bug.cgi?id=632100
https://bugzilla.redhat.com/show_bug.cgi?id=675319
v1 -> v2:
- free autostartLink
- fixed comment
Signed-off-by: Michael Chapman <mike(a)very.puzzling.org>
---
src/conf/domain_conf.c | 19 +++++++++++--------
1 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 0d9fef4..aa306fe 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -9859,21 +9859,24 @@ static virDomainObjPtr virDomainLoadConfig(virCapsPtr caps,
VIR_DOMAIN_XML_INACTIVE)))
goto error;
- /* if the domain is already in our hashtable, we don't need to do
- * anything further
+ if ((autostartLink = virDomainConfigFile(autostartDir, name)) == NULL)
+ goto error;
+
+ if ((autostart = virFileLinkPointsTo(autostartLink, configFile)) < 0)
+ goto error;
+
+ /* if the domain is already in our hashtable, we only need to
+ * update the autostart flag
*/
if ((dom = virDomainFindByUUID(doms, def->uuid))) {
+ dom->autostart = autostart;
+
VIR_FREE(configFile);
+ VIR_FREE(autostartLink);
virDomainDefFree(def);
return dom;
}
- if ((autostartLink = virDomainConfigFile(autostartDir, name)) == NULL)
- goto error;
-
- if ((autostart = virFileLinkPointsTo(autostartLink, configFile)) < 0)
- goto error;
-
if (!(dom = virDomainAssignDef(caps, doms, def, false)))
goto error;
--
1.7.4.4
13 years, 10 months
[libvirt] [PATCH v2] virsh: Increase device-detach intelligence
by Michal Prívozník
Up to now users have to give a full XML description on input when
device-detaching. If they omitted something it lead to unclear
error messages (like generated MAC wasn't found, etc.).
With this patch users can specify only those information which
specify one device sufficiently precise. Remaining information is
completed from domain.
---
diff to v1:
-rebase to current HEAD
-add a little bit comments
tools/virsh.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 250 insertions(+), 16 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index d98be1c..5c2634c 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -9302,6 +9302,226 @@ cmdAttachDevice(vshControl *ctl, const vshCmd *cmd)
return true;
}
+/**
+ * Check if n1 is superset of n2, meaning n1 contains all elements and
+ * attributes as n2 at lest. Including children.
+ * @n1 first node
+ * @n2 second node
+ * return 1 in case n1 covers n2, 0 otherwise.
+ */
+static int
+vshNodeIsSuperset(xmlNodePtr n1, xmlNodePtr n2) {
+ xmlNodePtr child1, child2;
+ xmlAttrPtr attr1, attr2;
+ int found;
+
+ if (!n1 && !n2)
+ return 1;
+
+ if (!n1 || !n2)
+ return 0;
+
+ if (!xmlStrEqual(n1->name, n2->name))
+ return 0;
+
+ /* Iterate over n2 attributes and check if n1 contains them*/
+ attr2 = n2->properties;
+ while (attr2) {
+ if (attr2->type == XML_ATTRIBUTE_NODE) {
+ attr1 = n1->properties;
+ found = 0;
+ while (attr1) {
+ if (xmlStrEqual(attr1->name, attr2->name)) {
+ found = 1;
+ break;
+ }
+ attr1 = attr1->next;
+ }
+ if (!found)
+ return 0;
+ if (!xmlStrEqual(BAD_CAST virXMLPropString(n1, (const char *) attr1->name),
+ BAD_CAST virXMLPropString(n2, (const char *) attr2->name)))
+ return 0;
+ }
+ attr2 = attr2->next;
+ }
+
+ /* and now iterate over n2 children */
+ child2 = n2->children;
+ while (child2) {
+ if (child2->type == XML_ELEMENT_NODE) {
+ child1 = n1->children;
+ found = 0;
+ while (child1) {
+ if (child1->type == XML_ELEMENT_NODE &&
+ xmlStrEqual(child1->name, child2->name)) {
+ found = 1;
+ break;
+ }
+ child1 = child1->next;
+ }
+ if (!found)
+ return 0;
+ if (!vshNodeIsSuperset(child1, child2))
+ return 0;
+ }
+ child2 = child2->next;
+ }
+
+ return 1;
+}
+
+/**
+ * To given domain and (probably incomplete) device XML specification try to
+ * find such device in domain and complete missing parts. This is however
+ * possible when given device XML is sufficiently precise so it addresses only
+ * one device.
+ * @ctl vshControl for error messages printing
+ * @dom domain
+ * @oldXML device XML before
+ * @newXML and after completion
+ * Returns -2 when no such device exists in domain, -3 when given XML selects many
+ * (is too ambiguous), 0 in case of success. Otherwise returns -1. @newXML
+ * is touched only in case of success.
+ */
+static int
+vshCompleteXMLFromDomain(vshControl *ctl, virDomainPtr dom, char *oldXML,
+ char **newXML) {
+ int funcRet = -1;
+ char *domXML = NULL;
+ xmlDocPtr domDoc = NULL, devDoc = NULL;
+ xmlNodePtr node = NULL;
+ xmlXPathContextPtr domCtxt = NULL, devCtxt = NULL;
+ xmlNodePtr *devices = NULL;
+ xmlSaveCtxtPtr sctxt = NULL;
+ int devices_size;
+ char *xpath;
+ xmlBufferPtr buf = NULL;
+
+ if (!(domXML = virDomainGetXMLDesc(dom, 0))) {
+ vshError(ctl, _("couldn't get XML description of domain %s"),
+ virDomainGetName(dom));
+ goto cleanup;
+ }
+
+ if (!(domDoc = xmlReadDoc(BAD_CAST domXML, "domain.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
+ vshError(ctl, "%s", _("could not parse domain XML"));
+ goto cleanup;
+ }
+
+ if (!(devDoc = xmlReadDoc(BAD_CAST oldXML, "device.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
+ vshError(ctl, "%s", _("could not parse device XML"));
+ goto cleanup;
+ }
+
+ node = xmlDocGetRootElement(domDoc);
+ if (!node) {
+ vshError(ctl, "%s", _("failed to get domain root element"));
+ goto cleanup;
+ }
+
+ domCtxt = xmlXPathNewContext(domDoc);
+ if (!domCtxt) {
+ vshError(ctl, "%s", _("failed to create context on domain XML"));
+ goto cleanup;
+ }
+ domCtxt->node = node;
+
+ node = xmlDocGetRootElement(devDoc);
+ if (!node) {
+ vshError(ctl, "%s", _("failed to get device root element"));
+ goto cleanup;
+ }
+
+ devCtxt = xmlXPathNewContext(devDoc);
+ if (!devCtxt) {
+ vshError(ctl, "%s", _("failed to create context on device XML"));
+ goto cleanup;
+ }
+ devCtxt->node = node;
+
+ buf = xmlBufferCreate();
+ if (!buf) {
+ vshError(ctl, "%s", _("out of memory"));
+ goto cleanup;
+ }
+
+ xmlBufferCat(buf, BAD_CAST "/domain/devices/");
+ xmlBufferCat(buf, node->name);
+ xpath = (char *) xmlBufferContent(buf);
+ /* Get all possible devices */
+ devices_size = virXPathNodeSet(xpath, domCtxt, &devices);
+ xmlBufferEmpty(buf);
+
+ if (devices_size < 0) {
+ /* error */
+ vshError(ctl, "%s", _("error when selecting nodes"));
+ goto cleanup;
+ } else if (devices_size == 0) {
+ /* no such device */
+ funcRet = -2;
+ goto cleanup;
+ }
+
+ /* and refine */
+ int i = 0;
+ while (i < devices_size) {
+ if (!vshNodeIsSuperset(devices[i], node)) {
+ if (devices_size == 1) {
+ VIR_FREE(devices);
+ devices_size = 0;
+ } else {
+ memmove(devices + i, devices + i + 1,
+ sizeof(*devices) * (devices_size-i-1));
+ devices_size--;
+ if (VIR_REALLOC_N(devices, devices_size) < 0) {
+ /* ignore, harmless */
+ }
+ }
+ } else {
+ i++;
+ }
+ }
+
+ if (!devices_size) {
+ /* no such device */
+ funcRet = -2;
+ goto cleanup;
+ } else if (devices_size > 1) {
+ /* ambiguous */
+ funcRet = -3;
+ goto cleanup;
+ }
+
+ if (newXML) {
+ sctxt = xmlSaveToBuffer(buf, NULL, 0);
+ if (!sctxt) {
+ vshError(ctl, "%s", _("failed to create document saving context"));
+ goto cleanup;
+ }
+
+ xmlSaveTree(sctxt, devices[0]);
+ xmlSaveClose(sctxt);
+ *newXML = (char *) xmlBufferContent(buf);
+ buf->content = NULL;
+ }
+
+ funcRet = 0;
+
+cleanup:
+ xmlBufferFree(buf);
+ VIR_FREE(devices);
+ xmlXPathFreeContext(devCtxt);
+ xmlXPathFreeContext(domCtxt);
+ xmlFreeDoc(devDoc);
+ xmlFreeDoc(domDoc);
+ VIR_FREE(domXML);
+ return funcRet;
+}
/*
* "detach-device" command
@@ -9322,10 +9542,11 @@ static const vshCmdOptDef opts_detach_device[] = {
static bool
cmdDetachDevice(vshControl *ctl, const vshCmd *cmd)
{
- virDomainPtr dom;
+ virDomainPtr dom = NULL;
const char *from = NULL;
- char *buffer;
+ char *buffer = NULL, *new_buffer = NULL;
int ret;
+ bool funcRet = false;
unsigned int flags;
if (!vshConnectionUsability(ctl, ctl->conn))
@@ -9334,37 +9555,50 @@ cmdDetachDevice(vshControl *ctl, const vshCmd *cmd)
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return false;
- if (vshCommandOptString(cmd, "file", &from) <= 0) {
- virDomainFree(dom);
- return false;
- }
+ if (vshCommandOptString(cmd, "file", &from) <= 0)
+ goto cleanup;
if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) {
virshReportError(ctl);
- virDomainFree(dom);
- return false;
+ goto cleanup;
+ }
+
+ ret = vshCompleteXMLFromDomain(ctl, dom, buffer, &new_buffer);
+ if (ret < 0) {
+ if (ret == -2) {
+ vshError(ctl, _("no such device in %s"), virDomainGetName(dom));
+ } else if (ret == -3) {
+ vshError(ctl, "%s", _("given XML selects too many devices. "
+ "Please, be more specific"));
+ } else {
+ /* vshCompleteXMLFromDomain() already printed error message,
+ * so nothing to do here. */
+ }
+ goto cleanup;
}
if (vshCommandOptBool(cmd, "persistent")) {
flags = VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
if (virDomainIsActive(dom) == 1)
flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
- ret = virDomainDetachDeviceFlags(dom, buffer, flags);
+ ret = virDomainDetachDeviceFlags(dom, new_buffer, flags);
} else {
- ret = virDomainDetachDevice(dom, buffer);
+ ret = virDomainDetachDevice(dom, new_buffer);
}
- VIR_FREE(buffer);
if (ret < 0) {
vshError(ctl, _("Failed to detach device from %s"), from);
- virDomainFree(dom);
- return false;
- } else {
- vshPrint(ctl, "%s", _("Device detached successfully\n"));
+ goto cleanup;
}
+ vshPrint(ctl, "%s", _("Device detached successfully\n"));
+ funcRet = true;
+
+cleanup:
+ VIR_FREE(new_buffer);
+ VIR_FREE(buffer);
virDomainFree(dom);
- return true;
+ return funcRet;
}
--
1.7.5.rc3
13 years, 10 months
[libvirt] [PATCH v2] Add support for network filter code in LXC driver
by Daniel P. Berrange
The LXC driver networking uses veth device pairs. These can
be easily hooked into the network filtering code.
* src/lxc/lxc_driver.c: Add calls to setup/teardown nwfilter
New in v2:
- Add missing hooks for automatic rebuild of filters for
online guests
---
src/lxc/lxc_driver.c | 40 ++++++++++++++++++++++++++++++++++++++--
1 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 9ef75f5..e8ad3f0 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -52,7 +52,7 @@
#include "hooks.h"
#include "files.h"
#include "fdstream.h"
-
+#include "domain_nwfilter.h"
#define VIR_FROM_THIS VIR_FROM_LXC
@@ -1027,6 +1027,8 @@ static void lxcVmCleanup(lxc_driver_t *driver,
vethDelete(vm->def->nets[i]->ifname);
}
+ virDomainConfVMNWFilterTeardown(vm);
+
if (driver->cgroup &&
virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) == 0) {
virCgroupRemove(cgroup);
@@ -1146,6 +1148,10 @@ static int lxcSetupInterfaces(virConnectPtr conn,
if (vethInterfaceUpOrDown(parentVeth, 1) < 0)
goto error_exit;
+
+ if (def->nets[i]->filter &&
+ virDomainConfNWFilterInstantiate(conn, def->nets[i]) < 0)
+ goto error_exit;
}
rc = 0;
@@ -1642,8 +1648,10 @@ cleanup:
vethDelete(veths[i]);
VIR_FREE(veths[i]);
}
- if (rc != 0)
+ if (rc != 0) {
VIR_FORCE_CLOSE(priv->monitor);
+ virDomainConfVMNWFilterTeardown(vm);
+ }
VIR_FORCE_CLOSE(parentTty);
VIR_FORCE_CLOSE(handshakefds[0]);
VIR_FORCE_CLOSE(handshakefds[1]);
@@ -2842,6 +2850,33 @@ cleanup:
return ret;
}
+static int
+lxcVMFilterRebuild(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virHashIterator iter, void *data)
+{
+ virHashForEach(lxc_driver->domains.objs, iter, data);
+
+ return 0;
+}
+
+static void
+lxcVMDriverLock(void)
+{
+ lxcDriverLock(lxc_driver);
+}
+
+static void
+lxcVMDriverUnlock(void)
+{
+ lxcDriverUnlock(lxc_driver);
+}
+
+static virNWFilterCallbackDriver lxcCallbackDriver = {
+ .name = "LXC",
+ .vmFilterRebuild = lxcVMFilterRebuild,
+ .vmDriverLock = lxcVMDriverLock,
+ .vmDriverUnlock = lxcVMDriverUnlock,
+};
/* Function Tables */
static virDriver lxcDriver = {
@@ -2911,5 +2946,6 @@ int lxcRegister(void)
{
virRegisterDriver(&lxcDriver);
virRegisterStateDriver(&lxcStateDriver);
+ virNWFilterRegisterCallbackDriver(&lxcCallbackDriver);
return 0;
}
--
1.7.4.4
13 years, 10 months
[libvirt] Request to rename 'destroy' to something milder.
by Kashyap Chamarthy
(please cc me in response as I have not subscribed to this list)
Hi all,
A minor nitpick:
Every-time I suggest someone to do a force shut-down a guest using 'virsh destroy foo' ,
the very first question I get is -- does it _destroy_ my data?
This causes confusion to the inexperienced user and makes him/her suspect that the
data/disk could be destroyed while running 'virsh destroy foo'
Maybe replacing it to a milder name like 'poweroff' or something might help?
Thanks,
Kashyap Chamarthy
13 years, 10 months