Add support for virtio-serial by defining a new 'virtio' channel target type and a virtio-serial controller. Allows the following to be specified in a domain: <controller type='virtio-serial' index='0' max_ports='16' vectors='4'/> <channel type='pty'> <target type='virtio' name='org.linux-kvm.port.0'/> <address type='virtio-serial' controller='0' bus='0'/> </channel> * docs/schemas/domain.rng: Add virtio-serial controller and virtio channel type. * src/conf/domain_conf.[ch]: Domain parsing/serialization for virtio-serial controller and virtio channel. * tests/qemuxml2xmltest.c tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml : add domain xml parsing test * src/libvirt_private.syms src/qemu/qemu_conf.c: virDomainDefAddDiskControllers() renamed to virDomainDefAddImplicitControllers() --- docs/schemas/domain.rng | 71 +++++- src/conf/domain_conf.c | 234 +++++++++++++++++--- src/conf/domain_conf.h | 25 ++- src/libvirt_private.syms | 2 +- src/qemu/qemu_conf.c | 2 +- .../qemuxml2argv-channel-virtio.xml | 35 +++ tests/qemuxml2xmltest.c | 1 + 7 files changed, 320 insertions(+), 50 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 53b82ce..85df8b8 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -523,16 +523,36 @@ </define> <define name="controller"> <element name="controller"> - <optional> - <attribute name="type"> - <choice> - <value>fdc</value> - <value>ide</value> - <value>scsi</value> - <value>sata</value> - </choice> - </attribute> - </optional> + <choice> + <group> + <optional> + <attribute name="type"> + <choice> + <value>fdc</value> + <value>ide</value> + <value>scsi</value> + <value>sata</value> + </choice> + </attribute> + </optional> + </group> + <!-- virtio-serial can have 2 additional attributes --> + <group> + <attribute name="type"> + <value>virtio-serial</value> + </attribute> + <optional> + <attribute name="max_ports"> + <ref name="unsignedInt"/> + </attribute> + </optional> + <optional> + <attribute name="vectors"> + <ref name="unsignedInt"/> + </attribute> + </optional> + </group> + </choice> <attribute name="index"> <ref name="unsignedInt"/> </attribute> @@ -1139,12 +1159,25 @@ <attribute name="port"/> </element> </define> + <define name="virtioTarget"> + <element name="target"> + <attribute name="type"> + <value>virtio</value> + </attribute> + <optional> + <attribute name="name"/> + </optional> + </element> + </define> <define name="channel"> <element name="channel"> <ref name="qemucdevSrcType"/> <interleave> <ref name="qemucdevSrcDef"/> - <ref name="guestfwdTarget"/> + <choice> + <ref name="guestfwdTarget"/> + <ref name="virtioTarget"/> + </choice> <optional> <ref name="address"/> </optional> @@ -1269,6 +1302,16 @@ <ref name="driveUnit"/> </attribute> </define> + <define name="virtioserialaddress"> + <attribute name="controller"> + <ref name="driveController"/> + </attribute> + <optional> + <attribute name="bus"> + <ref name="driveBus"/> + </attribute> + </optional> + </define> <!-- Devices attached to a domain. --> @@ -1413,6 +1456,12 @@ </attribute> <ref name="driveaddress"/> </group> + <group> + <attribute name="type"> + <value>virtio-serial</value> + </attribute> + <ref name="virtioserialaddress"/> + </group> </choice> </element> </define> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 59fd251..58f353b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -93,7 +93,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST, VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST, "none", "pci", - "drive"); + "drive", + "virtio-serial"); VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST, "block", @@ -125,7 +126,8 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST, "ide", "fdc", "scsi", - "sata") + "sata", + "virtio-serial") VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST, "mount", @@ -150,7 +152,8 @@ VIR_ENUM_IMPL(virDomainChrTarget, VIR_DOMAIN_CHR_TARGET_TYPE_LAST, "parallel", "serial", "console", - "guestfwd") + "guestfwd", + "virtio") VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST, "null", @@ -459,6 +462,10 @@ void virDomainChrDefFree(virDomainChrDefPtr def) case VIR_DOMAIN_CHR_TARGET_TYPE_GUESTFWD: VIR_FREE(def->target.addr); break; + + case VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO: + VIR_FREE(def->target.name); + break; } switch (def->type) { @@ -811,6 +818,13 @@ int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr ATTRI /*return addr->controller || addr->bus || addr->unit;*/ return 1; /* 0 is valid for all fields, so any successfully parsed addr is valid */ } + + +int virDomainDeviceVirtioSerialAddressIsValid( + virDomainDeviceVirtioSerialAddressPtr addr ATTRIBUTE_UNUSED) +{ + return 1; /* 0 is valid for all fields, so any successfully parsed addr is valid */ +} #endif /* !PROXY */ @@ -916,7 +930,8 @@ void virDomainDefClearDeviceAliases(virDomainDefPtr def) */ static int virDomainDeviceInfoFormat(virBufferPtr buf, virDomainDeviceInfoPtr info, - int flags) + int flags, + const char *indent) { if (!info) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -926,14 +941,15 @@ static int virDomainDeviceInfoFormat(virBufferPtr buf, if (info->alias && !(flags & VIR_DOMAIN_XML_INACTIVE)) { - virBufferVSprintf(buf, " <alias name='%s'/>\n", info->alias); + virBufferVSprintf(buf, "%s<alias name='%s'/>\n", indent, info->alias); } if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) return 0; /* We'll be in domain/devices/[device type]/ so 3 level indent */ - virBufferVSprintf(buf, " <address type='%s'", + virBufferVSprintf(buf, "%s<address type='%s'", + indent, virDomainDeviceAddressTypeToString(info->type)); switch (info->type) { @@ -952,6 +968,12 @@ static int virDomainDeviceInfoFormat(virBufferPtr buf, info->addr.drive.unit); break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL: + virBufferVSprintf(buf, " controller='%d' bus='%d'", + info->addr.vioserial.controller, + info->addr.vioserial.bus); + break; + default: virDomainReportError(VIR_ERR_INTERNAL_ERROR, _("unknown address type '%d'"), info->type); @@ -1075,6 +1097,50 @@ cleanup: return ret; } + +static int +virDomainDeviceVirtioSerialAddressParseXML( + xmlNodePtr node, + virDomainDeviceVirtioSerialAddressPtr addr +) +{ + char *controller, *bus; + int ret = -1; + + memset(addr, 0, sizeof(*addr)); + + controller = virXMLPropString(node, "controller"); + bus = virXMLPropString(node, "bus"); + + if (controller && + virStrToLong_ui(controller, NULL, 10, &addr->controller) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'controller' attribute")); + goto cleanup; + } + + if (bus && + virStrToLong_ui(bus, NULL, 10, &addr->bus) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot parse <address> 'bus' attribute")); + goto cleanup; + } + + if (!virDomainDeviceVirtioSerialAddressIsValid(addr)) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Insufficient specification for " + "virtio serial address")); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(controller); + VIR_FREE(bus); + return ret; +} + /* Parse the XML definition for a device address * @param node XML nodeset to parse for device address definition */ @@ -1137,6 +1203,12 @@ virDomainDeviceInfoParseXML(xmlNodePtr node, goto cleanup; break; + case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL: + if (virDomainDeviceVirtioSerialAddressParseXML + (address, &info->addr.vioserial) < 0) + goto cleanup; + break; + default: /* Should not happen */ virDomainReportError(VIR_ERR_INTERNAL_ERROR, @@ -1462,9 +1534,9 @@ virDomainControllerDefParseXML(xmlNodePtr node, type = virXMLPropString(node, "type"); if (type) { - if ((def->type = virDomainDiskBusTypeFromString(type)) < 0) { + if ((def->type = virDomainControllerTypeFromString(type)) < 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown disk controller type '%s'"), type); + _("Unknown controller type '%s'"), type); goto error; } } @@ -1473,7 +1545,7 @@ virDomainControllerDefParseXML(xmlNodePtr node, if (idx) { if (virStrToLong_i(idx, NULL, 10, &def->idx) < 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse disk controller index %s"), idx); + _("Cannot parse controller index %s"), idx); goto error; } } @@ -1481,10 +1553,49 @@ virDomainControllerDefParseXML(xmlNodePtr node, if (virDomainDeviceInfoParseXML(node, &def->info, flags) < 0) goto error; + switch (def->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: + 0; /* C requires a statement immediately following a label */ + + char *max_ports = virXMLPropString(node, "max_ports"); + if (max_ports) { + int r = virStrToLong_i(max_ports, NULL, 10, + &def->opts.vioserial.max_ports); + if (r != 0 || def->opts.vioserial.max_ports < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid max_ports: %s"), max_ports); + VIR_FREE(max_ports); + goto error; + } + } else { + def->opts.vioserial.max_ports = -1; + } + VIR_FREE(max_ports); + + char *vectors = virXMLPropString(node, "vectors"); + if (vectors) { + int r = virStrToLong_i(vectors, NULL, 10, + &def->opts.vioserial.vectors); + if (r != 0 || def->opts.vioserial.vectors < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid vectors: %s"), vectors); + VIR_FREE(vectors); + goto error; + } + } else { + def->opts.vioserial.vectors = -1; + } + VIR_FREE(vectors); + break; + + default: + break; + } + if (def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Disk controllers must use the 'pci' address type")); + _("Controllers must use the 'pci' address type")); goto error; } @@ -2086,6 +2197,10 @@ virDomainChrDefParseXML(xmlNodePtr node, virSocketSetPort(def->target.addr, port); break; + case VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO: + def->target.name = virXMLPropString(cur, "name"); + break; + default: virDomainReportError(VIR_ERR_XML_ERROR, _("unexpected target type type %u"), @@ -2096,7 +2211,6 @@ virDomainChrDefParseXML(xmlNodePtr node, cur = cur->next; } - switch (def->type) { case VIR_DOMAIN_CHR_TYPE_NULL: /* Nada */ @@ -3629,12 +3743,6 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, } VIR_FREE(nodes); - /* Auto-add any further disk controllers implied by declared <disk> - * elements, but not present as <controller> elements - */ - if (virDomainDefAddDiskControllers(def) < 0) - goto error; - /* analysis of the filesystems */ if ((n = virXPathNodeSet("./devices/filesystem", ctxt, &nodes)) < 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, @@ -3948,6 +4056,11 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, goto error; } + /* Auto-add any implied controllers which aren't present + */ + if (virDomainDefAddImplicitControllers(def) < 0) + goto error; + return def; no_memory: @@ -4211,9 +4324,9 @@ cleanup: return obj; } -static int virDomainDefMaybeAddDiskController(virDomainDefPtr def, - int type, - int idx) +static int virDomainDefMaybeAddController(virDomainDefPtr def, + int type, + int idx) { int found = 0; int i; @@ -4266,7 +4379,7 @@ static int virDomainDefAddDiskControllersForType(virDomainDefPtr def, } for (i = 0 ; i <= maxController ; i++) { - if (virDomainDefMaybeAddDiskController(def, controllerType, i) < 0) + if (virDomainDefMaybeAddController(def, controllerType, i) < 0) return -1; } @@ -4274,13 +4387,33 @@ static int virDomainDefAddDiskControllersForType(virDomainDefPtr def, } +static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def) +{ + /* Look for any virtio serial device */ + int i; + for (i = 0 ; i < def->nchannels ; i++) { + virDomainChrDefPtr channel = def->channels[i]; + + if (channel->targetType == VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO) { + /* Try to add a virtio serial controller with index 0 */ + if (virDomainDefMaybeAddController(def, + VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, 0) < 0) + return -1; + break; + } + } + + return 0; +} + + /* - * Based on the declared <address type=drive> info for any disks, + * Based on the declared <address/> info for any devices, * add neccessary drive controllers which are not already present * in the XML. This is for compat with existing apps which will * not know/care about <controller> info in the XML */ -int virDomainDefAddDiskControllers(virDomainDefPtr def) +int virDomainDefAddImplicitControllers(virDomainDefPtr def) { if (virDomainDefAddDiskControllersForType(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI, @@ -4297,6 +4430,9 @@ int virDomainDefAddDiskControllers(virDomainDefPtr def) VIR_DOMAIN_DISK_BUS_IDE) < 0) return -1; + if (virDomainDefMaybeAddVirtioSerialController(def) < 0) + return -1; + return 0; } @@ -4597,7 +4733,7 @@ virDomainDiskDefFormat(virBufferPtr buf, virStorageEncryptionFormat(buf, def->encryption) < 0) return -1; - if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) + if (virDomainDeviceInfoFormat(buf, &def->info, flags, " ") < 0) return -1; virBufferAddLit(buf, " </disk>\n"); @@ -4622,9 +4758,25 @@ virDomainControllerDefFormat(virBufferPtr buf, " <controller type='%s' index='%d'", type, def->idx); + switch (def->type) { + case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL: + if (def->opts.vioserial.max_ports != -1) { + virBufferVSprintf(buf, " max_ports='%d'", + def->opts.vioserial.max_ports); + } + if (def->opts.vioserial.vectors != -1) { + virBufferVSprintf(buf, " vectors='%d'", + def->opts.vioserial.vectors); + } + break; + + default: + break; + } + if (virDomainDeviceInfoIsSet(&def->info)) { virBufferAddLit(buf, ">\n"); - if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) + if (virDomainDeviceInfoFormat(buf, &def->info, flags, " ") < 0) return -1; virBufferAddLit(buf, " </controller>\n"); } else { @@ -4680,7 +4832,7 @@ virDomainFSDefFormat(virBufferPtr buf, if (def->readonly) virBufferAddLit(buf, " <readonly/>\n"); - if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) + if (virDomainDeviceInfoFormat(buf, &def->info, flags, " ") < 0) return -1; virBufferAddLit(buf, " </filesystem>\n"); @@ -4769,7 +4921,7 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " <model type='%s'/>\n", def->model); - if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) + if (virDomainDeviceInfoFormat(buf, &def->info, flags, " ") < 0) return -1; virBufferAddLit(buf, " </interface>\n"); @@ -4792,6 +4944,7 @@ virDomainChrDefFormat(virBufferPtr buf, switch (def->targetType) { /* channel types are in a common channel element */ case VIR_DOMAIN_CHR_TARGET_TYPE_GUESTFWD: + case VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO: elementName = "channel"; break; @@ -4905,11 +5058,18 @@ virDomainChrDefFormat(virBufferPtr buf, break; } + case VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO: + virBufferAddLit(buf, " <target type='virtio'"); + if (def->target.name) { + virBufferVSprintf(buf, " name='%s'", def->target.name); + } + virBufferAddLit(buf, "/>\n"); + break; + case VIR_DOMAIN_CHR_TARGET_TYPE_PARALLEL: case VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL: case VIR_DOMAIN_CHR_TARGET_TYPE_CONSOLE: - virBufferVSprintf(buf, " <target port='%d'/>\n", - def->target.port); + virBufferVSprintf(buf, " <target port='%d'/>\n", def->target.port); break; default: @@ -4919,8 +5079,10 @@ virDomainChrDefFormat(virBufferPtr buf, return -1; } - if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) - return -1; + if (virDomainDeviceInfoIsSet(&def->info)) { + if (virDomainDeviceInfoFormat(buf, &def->info, flags, " ") < 0) + return -1; + } virBufferVSprintf(buf, " </%s>\n", elementName); @@ -4946,7 +5108,7 @@ virDomainSoundDefFormat(virBufferPtr buf, if (virDomainDeviceInfoIsSet(&def->info)) { virBufferAddLit(buf, ">\n"); - if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) + if (virDomainDeviceInfoFormat(buf, &def->info, flags, " ") < 0) return -1; virBufferAddLit(buf, " </sound>\n"); } else { @@ -4982,7 +5144,7 @@ virDomainWatchdogDefFormat(virBufferPtr buf, if (virDomainDeviceInfoIsSet(&def->info)) { virBufferAddLit(buf, ">\n"); - if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) + if (virDomainDeviceInfoFormat(buf, &def->info, flags, " ") < 0) return -1; virBufferAddLit(buf, " </watchdog>\n"); } else { @@ -5033,7 +5195,7 @@ virDomainVideoDefFormat(virBufferPtr buf, virBufferAddLit(buf, "/>\n"); } - if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) + if (virDomainDeviceInfoFormat(buf, &def->info, flags, " ") < 0) return -1; virBufferAddLit(buf, " </video>\n"); @@ -5065,7 +5227,7 @@ virDomainInputDefFormat(virBufferPtr buf, if (virDomainDeviceInfoIsSet(&def->info)) { virBufferAddLit(buf, ">\n"); - if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) + if (virDomainDeviceInfoFormat(buf, &def->info, flags, " ") < 0) return -1; virBufferAddLit(buf, " </input>\n"); } else { @@ -5218,7 +5380,7 @@ virDomainHostdevDefFormat(virBufferPtr buf, virBufferAddLit(buf, " </source>\n"); - if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) + if (virDomainDeviceInfoFormat(buf, &def->info, flags, " ") < 0) return -1; virBufferAddLit(buf, " </hostdev>\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 782af95..d4b0930 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -68,6 +68,7 @@ enum virDomainDeviceAddressType { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE, + VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST }; @@ -89,6 +90,13 @@ struct _virDomainDeviceDriveAddress { unsigned int unit; }; +typedef struct _virDomainDeviceVirtioSerialAddress virDomainDeviceVirtioSerialAddress; +typedef virDomainDeviceVirtioSerialAddress *virDomainDeviceVirtioSerialAddressPtr; +struct _virDomainDeviceVirtioSerialAddress { + unsigned int controller; + unsigned int bus; +}; + typedef struct _virDomainDeviceInfo virDomainDeviceInfo; typedef virDomainDeviceInfo *virDomainDeviceInfoPtr; struct _virDomainDeviceInfo { @@ -97,6 +105,7 @@ struct _virDomainDeviceInfo { union { virDomainDevicePCIAddress pci; virDomainDeviceDriveAddress drive; + virDomainDeviceVirtioSerialAddress vioserial; } addr; }; @@ -166,16 +175,27 @@ enum virDomainControllerType { VIR_DOMAIN_CONTROLLER_TYPE_FDC, VIR_DOMAIN_CONTROLLER_TYPE_SCSI, VIR_DOMAIN_CONTROLLER_TYPE_SATA, + VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, VIR_DOMAIN_CONTROLLER_TYPE_LAST }; +typedef struct _virDomainVirtioSerialOpts virDomainVirtioSerialOpts; +typedef virDomainVirtioSerialOpts *virDomainVirtioSerialOptsPtr; +struct _virDomainVirtioSerialOpts { + int max_ports; /* -1 == undef */ + int vectors; /* -1 == undef */ +}; + /* Stores the virtual disk controller configuration */ typedef struct _virDomainControllerDef virDomainControllerDef; typedef virDomainControllerDef *virDomainControllerDefPtr; struct _virDomainControllerDef { int type; int idx; + union { + virDomainVirtioSerialOpts vioserial; + } opts; virDomainDeviceInfo info; }; @@ -271,6 +291,7 @@ enum virDomainChrTargetType { VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL, VIR_DOMAIN_CHR_TARGET_TYPE_CONSOLE, VIR_DOMAIN_CHR_TARGET_TYPE_GUESTFWD, + VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO, VIR_DOMAIN_CHR_TARGET_TYPE_LAST }; @@ -304,6 +325,7 @@ struct _virDomainChrDef { union { int port; /* parallel, serial, console */ virSocketAddrPtr addr; /* guestfwd */ + char *name; /* virtio */ } target; int type; @@ -744,6 +766,7 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info, int type); int virDomainDevicePCIAddressIsValid(virDomainDevicePCIAddressPtr addr); int virDomainDeviceDriveAddressIsValid(virDomainDeviceDriveAddressPtr addr); +int virDomainDeviceVirtioSerialAddressIsValid(virDomainDeviceVirtioSerialAddressPtr addr); int virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info); void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info); void virDomainDefClearPCIAddresses(virDomainDefPtr def); @@ -790,7 +813,7 @@ virDomainObjPtr virDomainObjParseNode(virCapsPtr caps, xmlDocPtr xml, xmlNodePtr root); -int virDomainDefAddDiskControllers(virDomainDefPtr def); +int virDomainDefAddImplicitControllers(virDomainDefPtr def); #endif char *virDomainDefFormat(virDomainDefPtr def, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index aa826d6..284db08 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -186,7 +186,7 @@ virDomainDeviceInfoIsSet; virDomainControllerTypeToString; virDomainControllerDefFree; virDomainDeviceAddressTypeToString; -virDomainDefAddDiskControllers; +virDomainDefAddImplicitControllers; virDomainDefClearPCIAddresses; virDomainDefClearDeviceAliases; virDomainDeviceInfoIterate; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index c9fe55b..456ee34 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -5697,7 +5697,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, goto no_memory; } - if (virDomainDefAddDiskControllers(def) < 0) + if (virDomainDefAddImplicitControllers(def) < 0) goto error; return def; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml new file mode 100644 index 0000000..29af510 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.xml @@ -0,0 +1,35 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219200</memory> + <currentMemory>219200</currentMemory> + <vcpu cpuset='1-4,8-20,525'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </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> + <controller type='ide' index='0'/> + <controller type='virtio-serial' index='0' max_ports='16' vectors='4'/> + <controller type='virtio-serial' index='1'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/> + </controller> + <channel type='pty'> + <target type='virtio' name='org.linux-kvm.port.0'/> + </channel> + <channel type='pty'> + <target type='virtio' name='org.linux-kvm.port.1'/> + <address type='virtio-serial' controller='1' bus='0'/> + </channel> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index e807d7b..ace2be8 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -133,6 +133,7 @@ mymain(int argc, char **argv) DO_TEST("parallel-tcp"); DO_TEST("console-compat"); DO_TEST("channel-guestfwd"); + DO_TEST("channel-virtio"); DO_TEST("hostdev-usb-address"); DO_TEST("hostdev-pci-address"); -- 1.6.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list