[libvirt] [PATCH] Fix sparse volume allocation reporting
by Cole Robinson
I have a sparse volume with a capacity of 1000M, and an allocation of a
little over 750M. 'du' prints the correct sizes, but 'virsh vol-dumpxml'
shows:
<capacity>1048576000</capacity>
<allocation>6406307840</allocation>
This is because we were calculating the allocation size using the
requested fs block size, instead of what stat actually uses as a block
size (DEV_BSIZE in sys/params.h). sys/params.h looks to be present in
mingw32-runtime, so I didn't add a configure check for it.
The attached patch fixes allocation listing for me.
Thanks,
Cole
15 years, 7 months
[libvirt] PATCH: Fix crash / cleanup bugs in sVirt verification
by Daniel P. Berrange
If defining a VM without any <seclabel> element present, the new
verification code will crash as it deferences NULL, so we just need
to skip over that.
Second, if one does a roundtrip of a live VM config
virsh dumpxml foo > foo.xml
virsh define foo.xml
and then stop and start the guest, it will now fail complaining that the
security label is already defined. This is because the XML parser is
mistakenly parsing the 'model' attribute even for VMs whose label is
defined to be dynamic.
This then exposed anothe bug in the qemudStartVMDaemon() method where it
would not properly cleanup after a failed launch, failing to reset the
dynamic allocated security label, and also failing to close a logfil
file descriptor.
This patch fixes all of these problems
Daniel
Index: src/domain_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/domain_conf.c,v
retrieving revision 1.74
diff -u -p -r1.74 domain_conf.c
--- src/domain_conf.c 3 Apr 2009 10:55:51 -0000 1.74
+++ src/domain_conf.c 3 Apr 2009 12:14:54 -0000
@@ -1859,15 +1859,6 @@ virSecurityLabelDefParseXML(virConnectPt
if (virXPathNode(conn, "./seclabel", ctxt) == NULL)
return 0;
- p = virXPathStringLimit(conn, "string(./seclabel/@model)",
- VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
- if (p == NULL) {
- virDomainReportError(conn, VIR_ERR_XML_ERROR,
- "%s", _("missing security model"));
- goto error;
- }
- def->seclabel.model = p;
-
p = virXPathStringLimit(conn, "string(./seclabel/@type)",
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
if (p == NULL) {
@@ -1888,6 +1879,14 @@ virSecurityLabelDefParseXML(virConnectPt
*/
if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC ||
!(flags & VIR_DOMAIN_XML_INACTIVE)) {
+ p = virXPathStringLimit(conn, "string(./seclabel/@model)",
+ VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
+ if (p == NULL) {
+ virDomainReportError(conn, VIR_ERR_XML_ERROR,
+ "%s", _("missing security model"));
+ goto error;
+ }
+ def->seclabel.model = p;
p = virXPathStringLimit(conn, "string(./seclabel/label[1])",
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
@@ -1905,8 +1904,11 @@ virSecurityLabelDefParseXML(virConnectPt
!(flags & VIR_DOMAIN_XML_INACTIVE)) {
p = virXPathStringLimit(conn, "string(./seclabel/imagelabel[1])",
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
- if (p == NULL)
+ if (p == NULL) {
+ virDomainReportError(conn, VIR_ERR_XML_ERROR,
+ _("security imagelabel is missing"));
goto error;
+ }
def->seclabel.imagelabel = p;
}
Index: src/qemu_driver.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_driver.c,v
retrieving revision 1.224
diff -u -p -r1.224 qemu_driver.c
--- src/qemu_driver.c 3 Apr 2009 10:55:51 -0000 1.224
+++ src/qemu_driver.c 3 Apr 2009 12:14:54 -0000
@@ -332,7 +332,7 @@ qemudReconnectVMs(struct qemud_driver *d
}
if ((vm->logfile = qemudLogFD(NULL, driver->logDir, vm->def->name)) < 0)
- return -1;
+ goto next_error;
if (vm->def->id >= driver->nextvmid)
driver->nextvmid = vm->def->id + 1;
@@ -344,9 +344,12 @@ next_error:
/* we failed to reconnect the vm so remove it's traces */
vm->def->id = -1;
qemudRemoveDomainStatus(NULL, driver, vm);
- virDomainDefFree(vm->def);
- vm->def = vm->newDef;
- vm->newDef = NULL;
+ /* Restore orignal def, if we'd loaded a live one */
+ if (vm->newDef) {
+ virDomainDefFree(vm->def);
+ vm->def = vm->newDef;
+ vm->newDef = NULL;
+ }
next:
virDomainObjUnlock(vm);
if (status)
@@ -1319,14 +1322,6 @@ static int qemudStartVMDaemon(virConnect
hookData.vm = vm;
hookData.driver = driver;
- /* If you are using a SecurityDriver with dynamic labelling,
- then generate a security label for isolation */
- if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
- driver->securityDriver &&
- driver->securityDriver->domainGenSecurityLabel &&
- driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0)
- return -1;
-
FD_ZERO(&keepfd);
if (virDomainIsActive(vm)) {
@@ -1335,6 +1330,14 @@ static int qemudStartVMDaemon(virConnect
return -1;
}
+ /* If you are using a SecurityDriver with dynamic labelling,
+ then generate a security label for isolation */
+ if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
+ driver->securityDriver &&
+ driver->securityDriver->domainGenSecurityLabel &&
+ driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0)
+ return -1;
+
if (vm->def->graphics &&
vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
vm->def->graphics->data.vnc.autoport) {
@@ -1342,7 +1345,7 @@ static int qemudStartVMDaemon(virConnect
if (port < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("Unable to find an unused VNC port"));
- return -1;
+ goto cleanup;
}
vm->def->graphics->data.vnc.port = port;
}
@@ -1351,17 +1354,17 @@ static int qemudStartVMDaemon(virConnect
virReportSystemError(conn, errno,
_("cannot create log directory %s"),
driver->logDir);
- return -1;
+ goto cleanup;
}
if((vm->logfile = qemudLogFD(conn, driver->logDir, vm->def->name)) < 0)
- return -1;
+ goto cleanup;
emulator = vm->def->emulator;
if (!emulator)
emulator = virDomainDefDefaultEmulator(conn, vm->def, driver->caps);
if (!emulator)
- return -1;
+ goto cleanup;
/* Make sure the binary we are about to try exec'ing exists.
* Technically we could catch the exec() failure, but that's
@@ -1371,7 +1374,7 @@ static int qemudStartVMDaemon(virConnect
virReportSystemError(conn, errno,
_("Cannot find QEMU binary %s"),
emulator);
- return -1;
+ goto cleanup;
}
if (qemudExtractVersionInfo(emulator,
@@ -1380,21 +1383,17 @@ static int qemudStartVMDaemon(virConnect
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("Cannot determine QEMU argv syntax %s"),
emulator);
- return -1;
+ goto cleanup;
}
if (qemuPrepareHostDevices(conn, vm->def) < 0)
- return -1;
+ goto cleanup;
vm->def->id = driver->nextvmid++;
if (qemudBuildCommandLine(conn, driver, vm,
qemuCmdFlags, &argv, &progenv,
- &tapfds, &ntapfds, migrateFrom) < 0) {
- close(vm->logfile);
- vm->def->id = -1;
- vm->logfile = -1;
- return -1;
- }
+ &tapfds, &ntapfds, migrateFrom) < 0)
+ goto cleanup;
tmp = progenv;
while (*tmp) {
@@ -1457,12 +1456,8 @@ static int qemudStartVMDaemon(virConnect
"%s", _("Unable to daemonize QEMU process"));
ret = -1;
}
- }
-
- if (ret == 0) {
vm->state = migrateFrom ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
- } else
- vm->def->id = -1;
+ }
for (i = 0 ; argv[i] ; i++)
VIR_FREE(argv[i]);
@@ -1479,19 +1474,38 @@ static int qemudStartVMDaemon(virConnect
VIR_FREE(tapfds);
}
- if (ret == 0) {
- if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) ||
- (qemudDetectVcpuPIDs(conn, vm) < 0) ||
- (qemudInitCpus(conn, vm, migrateFrom) < 0) ||
- (qemudInitPasswords(conn, driver, vm) < 0) ||
- (qemudDomainSetMemoryBalloon(conn, vm, vm->def->memory) < 0) ||
- (qemudSaveDomainStatus(conn, qemu_driver, vm) < 0)) {
- qemudShutdownVMDaemon(conn, driver, vm);
- return -1;
- }
+ if (ret == -1)
+ goto cleanup;
+
+ if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) ||
+ (qemudDetectVcpuPIDs(conn, vm) < 0) ||
+ (qemudInitCpus(conn, vm, migrateFrom) < 0) ||
+ (qemudInitPasswords(conn, driver, vm) < 0) ||
+ (qemudDomainSetMemoryBalloon(conn, vm, vm->def->memory) < 0) ||
+ (qemudSaveDomainStatus(conn, qemu_driver, vm) < 0)) {
+ qemudShutdownVMDaemon(conn, driver, vm);
+ ret = -1;
+ /* No need for 'goto cleanup' now since qemudShutdownVMDaemon does enough */
}
return ret;
+
+cleanup:
+ if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
+ VIR_FREE(vm->def->seclabel.model);
+ VIR_FREE(vm->def->seclabel.label);
+ VIR_FREE(vm->def->seclabel.imagelabel);
+ }
+ if (vm->def->graphics &&
+ vm->def->graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
+ vm->def->graphics->data.vnc.autoport)
+ vm->def->graphics->data.vnc.port = -1;
+ if (vm->logfile != -1) {
+ close(vm->logfile);
+ vm->logfile = -1;
+ }
+ vm->def->id = -1;
+ return -1;
}
Index: src/security.c
===================================================================
RCS file: /data/cvs/libvirt/src/security.c,v
retrieving revision 1.3
diff -u -p -r1.3 security.c
--- src/security.c 3 Apr 2009 10:55:51 -0000 1.3
+++ src/security.c 3 Apr 2009 12:14:54 -0000
@@ -33,7 +33,8 @@ virSecurityDriverVerify(virConnectPtr co
unsigned int i;
const virSecurityLabelDefPtr secdef = &def->seclabel;
- if (STREQ(secdef->model, "none"))
+ if (!secdef->model ||
+ STREQ(secdef->model, "none"))
return 0;
for (i = 0; security_drivers[i] != NULL ; i++) {
@@ -42,7 +43,7 @@ virSecurityDriverVerify(virConnectPtr co
}
}
virSecurityReportError(conn, VIR_ERR_XML_ERROR,
- _("invalid security model"));
+ _("invalid security model '%s'"), secdef->model);
return -1;
}
Index: src/security_selinux.c
===================================================================
RCS file: /data/cvs/libvirt/src/security_selinux.c,v
retrieving revision 1.5
diff -u -p -r1.5 security_selinux.c
--- src/security_selinux.c 3 Apr 2009 10:55:51 -0000 1.5
+++ src/security_selinux.c 3 Apr 2009 12:14:54 -0000
@@ -162,11 +162,12 @@ SELinuxGenSecurityLabel(virConnectPtr co
char *scontext = NULL;
int c1 = 0;
int c2 = 0;
- if ( ( vm->def->seclabel.label ) ||
- ( vm->def->seclabel.model ) ||
- ( vm->def->seclabel.imagelabel )) {
- virSecurityReportError(conn, VIR_ERR_ERROR,
- "%s", _("security labellin already defined for VM"));
+
+ if (vm->def->seclabel.label ||
+ vm->def->seclabel.model ||
+ vm->def->seclabel.imagelabel) {
+ virSecurityReportError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("security label already defined for VM"));
return rc;
}
@@ -197,7 +198,7 @@ SELinuxGenSecurityLabel(virConnectPtr co
goto err;
}
vm->def->seclabel.model = strdup(SECURITY_SELINUX_NAME);
- if (! vm->def->seclabel.model) {
+ if (!vm->def->seclabel.model) {
virReportOOMError(conn);
goto err;
}
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
15 years, 7 months
[libvirt] PATCH: Xen PCI device passthrough
by Daniel P. Berrange
This patch implements PCI device passthrough for Xen.
In pci.c there is a fair bit of refactoring to better support both
pcistub.ko and pciback.ko. The latter has two extra sysfs files,
add_slot and remove_slot for associating the driver with a specific
PCI device domain:bus:slot:func address, whereas pcistub can only
associate based on vendor:product ID
The Xen driver gets an implementation of the dettach/reattach APIs
for node devices.
The XML <-> SEXPR conversion gets adapted to cope with PCI devices
The XM <-> XML conversion gets adapted to load/save PCI device info
in /etc/xen config files
Daniel
Index: src/pci.c
===================================================================
RCS file: /data/cvs/libvirt/src/pci.c,v
retrieving revision 1.4
diff -u -p -r1.4 pci.c
--- src/pci.c 3 Mar 2009 17:00:18 -0000 1.4
+++ src/pci.c 30 Mar 2009 13:09:44 -0000
@@ -614,46 +614,80 @@ pciResetDevice(virConnectPtr conn, pciDe
return ret;
}
-static int
-pciBindDeviceToStub(virConnectPtr conn, pciDevice *dev, const char *stub_module)
+
+static void
+pciDriverDir(char *buf, size_t buflen, const char *driver)
{
- char stub_dir[PATH_MAX];
- char path[PATH_MAX];
+ snprintf(buf, buflen, PCI_SYSFS "drivers/%s", driver);
+}
- snprintf(stub_dir, sizeof(stub_dir), PCI_SYSFS "drivers/%s", stub_module);
+static void
+pciDriverFile(char *buf, size_t buflen, const char *driver, const char *file)
+{
+ snprintf(buf, buflen, PCI_SYSFS "drivers/%s/%s", driver, file);
+}
+
+static void
+pciDeviceFile(char *buf, size_t buflen, const char *device, const char *file)
+{
+ snprintf(buf, buflen, PCI_SYSFS "devices/%s/%s", device, file);
+}
- /* Try loading the stub module if it isn't already loaded;
- * Do not return an error if the stub module is not available.
- */
- if (!virFileExists(stub_dir)) {
- const char *const modprobeargv[] = { MODPROBE, stub_module, NULL };
- if (virRun(conn, modprobeargv, NULL) < 0) {
+static const char *
+pciFindStubDriver(virConnectPtr conn)
+{
+ char drvpath[PATH_MAX];
+ int probed = 0;
+
+recheck:
+ pciDriverDir(drvpath, sizeof(drvpath), "pci-stub");
+ if (virFileExists(drvpath))
+ return "pci-stub";
+ pciDriverDir(drvpath, sizeof(drvpath), "pciback");
+ if (virFileExists(drvpath))
+ return "pciback";
+
+ if (!probed) {
+ const char *const stubprobe[] = { MODPROBE, "pci-stub", NULL };
+ const char *const backprobe[] = { MODPROBE, "pciback", NULL };
+
+ probed = 1;
+ if (virRun(conn, stubprobe, NULL) < 0 &&
+ virRun(conn, backprobe, NULL) < 0) {
char ebuf[1024];
- VIR_WARN(_("modprobe %s failed: %s"), stub_module,
+ VIR_WARN(_("failed to load pci-stub or pciback drivers: %s"),
virStrerror(errno, ebuf, sizeof ebuf));
+ return 0;
}
+
+ goto recheck;
}
- if (!virFileExists(stub_dir)) {
- VIR_WARN(_("%s module not available, cannot bind device %s to it"),
- stub_module, dev->name);
- } else {
- /* Add the PCI device ID to the stub's dynamic ID table;
- * this is needed to allow us to bind the device to the stub.
- * Note: if the device is not currently bound to any driver,
- * stub will immediately be bound to the device. Also, note
- * that if a new device with this ID is hotplugged, or if a probe
- * is triggered for such a device, it will also be immediately
- * bound by the stub.
- */
- snprintf(path, sizeof(path), "%s/new_id", stub_dir);
- if (virFileWriteStr(path, dev->id) < 0) {
- virReportSystemError(conn, errno,
- _("Failed to add PCI device ID '%s' to %s"),
- dev->id, stub_module);
- return -1;
- }
+ return NULL;
+}
+
+
+static int
+pciBindDeviceToStub(virConnectPtr conn, pciDevice *dev, const char *driver)
+{
+ char drvdir[PATH_MAX];
+ char path[PATH_MAX];
+
+ /* Add the PCI device ID to the stub's dynamic ID table;
+ * this is needed to allow us to bind the device to the stub.
+ * Note: if the device is not currently bound to any driver,
+ * stub will immediately be bound to the device. Also, note
+ * that if a new device with this ID is hotplugged, or if a probe
+ * is triggered for such a device, it will also be immediately
+ * bound by the stub.
+ */
+ pciDriverFile(path, sizeof(path), driver, "new_id");
+ if (virFileWriteStr(path, dev->id) < 0) {
+ virReportSystemError(conn, errno,
+ _("Failed to add PCI device ID '%s' to %s"),
+ dev->id, driver);
+ return -1;
}
/* If the device is already bound to a driver, unbind it.
@@ -661,77 +695,100 @@ pciBindDeviceToStub(virConnectPtr conn,
* PCI device happens to be IDE controller for the disk hosting
* your root filesystem.
*/
- snprintf(path, sizeof(path),
- PCI_SYSFS "devices/%s/driver/unbind", dev->name);
+ pciDeviceFile(path, sizeof(path), dev->name, "driver/unbind");
if (virFileExists(path) && virFileWriteStr(path, dev->name) < 0) {
virReportSystemError(conn, errno,
_("Failed to unbind PCI device '%s'"), dev->name);
return -1;
}
- if (virFileExists(stub_dir)) {
- /* If the device isn't already bound to pci-stub, try binding it now.
- */
- snprintf(path, sizeof(path), PCI_SYSFS "devices/%s/driver", dev->name);
- if (!virFileLinkPointsTo(path, stub_dir)) {
- snprintf(path, sizeof(path), "%s/bind", stub_dir);
- if (virFileWriteStr(path, dev->name) < 0) {
- virReportSystemError(conn, errno,
- _("Failed to bind PCI device '%s' to %s"),
- dev->name, stub_module);
- return -1;
- }
+ /* If the device isn't already bound to pci-stub, try binding it now.
+ */
+ pciDriverDir(drvdir, sizeof(drvdir), driver);
+ pciDeviceFile(path, sizeof(path), dev->name, "driver");
+ if (!virFileLinkPointsTo(path, drvdir)) {
+ /* Xen's pciback.ko wants you to use new_slot first */
+ pciDriverFile(path, sizeof(path), driver, "new_slot");
+ if (virFileExists(path) && virFileWriteStr(path, dev->name) < 0) {
+ virReportSystemError(conn, errno,
+ _("Failed to add slot for PCI device '%s' to %s"),
+ dev->name, driver);
+ return -1;
}
- /* If 'remove_id' exists, remove the device id from pci-stub's dynamic
- * ID table so that 'drivers_probe' works below.
- */
- snprintf(path, sizeof(path), "%s/remove_id", stub_dir);
- if (virFileExists(path) && virFileWriteStr(path, dev->id) < 0) {
+ pciDriverFile(path, sizeof(path), driver, "bind");
+ if (virFileWriteStr(path, dev->name) < 0) {
virReportSystemError(conn, errno,
- _("Failed to remove PCI ID '%s' from %s"),
- dev->id, stub_module);
+ _("Failed to bind PCI device '%s' to %s"),
+ dev->name, driver);
return -1;
}
}
+ /* If 'remove_id' exists, remove the device id from pci-stub's dynamic
+ * ID table so that 'drivers_probe' works below.
+ */
+ pciDriverFile(path, sizeof(path), driver, "remove_id");
+ if (virFileExists(path) && virFileWriteStr(path, dev->id) < 0) {
+ virReportSystemError(conn, errno,
+ _("Failed to remove PCI ID '%s' from %s"),
+ dev->id, driver);
+ return -1;
+ }
+
return 0;
}
int
pciDettachDevice(virConnectPtr conn, pciDevice *dev)
{
- return pciBindDeviceToStub(conn, dev, "pci-stub");
+ const char *driver = pciFindStubDriver(conn);
+ if (!driver) {
+ pciReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot find any PCI stub module"));
+ return -1;
+ }
+
+ return pciBindDeviceToStub(conn, dev, driver);
}
static int
-pciUnBindDeviceFromStub(virConnectPtr conn, pciDevice *dev, const char *stub_module)
+pciUnBindDeviceFromStub(virConnectPtr conn, pciDevice *dev, const char *driver)
{
- char stub_dir[PATH_MAX];
+ char drvdir[PATH_MAX];
char path[PATH_MAX];
- snprintf(stub_dir, sizeof(stub_dir), PCI_SYSFS "drivers/%s", stub_module);
-
/* If the device is bound to stub, unbind it.
*/
- snprintf(path, sizeof(path), PCI_SYSFS "devices/%s/driver", dev->name);
- if (virFileExists(stub_dir) && virFileLinkPointsTo(path, stub_dir)) {
- snprintf(path, sizeof(path), "%s/unbind", stub_dir);
+ pciDriverDir(drvdir, sizeof(drvdir), driver);
+ pciDeviceFile(path, sizeof(path), dev->name, "driver");
+ if (virFileExists(drvdir) && virFileLinkPointsTo(path, drvdir)) {
+ pciDriverFile(path, sizeof(path), driver, "unbind");
if (virFileWriteStr(path, dev->name) < 0) {
virReportSystemError(conn, errno,
_("Failed to bind PCI device '%s' to %s"),
- dev->name, stub_module);
+ dev->name, driver);
return -1;
}
}
+ /* Xen's pciback.ko wants you to use remove_slot on the specific device */
+ pciDriverFile(path, sizeof(path), driver, "remove_slot");
+ if (virFileExists(path) && virFileWriteStr(path, dev->name) < 0) {
+ virReportSystemError(conn, errno,
+ _("Failed to remove slot for PCI device '%s' to %s"),
+ dev->name, driver);
+ return -1;
+ }
+
+
/* Trigger a re-probe of the device is not in the stub's dynamic
* ID table. If the stub is available, but 'remove_id' isn't
* available, then re-probing would just cause the device to be
* re-bound to the stub.
*/
- snprintf(path, sizeof(path), "%s/remove_id", stub_dir);
- if (!virFileExists(stub_dir) || virFileExists(path)) {
+ pciDriverFile(path, sizeof(path), driver, "remove_id");
+ if (!virFileExists(drvdir) || virFileExists(path)) {
if (virFileWriteStr(PCI_SYSFS "drivers_probe", dev->name) < 0) {
virReportSystemError(conn, errno,
_("Failed to trigger a re-probe for PCI device '%s'"),
@@ -746,7 +803,14 @@ pciUnBindDeviceFromStub(virConnectPtr co
int
pciReAttachDevice(virConnectPtr conn, pciDevice *dev)
{
- return pciUnBindDeviceFromStub(conn, dev, "pci-stub");
+ const char *driver = pciFindStubDriver(conn);
+ if (!driver) {
+ pciReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
+ _("cannot find any PCI stub module"));
+ return -1;
+ }
+
+ return pciUnBindDeviceFromStub(conn, dev, driver);
}
static char *
Index: src/xen_unified.c
===================================================================
RCS file: /data/cvs/libvirt/src/xen_unified.c,v
retrieving revision 1.83
diff -u -p -r1.83 xen_unified.c
--- src/xen_unified.c 5 Feb 2009 16:03:11 -0000 1.83
+++ src/xen_unified.c 30 Mar 2009 13:09:44 -0000
@@ -43,6 +43,8 @@
#include "xml.h"
#include "util.h"
#include "memory.h"
+#include "node_device_conf.h"
+#include "pci.h"
#define VIR_FROM_THIS VIR_FROM_XEN
@@ -1420,6 +1422,123 @@ xenUnifiedDomainEventDeregister (virConn
return ret;
}
+
+static int
+xenUnifiedNodeDeviceGetPciInfo (virNodeDevicePtr dev,
+ unsigned *domain,
+ unsigned *bus,
+ unsigned *slot,
+ unsigned *function)
+{
+ virNodeDeviceDefPtr def = NULL;
+ virNodeDevCapsDefPtr cap;
+ char *xml = NULL;
+ int ret = -1;
+
+ xml = virNodeDeviceGetXMLDesc(dev, 0);
+ if (!xml)
+ goto out;
+
+ def = virNodeDeviceDefParseString(dev->conn, xml);
+ if (!def)
+ goto out;
+
+ cap = def->caps;
+ while (cap) {
+ if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
+ *domain = cap->data.pci_dev.domain;
+ *bus = cap->data.pci_dev.bus;
+ *slot = cap->data.pci_dev.slot;
+ *function = cap->data.pci_dev.function;
+ break;
+ }
+
+ cap = cap->next;
+ }
+
+ if (!cap) {
+ xenUnifiedError(dev->conn, VIR_ERR_INVALID_ARG,
+ _("device %s is not a PCI device"), dev->name);
+ goto out;
+ }
+
+ ret = 0;
+out:
+ virNodeDeviceDefFree(def);
+ VIR_FREE(xml);
+ return ret;
+}
+
+static int
+xenUnifiedNodeDeviceDettach (virNodeDevicePtr dev)
+{
+ pciDevice *pci;
+ unsigned domain, bus, slot, function;
+ int ret = -1;
+
+ if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
+ return -1;
+
+ pci = pciGetDevice(dev->conn, domain, bus, slot, function);
+ if (!pci)
+ return -1;
+
+ if (pciDettachDevice(dev->conn, pci) < 0)
+ goto out;
+
+ ret = 0;
+out:
+ pciFreeDevice(dev->conn, pci);
+ return ret;
+}
+
+static int
+xenUnifiedNodeDeviceReAttach (virNodeDevicePtr dev)
+{
+ pciDevice *pci;
+ unsigned domain, bus, slot, function;
+ int ret = -1;
+
+ if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
+ return -1;
+
+ pci = pciGetDevice(dev->conn, domain, bus, slot, function);
+ if (!pci)
+ return -1;
+
+ if (pciReAttachDevice(dev->conn, pci) < 0)
+ goto out;
+
+ ret = 0;
+out:
+ pciFreeDevice(dev->conn, pci);
+ return ret;
+}
+
+static int
+xenUnifiedNodeDeviceReset (virNodeDevicePtr dev)
+{
+ pciDevice *pci;
+ unsigned domain, bus, slot, function;
+ int ret = -1;
+
+ if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
+ return -1;
+
+ pci = pciGetDevice(dev->conn, domain, bus, slot, function);
+ if (!pci)
+ return -1;
+
+ if (pciResetDevice(dev->conn, pci) < 0)
+ goto out;
+
+ ret = 0;
+out:
+ pciFreeDevice(dev->conn, pci);
+ return ret;
+}
+
+
/*----- Register with libvirt.c, and initialise Xen drivers. -----*/
/* The interface which we export upwards to libvirt.c. */
@@ -1481,6 +1600,9 @@ static virDriver xenUnifiedDriver = {
.getFreeMemory = xenUnifiedNodeGetFreeMemory,
.domainEventRegister = xenUnifiedDomainEventRegister,
.domainEventDeregister = xenUnifiedDomainEventDeregister,
+ .nodeDeviceDettach = xenUnifiedNodeDeviceDettach,
+ .nodeDeviceReAttach = xenUnifiedNodeDeviceReAttach,
+ .nodeDeviceReset = xenUnifiedNodeDeviceReset,
};
/**
Index: src/xend_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xend_internal.c,v
retrieving revision 1.253
diff -u -p -r1.253 xend_internal.c
--- src/xend_internal.c 10 Mar 2009 11:13:32 -0000 1.253
+++ src/xend_internal.c 30 Mar 2009 13:09:45 -0000
@@ -92,6 +92,11 @@ xenDaemonFormatSxprNet(virConnectPtr con
int xendConfigVersion,
int isAttach);
static int
+xenDaemonFormatSxprOnePCI(virConnectPtr conn,
+ virDomainHostdevDefPtr def,
+ virBufferPtr buf);
+
+static int
virDomainXMLDevID(virDomainPtr domain,
virDomainDeviceDefPtr dev,
char *class,
@@ -2145,6 +2150,131 @@ error:
return -1;
}
+/**
+ * xenDaemonParseSxprPCI
+ * @conn: connection
+ * @root: root sexpr
+ *
+ * This parses out block devices from the domain sexpr
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
+static int
+xenDaemonParseSxprPCI(virConnectPtr conn,
+ virDomainDefPtr def,
+ const struct sexpr *root)
+{
+ const struct sexpr *cur, *tmp = NULL, *node;
+ virDomainHostdevDefPtr dev = NULL;
+
+ /*
+ * With the (domain ...) block we have the following odd setup
+ *
+ * (device
+ * (pci
+ * (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
+ * (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
+ * )
+ * )
+ *
+ * Normally there is one (device ...) block per device, but in
+ * wierd world of Xen PCI, once (device ...) covers multiple
+ * devices.
+ */
+
+ for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+ node = cur->u.s.car;
+ if ((tmp = sexpr_lookup(node, "device/pci")) != NULL)
+ break;
+ }
+
+ if (!tmp)
+ return 0;
+
+ for (cur = tmp; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+ const char *domain = NULL;
+ const char *bus = NULL;
+ const char *slot = NULL;
+ const char *func = NULL;
+ int domainID;
+ int busID;
+ int slotID;
+ int funcID;
+
+ node = cur->u.s.car;
+ if (!sexpr_lookup(node, "dev"))
+ continue;
+
+ if (!(domain = sexpr_node(node, "dev/domain"))) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing PCI domain"));
+ goto error;
+ }
+ if (!(bus = sexpr_node(node, "dev/bus"))) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing PCI bus"));
+ goto error;
+ }
+ if (!(slot = sexpr_node(node, "dev/slot"))) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing PCI slot"));
+ goto error;
+ }
+ if (!(func = sexpr_node(node, "dev/func"))) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing PCI func"));
+ goto error;
+ }
+
+ if (virStrToLong_i(domain, NULL, 0, &domainID) < 0) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse PCI domain '%s'"), domain);
+ goto error;
+ }
+ if (virStrToLong_i(bus, NULL, 0, &busID) < 0) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse PCI bus '%s'"), bus);
+ goto error;
+ }
+ if (virStrToLong_i(slot, NULL, 0, &slotID) < 0) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse PCI slot '%s'"), slot);
+ goto error;
+ }
+ if (virStrToLong_i(func, NULL, 0, &funcID) < 0) {
+ virXendError(conn, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse PCI func '%s'"), func);
+ goto error;
+ }
+
+ if (VIR_ALLOC(dev) < 0)
+ goto no_memory;
+
+ dev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
+ dev->managed = 0;
+ dev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
+ dev->source.subsys.u.pci.domain = domainID;
+ dev->source.subsys.u.pci.bus = busID;
+ dev->source.subsys.u.pci.slot = slotID;
+ dev->source.subsys.u.pci.function = funcID;
+
+ if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0) {
+ goto no_memory;
+ }
+
+ def->hostdevs[def->nhostdevs++] = dev;
+ }
+
+ return 0;
+
+no_memory:
+ virReportOOMError(conn);
+
+error:
+ virDomainHostdevDefFree(dev);
+ return -1;
+}
+
/**
* xenDaemonParseSxpr:
@@ -2310,6 +2440,9 @@ xenDaemonParseSxpr(virConnectPtr conn,
if (xenDaemonParseSxprNets(conn, def, root) < 0)
goto error;
+ if (xenDaemonParseSxprPCI(conn, def, root) < 0)
+ goto error;
+
/* New style graphics device config */
if (xenDaemonParseSxprGraphicsNew(conn, def, root) < 0)
goto error;
@@ -3953,6 +4086,20 @@ xenDaemonAttachDevice(virDomainPtr domai
goto cleanup;
break;
+ case VIR_DOMAIN_DEVICE_HOSTDEV:
+ if (dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+ if (xenDaemonFormatSxprOnePCI(domain->conn,
+ dev->data.hostdev,
+ &buf) < 0)
+ goto cleanup;
+ } else {
+ virXendError(domain->conn, VIR_ERR_NO_SUPPORT, "%s",
+ _("unsupported device type"));
+ goto cleanup;
+ }
+ break;
+
default:
virXendError(domain->conn, VIR_ERR_NO_SUPPORT, "%s",
_("unsupported device type"));
@@ -5263,6 +5410,85 @@ xenDaemonFormatSxprNet(virConnectPtr con
return 0;
}
+
+static void
+xenDaemonFormatSxprPCI(virDomainHostdevDefPtr def,
+ virBufferPtr buf)
+{
+ virBufferVSprintf(buf, "(dev (domain 0x%04x)(bus 0x%02x)(slot 0x%02x)(func 0x%x))",
+ def->source.subsys.u.pci.domain,
+ def->source.subsys.u.pci.bus,
+ def->source.subsys.u.pci.slot,
+ def->source.subsys.u.pci.function);
+}
+
+static int
+xenDaemonFormatSxprOnePCI(virConnectPtr conn,
+ virDomainHostdevDefPtr def,
+ virBufferPtr buf)
+{
+ if (def->managed) {
+ virXendError(conn, VIR_ERR_NO_SUPPORT, "%s",
+ _("managed PCI devices not supported with XenD"));
+ return -1;
+ }
+
+ virBufferAddLit(buf, "(pci ");
+ xenDaemonFormatSxprPCI(def, buf);
+ virBufferAddLit(buf, ")");
+
+ return 0;
+}
+
+static int
+xenDaemonFormatSxprAllPCI(virConnectPtr conn,
+ virDomainDefPtr def,
+ virBufferPtr buf)
+{
+ int hasPCI = 0;
+ int i;
+
+ for (i = 0 ; i < def->nhostdevs ; i++)
+ if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ hasPCI = 1;
+
+ if (!hasPCI)
+ return 0;
+
+ /*
+ * With the (domain ...) block we have the following odd setup
+ *
+ * (device
+ * (pci
+ * (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
+ * (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
+ * )
+ * )
+ *
+ * Normally there is one (device ...) block per device, but in
+ * wierd world of Xen PCI, once (device ...) covers multiple
+ * devices.
+ */
+
+ virBufferAddLit(buf, "(device (pci ");
+ for (i = 0 ; i < def->nhostdevs ; i++) {
+ if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+ if (def->hostdevs[i]->managed) {
+ virXendError(conn, VIR_ERR_NO_SUPPORT, "%s",
+ _("managed PCI devices not supported with XenD"));
+ return -1;
+ }
+
+ xenDaemonFormatSxprPCI(def->hostdevs[i], buf);
+ }
+ }
+ virBufferAddLit(buf, "))");
+
+ return 0;
+}
+
int
xenDaemonFormatSxprSound(virConnectPtr conn,
virDomainDefPtr def,
@@ -5529,6 +5755,9 @@ xenDaemonFormatSxpr(virConnectPtr conn,
&buf, hvm, xendConfigVersion, 0) < 0)
goto error;
+ if (xenDaemonFormatSxprAllPCI(conn, def, &buf) < 0)
+ goto error;
+
/* New style PV graphics config xen >= 3.0.4,
* or HVM graphics config xen >= 3.0.5 */
if ((xendConfigVersion >= XEND_CONFIG_MIN_VERS_PVFB_NEWCONF && !hvm) ||
@@ -5611,6 +5840,9 @@ virDomainXMLDevID(virDomainPtr domain,
strncpy(ref, xref, ref_len);
free(xref);
ref[ref_len - 1] = '\0';
+ } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
+ dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ dev->data.hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
} else {
virXendError(NULL, VIR_ERR_NO_SUPPORT,
"%s", _("hotplug of device type not supported"));
Index: src/xm_internal.c
===================================================================
RCS file: /data/cvs/libvirt/src/xm_internal.c,v
retrieving revision 1.118
diff -u -p -r1.118 xm_internal.c
--- src/xm_internal.c 24 Mar 2009 11:16:29 -0000 1.118
+++ src/xm_internal.c 30 Mar 2009 13:09:45 -0000
@@ -673,6 +673,7 @@ xenXMDomainConfigParse(virConnectPtr con
virDomainDiskDefPtr disk = NULL;
virDomainNetDefPtr net = NULL;
virDomainGraphicsDefPtr graphics = NULL;
+ virDomainHostdevDefPtr hostdev = NULL;
int i;
const char *defaultArch, *defaultMachine;
@@ -1115,6 +1116,88 @@ xenXMDomainConfigParse(virConnectPtr con
}
}
+ list = virConfGetValue(conf, "pci");
+ if (list && list->type == VIR_CONF_LIST) {
+ list = list->list;
+ while (list) {
+ char domain[5];
+ char bus[3];
+ char slot[3];
+ char func[2];
+ char *key, *nextkey;
+ int domainID;
+ int busID;
+ int slotID;
+ int funcID;
+
+ domain[0] = bus[0] = slot[0] = func[0] = '\0';
+
+ if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
+ goto skippci;
+
+ /* pci=['0000:00:1b.0','0000:00:13.0'] */
+ key = list->str;
+ if (!(key = list->str))
+ goto skippci;
+ if (!(nextkey = strchr(key, ':')))
+ goto skippci;
+
+ if ((nextkey - key) > (sizeof(domain)-1))
+ goto skippci;
+
+ strncpy(domain, key, sizeof(domain));
+ domain[sizeof(domain)-1] = '\0';
+
+ key = nextkey + 1;
+ if (!(nextkey = strchr(key, ':')))
+ goto skippci;
+
+ strncpy(bus, key, sizeof(bus));
+ bus[sizeof(bus)-1] = '\0';
+
+ key = nextkey + 1;
+ if (!(nextkey = strchr(key, '.')))
+ goto skippci;
+
+ strncpy(slot, key, sizeof(slot));
+ slot[sizeof(slot)-1] = '\0';
+
+ key = nextkey + 1;
+ if (strlen(key) != 1)
+ goto skippci;
+
+ strncpy(func, key, sizeof(func));
+ func[sizeof(func)-1] = '\0';
+
+ if (virStrToLong_i(domain, NULL, 16, &domainID) < 0)
+ goto skippci;
+ if (virStrToLong_i(bus, NULL, 16, &busID) < 0)
+ goto skippci;
+ if (virStrToLong_i(slot, NULL, 16, &slotID) < 0)
+ goto skippci;
+ if (virStrToLong_i(func, NULL, 16, &funcID) < 0)
+ goto skippci;
+
+ if (VIR_ALLOC(hostdev) < 0)
+ goto cleanup;
+
+ hostdev->managed = 0;
+ hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
+ hostdev->source.subsys.u.pci.domain = domainID;
+ hostdev->source.subsys.u.pci.bus = busID;
+ hostdev->source.subsys.u.pci.slot = slotID;
+ hostdev->source.subsys.u.pci.function = funcID;
+
+ if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0)
+ goto no_memory;
+ def->hostdevs[def->nhostdevs++] = hostdev;
+ hostdev = NULL;
+
+ skippci:
+ list = list->next;
+ }
+ }
+
if (hvm) {
if (xenXMConfigGetString(conn, conf, "usbdevice", &str, NULL) < 0)
goto cleanup;
@@ -1939,6 +2022,76 @@ cleanup:
+static int
+xenXMDomainConfigFormatPCI(virConnectPtr conn,
+ virConfPtr conf,
+ virDomainDefPtr def)
+{
+
+ virConfValuePtr pciVal = NULL;
+ int hasPCI = 0;
+ int i;
+
+ for (i = 0 ; i < def->nhostdevs ; i++)
+ if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ hasPCI = 1;
+
+ if (!hasPCI)
+ return 0;
+
+ if (VIR_ALLOC(pciVal) < 0)
+ return -1;
+
+ pciVal->type = VIR_CONF_LIST;
+ pciVal->list = NULL;
+
+ for (i = 0 ; i < def->nhostdevs ; i++) {
+ if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+ virConfValuePtr val, tmp;
+ char *buf;
+
+ if (virAsprintf(&buf, "%04x:%02x:%02x.%x",
+ def->hostdevs[i]->source.subsys.u.pci.domain,
+ def->hostdevs[i]->source.subsys.u.pci.bus,
+ def->hostdevs[i]->source.subsys.u.pci.slot,
+ def->hostdevs[i]->source.subsys.u.pci.function) < 0)
+ goto error;
+
+ if (VIR_ALLOC(val) < 0) {
+ VIR_FREE(buf);
+ virReportOOMError(conn);
+ goto error;
+ }
+ val->type = VIR_CONF_STRING;
+ val->str = buf;
+ tmp = pciVal->list;
+ while (tmp && tmp->next)
+ tmp = tmp->next;
+ if (tmp)
+ tmp->next = val;
+ else
+ pciVal->list = val;
+ }
+ }
+
+ if (pciVal->list != NULL) {
+ int ret = virConfSetValue(conf, "pci", pciVal);
+ pciVal = NULL;
+ if (ret < 0)
+ return -1;
+ }
+ VIR_FREE(pciVal);
+
+ return 0;
+
+error:
+ virConfFreeValue(pciVal);
+ return -1;
+}
+
+
virConfPtr xenXMDomainConfigFormat(virConnectPtr conn,
virDomainDefPtr def) {
virConfPtr conf = NULL;
@@ -2260,6 +2413,9 @@ virConfPtr xenXMDomainConfigFormat(virCo
}
VIR_FREE(netVal);
+ if (xenXMDomainConfigFormatPCI(conn, conf, def) < 0)
+ goto cleanup;
+
if (hvm) {
if (def->nparallels) {
virBuffer buf = VIR_BUFFER_INITIALIZER;
Index: tests/sexpr2xmltest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/sexpr2xmltest.c,v
retrieving revision 1.36
diff -u -p -r1.36 sexpr2xmltest.c
--- tests/sexpr2xmltest.c 29 Jan 2009 17:02:00 -0000 1.36
+++ tests/sexpr2xmltest.c 30 Mar 2009 13:09:45 -0000
@@ -142,6 +142,7 @@ mymain(int argc, char **argv)
DO_TEST("net-e1000", "net-e1000", 2);
DO_TEST("bridge-ipaddr", "bridge-ipaddr", 3);
DO_TEST("no-source-cdrom", "no-source-cdrom", 2);
+ DO_TEST("pci-devs", "pci-devs", 2);
DO_TEST("fv-utc", "fv-utc", 1);
DO_TEST("fv-localtime", "fv-localtime", 1);
Index: tests/xmconfigtest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/xmconfigtest.c,v
retrieving revision 1.26
diff -u -p -r1.26 xmconfigtest.c
--- tests/xmconfigtest.c 8 Jan 2009 19:52:15 -0000 1.26
+++ tests/xmconfigtest.c 30 Mar 2009 13:09:45 -0000
@@ -231,6 +231,7 @@ mymain(int argc, char **argv)
DO_TEST("escape-paths", 2);
DO_TEST("no-source-cdrom", 2);
+ DO_TEST("pci-devs", 2);
virCapabilitiesFree(caps);
Index: tests/xml2sexprtest.c
===================================================================
RCS file: /data/cvs/libvirt/tests/xml2sexprtest.c,v
retrieving revision 1.34
diff -u -p -r1.34 xml2sexprtest.c
--- tests/xml2sexprtest.c 23 Jan 2009 01:48:47 -0000 1.34
+++ tests/xml2sexprtest.c 30 Mar 2009 13:09:45 -0000
@@ -128,6 +128,7 @@ mymain(int argc, char **argv)
DO_TEST("net-e1000", "net-e1000", "pvtest", 2);
DO_TEST("bridge-ipaddr", "bridge-ipaddr", "pvtest", 2);
DO_TEST("no-source-cdrom", "no-source-cdrom", "test", 2);
+ DO_TEST("pci-devs", "pci-devs", "pvtest", 2);
DO_TEST("fv-utc", "fv-utc", "fvtest", 1);
DO_TEST("fv-localtime", "fv-localtime", "fvtest", 1);
Index: tests/sexpr2xmldata/sexpr2xml-pci-devs.sexpr
===================================================================
RCS file: tests/sexpr2xmldata/sexpr2xml-pci-devs.sexpr
diff -N tests/sexpr2xmldata/sexpr2xml-pci-devs.sexpr
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/sexpr2xmldata/sexpr2xml-pci-devs.sexpr 30 Mar 2009 13:09:45 -0000
@@ -0,0 +1,2 @@
+(domain (domid 6)(name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test... ')))(device (pci (backend 0)(dev (domain 0x0001) (bus 0x0c) (slot 0x1b) (func 0x2))(dev (domain 0x0000) (bus 0x01) (slot 0x13) (func 0x0))))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestVG')(mode 'w'))))
+
Index: tests/sexpr2xmldata/sexpr2xml-pci-devs.xml
===================================================================
RCS file: tests/sexpr2xmldata/sexpr2xml-pci-devs.xml
diff -N tests/sexpr2xmldata/sexpr2xml-pci-devs.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/sexpr2xmldata/sexpr2xml-pci-devs.xml 30 Mar 2009 13:09:45 -0000
@@ -0,0 +1,37 @@
+<domain type='xen' id='6'>
+ <name>pvtest</name>
+ <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid>
+ <memory>430080</memory>
+ <currentMemory>430080</currentMemory>
+ <vcpu>2</vcpu>
+ <os>
+ <type>linux</type>
+ <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel>
+ <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd>
+ <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test... </cmdline>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <disk type='block' device='disk'>
+ <driver name='phy'/>
+ <source dev='/dev/MainVG/GuestVG'/>
+ <target dev='xvda' bus='xen'/>
+ </disk>
+ <console type='pty'>
+ <target port='0'/>
+ </console>
+ <hostdev mode='subsystem' type='pci' managed='no'>
+ <source>
+ <address domain='0x0001' bus='0x0c' slot='0x1b' function='0x2'/>
+ </source>
+ </hostdev>
+ <hostdev mode='subsystem' type='pci' managed='no'>
+ <source>
+ <address domain='0x0000' bus='0x01' slot='0x13' function='0x0'/>
+ </source>
+ </hostdev>
+ </devices>
+</domain>
Index: tests/xmconfigdata/test-pci-devs.cfg
===================================================================
RCS file: tests/xmconfigdata/test-pci-devs.cfg
diff -N tests/xmconfigdata/test-pci-devs.cfg
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/xmconfigdata/test-pci-devs.cfg 30 Mar 2009 13:09:45 -0000
@@ -0,0 +1,24 @@
+name = "test"
+uuid = "cc2315e7-d26a-307a-438c-6d188ec4c09c"
+maxmem = 382
+memory = 350
+vcpus = 1
+builder = "hvm"
+kernel = "/usr/lib/xen/boot/hvmloader"
+boot = "c"
+pae = 1
+acpi = 1
+apic = 1
+localtime = 0
+on_poweroff = "destroy"
+on_reboot = "destroy"
+on_crash = "destroy"
+device_model = "/usr/lib/xen/bin/qemu-dm"
+sdl = 0
+vnc = 1
+vncunused = 1
+disk = [ "phy:/dev/sda8,hda,w", ",hdc:cdrom,r" ]
+vif = [ "mac=00:16:3e:0a:7b:39,bridge=xenbr0,type=ioemu" ]
+pci = [ "0001:0c:1b.2", "0000:01:13.0" ]
+parallel = "none"
+serial = "pty"
Index: tests/xmconfigdata/test-pci-devs.xml
===================================================================
RCS file: tests/xmconfigdata/test-pci-devs.xml
diff -N tests/xmconfigdata/test-pci-devs.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/xmconfigdata/test-pci-devs.xml 30 Mar 2009 13:09:45 -0000
@@ -0,0 +1,56 @@
+<domain type='xen'>
+ <name>test</name>
+ <uuid>cc2315e7-d26a-307a-438c-6d188ec4c09c</uuid>
+ <memory>391168</memory>
+ <currentMemory>358400</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='xenfv'>hvm</type>
+ <loader>/usr/lib/xen/boot/hvmloader</loader>
+ <boot dev='hd'/>
+ </os>
+ <features>
+ <acpi/>
+ <apic/>
+ <pae/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/lib/xen/bin/qemu-dm</emulator>
+ <disk type='block' device='disk'>
+ <driver name='phy'/>
+ <source dev='/dev/sda8'/>
+ <target dev='hda' bus='ide'/>
+ </disk>
+ <disk type='block' device='cdrom'>
+ <driver name='phy'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ </disk>
+ <interface type='bridge'>
+ <mac address='00:16:3e:0a:7b:39'/>
+ <source bridge='xenbr0'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target port='0'/>
+ </console>
+ <input type='mouse' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes'/>
+ <hostdev mode='subsystem' type='pci' managed='no'>
+ <source>
+ <address domain='0x0001' bus='0x0c' slot='0x1b' function='0x2'/>
+ </source>
+ </hostdev>
+ <hostdev mode='subsystem' type='pci' managed='no'>
+ <source>
+ <address domain='0x0000' bus='0x01' slot='0x13' function='0x0'/>
+ </source>
+ </hostdev>
+ </devices>
+</domain>
Index: tests/xml2sexprdata/xml2sexpr-pci-devs.sexpr
===================================================================
RCS file: tests/xml2sexprdata/xml2sexpr-pci-devs.sexpr
diff -N tests/xml2sexprdata/xml2sexpr-pci-devs.sexpr
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/xml2sexprdata/xml2sexpr-pci-devs.sexpr 30 Mar 2009 13:09:45 -0000
@@ -0,0 +1 @@
+(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test... ')))(device (vbd (dev 'xvda')(uname 'phy:/dev/MainVG/GuestLV')(mode 'w')))(device (pci (dev (domain 0x0001)(bus 0x0c)(slot 0x1b)(func 0x2))(dev (domain 0x0000)(bus 0x01)(slot 0x13)(func 0x0)))))
\ No newline at end of file
Index: tests/xml2sexprdata/xml2sexpr-pci-devs.xml
===================================================================
RCS file: tests/xml2sexprdata/xml2sexpr-pci-devs.xml
diff -N tests/xml2sexprdata/xml2sexpr-pci-devs.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/xml2sexprdata/xml2sexpr-pci-devs.xml 30 Mar 2009 13:09:45 -0000
@@ -0,0 +1,33 @@
+<domain type='xen' id='15'>
+ <name>pvtest</name>
+ <uuid>596a5d2171f48fb2e068e2386a5c413e</uuid>
+ <os>
+ <type>linux</type>
+ <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel>
+ <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd>
+ <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test... </cmdline>
+ </os>
+ <memory>430080</memory>
+ <vcpu>2</vcpu>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>destroy</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <disk type='block' device='disk'>
+ <source dev='/dev/MainVG/GuestLV'/>
+ <target dev='xvda'/>
+ </disk>
+ <console tty='/dev/pts/4'/>
+ <hostdev mode='subsystem' type='pci' managed='no'>
+ <source>
+ <address domain='0x0001' bus='0x0c' slot='0x1b' function='0x2'/>
+ </source>
+ </hostdev>
+ <hostdev mode='subsystem' type='pci' managed='no'>
+ <source>
+ <address domain='0x0000' bus='0x01' slot='0x13' function='0x0'/>
+ </source>
+ </hostdev>
+ </devices>
+</domain>
+
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
15 years, 7 months
[libvirt] Reworked the XML verification patch for svirt
by Daniel J Walsh
Main goal of this patch it to verify data being written to xml and
inform the user when he makes a mistake.
Only able to verify static/dynamic in domain_conf.
Added verify code to qemu_driver.c for model and potentially label.
15 years, 7 months
[libvirt] ANNOUNCE: netcf, a platform-agnostic library for network configuration
by David Lutterkort
I am pleased to announce the availability of netcf 0.0.1, the initial
release of a library for managing network configuration in a platform
agnostic manner. If I were into code names, this would be the "what have
you been waiting for" release.
Netcf does its work by directly modifying the 'native' configuration files
of the host it is running on; this avoids a whole class of problems caused
by similar approaches that do network configuration behind the back of the
native mechanisms. The API allows listing of configured interfaces,
defining the configuration of an interface, retrieving the same (regardless
of whether the interface was initially configured with netcf or not), and
bringing interfaces up and down. This functionality is needed both by
libvirt and NetworkManager, so it seemed only logical to move their common
needs into a separate library.
This release is mostly geared at soliciting feedback and sparking spirited
reviews. In particular, the API is not stable yet (it will be with the
release of netcf 0.1.0) Besides general comments, criticism and the
customary praise, I am particularly interested in reviews on the following:
* The API (barring any strong objections, I will declare it stable)
* The XML schema for describing network interfaces (in data/xml/interface.rng)
* General code review
Where can I get it ?
--------------------
Main website
https://fedorahosted.org/netcf/
A tarball can be downloaded from
https://fedorahosted.org/released/netcf/
The git repo is at
http://git.fedorahosted.org/git/netcf.git
git clone git://git.fedorahosted.org/netcf.git
For those running Fedora 10, I built some preliminary RPM's and made them
available at
http://people.redhat.com/dlutter/netcf/download/
(and if you are a Fedora reviewer, the review BZ is 493750 ;)
How can I help ?
----------------
Join the mailing list at
https://fedorahosted.org/mailman/listinfo/netcf-devel
Currently, netcf can set up simple Ethernet interfaces, bridges with
enslaved physical devices and bonds on Fedora. This points to two areas
where improvements are most needed:
* support other Linux distros and operating systems
* expand what kind of interfaces netcf can handle (most sorely needed are
VLAN's and adding bonds to a bridge)
If you can help with either of these two, or anything, really, drop a note
on the mailing list so wecan discuss.
David
15 years, 7 months
[libvirt] specifying -serial telnet: in XML
by Sukadev Bhattiprolu
I run qemu (version 0.9.1 kvm-84) with -serial option as follows:
- serial telnet::2445,server
so I can telnet to 2445 and have a serial console.
I tried specifying this to libvirt (version 0.6.0) using the following stanza:
<serial type='tcp'>
<source mode="bind" host="127.0.0.1" service="2445"/>
<protocol type="telnet"/>
<target port="1"/>
</serial>
I checked /var/log/libvirt/qemu/<guest>.log and found that libvirt
added 'nowait' to the serial option:
-serial telnet:127.0.0.1:2445,server,nowait
which is fine (I think).
But when I start my guest, and "telnet 127.0.0.1 2445" I don't get any
output even though the guest boots up fine. After the guest boots
$ echo foo > /dev/ttyS0
in the guest shows the 'foo' in the telnet window. But I don't get the
boot/shutdown messages.
I also have the vnc option in the xml,
<graphics type='vnc' port='5902' autoport='no' listen='127.0.0.1'/>
so if I open vncviewer, I can see the boot messages. The problem with this
though is if the kernel fails to boot for some reason, the vncviewer exits
and I can't find the reason the boot failed.
My kernel boot command line has 'console=ttyS0' option. Is there anything
else I need to ensure 'telnet 127.0.0.1 port' displays the messages ?
Thanks,
Sukadev
15 years, 7 months
[libvirt] [PATCH] Openvz: how to use a nondefault config
by Anton Protopopov
Hi all.
When libvirt creates an OpenVZ machine, it does smth like
# vzctl create $ctid --ostemplate `ostemplate`
And we can't specify an --config `config` argument. In this case vzctl
chooses
a default config file (a value of CONFIG variable from /etc/vz/vz.conf).
But there are cases when we want to specify a config file directly, as in
# vzctl create $ctid --ostemplate `ostemplate` --config `config`
I think, that we can try to use the same `ostemplate` name as --config
value, if corresponding template exists,
i.e., if there is a file /etc/vz/conf/ve-`ostemplate`.conf-sample, libvirt
will run a command
# vzctl create $ctid --ostemplate `ostemplate` --config `ostemplate`
Otherwise, it will run it's default command
# vzctl create $ctid --ostemplate `ostemplate`
(the same arguments.)
-----------
Example of creating a machine with nondefault config:
1. Create /etc/vz/conf/ve-altlinux-test.conf-sample
2. Create /var/lib/vz/template/cache/altlinux-test.tar
3. Use libvirt with (hypothetical) XML:
<domain type="openvz">
<name>100</name>
<memory>1</memory>
<os><type>exe</type></os>
<devices>
<filesystem type="template">
<source name="altlinux-test"/>
<target dir="/"/>
</filesystem>
</devices>
</domain>
-----------
Example of creating a machine with default config:
1. Ensure there is no /etc/vz/conf/ve-altlinux-test.conf-sample
2. Create /var/lib/vz/template/cache/altlinux-test.tar
3. Use libvirt with (the same as above) XML file
-----------
15 years, 7 months
[libvirt] SYSCONF_DIR
by Zvi Dubitzky
I can do TLS certificate authentication on a remote libvirt access
through 'virsh' ( virsh -c qemu+tls://hostnake/system) .
But when I try same auth from my C code linked with libvirt 0.6.1 I get
the message : " libvir: Remote error: cannot access CA certificate
'/usr/local/etc/pki/CA/cacert.pem . No such file or directory"
My certificate is at /etc/pki/CA as instructed in the web site (deafult)
and so is my libvirtd.conf saying. virsh works ok with it .
In my case the server and client are on same machine .
I guess the need for SYSCONF_DIR = /usr/local/etc comes from the
configure of the libvirt . In fact I see in the configure file the
statement : sysconfigdir = '${prefix}/etc .
Any idea how to fix that . I am using the installed libvirt . did not
rebuild it .
thanks
Zvi Dubitzky
Virtualization and System Architecture Email:dubi@il.ibm.com
IBM Haifa Research Laboratory Phone: +972-4-8296182
Haifa, 31905, ISRAEL
15 years, 7 months
[libvirt] checkpoint patches of netcf integration for review/guidance
by laine@laine.org
I've gone through the first two steps of danpb's "Guide to Adding New
libvirt APIs", and thought this would be a good time to send a copy of
my work to the list to make sure I'm going in the right direction. Now
is (yet another) good time to tell me "You're doing it wrong!".
Basically, I've defined the public api in libvirt.h (actually
libvirt.h.in - it's a real pain to have generated files under source
control - it almost led me to mistakenly lose my modifications a
couple times after running autogen, until I actually looked in the
directory containing the file and saw the *.in file), done all the
toplevel functions in libvirt.c, and whatever ancillary definitions
and small functions were needed by them.
In a 3rd patch, I also added stuff to configure.in that detects the
presence of libnetcf and 1) turns on WITH_NETCF in config.h and 2)
adds -lnetcf to LDFLAGS. I noticed that some other similar items have
been added to configure.in by peppering little changes in several
spots throughout the file; I preferred adding all my stuff in one
place to make it easier to follow (and less likely to cause merge
conflicts).
So far this has been a *lot* of cut-n-paste, which makes me a bit uneasy
(both because of the lesser problem that it almost always leads to
errors caused by missing bits and pieces that need modification after
the paste, and the greater problem that using this method may indicate
I'm operating mechanically, without having adequate understanding of
what I'm trying to do).
15 years, 7 months