Laine Stump wrote:
On 01/05/2017 09:46 AM, Roman Bogorodskiy wrote:
> As bhyve for a long time didn't have a notion of the explicit SATA
> controller and created a controller for each drive, the bhyve driver
> in libvirt acted in a similar way and didn't care about the SATA
> controllers and assigned PCI addresses to drives directly, as
> the generated command will look like this anyway:
>
> 2:0,ahci-hd,somedisk.img
>
> This no longer makes sense because:
>
> 1. After commit c07d1c1c4f it's not possible to assign
> PCI addresses to disks
> 2. Bhyve now supports multiple disk drives for a controller,
> so it's going away from 1:1 controller:disk mapping, so
> the controller object starts to make more sense now
>
> So, this patch does the following:
>
> - Assign PCI address to SATA controllers (previously we didn't do this)
> - Assign disk addresses instead of PCI addresses for disks. Now, when
> building a bhyve command, we take PCI address not from the disk
> itself but from its controller
> - Assign addresses at XML parsing time using the
> assignAddressesCallback. This is done mainly for being able to
> verify address allocation via xml2xml tests
> - Adjust existing bhyvexml2{xml,argv} tests to chase the new
> address allocation
>
> This patch is largely based on work of Fabian Freyer.
> ---
> po/POTFILES.in | 1 +
> src/bhyve/bhyve_command.c | 143 ++++++++++++++++-----
> src/bhyve/bhyve_device.c | 33 ++---
> src/bhyve/bhyve_domain.c | 60 ++++++++-
> .../bhyvexml2argvdata/bhyvexml2argv-acpiapic.args | 4 +-
> tests/bhyvexml2argvdata/bhyvexml2argv-base.args | 4 +-
> .../bhyvexml2argv-bhyveload-bootorder.args | 5 +-
> .../bhyvexml2argv-bhyveload-bootorder1.args | 5 +-
> .../bhyvexml2argv-bhyveload-bootorder3.args | 5 +-
> .../bhyvexml2argv-bhyveload-explicitargs.args | 4 +-
> tests/bhyvexml2argvdata/bhyvexml2argv-console.args | 2 +-
> .../bhyvexml2argv-custom-loader.args | 4 +-
> .../bhyvexml2argv-disk-cdrom-grub.args | 4 +-
> .../bhyvexml2argv-disk-cdrom.args | 4 +-
> .../bhyvexml2argv-grub-bootorder.args | 6 +-
> .../bhyvexml2argv-grub-bootorder2.args | 6 +-
> .../bhyvexml2argv-grub-defaults.args | 4 +-
> .../bhyvexml2argvdata/bhyvexml2argv-localtime.args | 4 +-
> tests/bhyvexml2argvdata/bhyvexml2argv-macaddr.args | 4 +-
> .../bhyvexml2argv-serial-grub-nocons.args | 2 +-
> .../bhyvexml2argv-serial-grub.args | 2 +-
> tests/bhyvexml2argvdata/bhyvexml2argv-serial.args | 2 +-
> tests/bhyvexml2argvtest.c | 2 +-
> .../bhyvexml2xmlout-acpiapic.xml | 4 +-
> tests/bhyvexml2xmloutdata/bhyvexml2xmlout-base.xml | 4 +-
> .../bhyvexml2xmlout-bhyveload-bootorder.xml | 4 +-
> .../bhyvexml2xmlout-bhyveload-bootorder1.xml | 4 +-
> .../bhyvexml2xmlout-bhyveload-bootorder2.xml | 4 +-
> .../bhyvexml2xmlout-bhyveload-bootorder3.xml | 4 +-
> .../bhyvexml2xmlout-bhyveload-bootorder4.xml | 4 +-
> .../bhyvexml2xmlout-bhyveload-explicitargs.xml | 4 +-
> .../bhyvexml2xmlout-console.xml | 4 +-
> .../bhyvexml2xmlout-custom-loader.xml | 4 +-
> .../bhyvexml2xmlout-disk-cdrom-grub.xml | 4 +-
> .../bhyvexml2xmlout-disk-cdrom.xml | 4 +-
> .../bhyvexml2xmlout-grub-bootorder.xml | 4 +-
> .../bhyvexml2xmlout-grub-bootorder2.xml | 4 +-
> .../bhyvexml2xmlout-grub-defaults.xml | 4 +-
> .../bhyvexml2xmlout-localtime.xml | 4 +-
> .../bhyvexml2xmlout-macaddr.xml | 4 +-
> .../bhyvexml2xmlout-metadata.xml | 5 +-
> .../bhyvexml2xmlout-serial-grub-nocons.xml | 4 +-
> .../bhyvexml2xmlout-serial-grub.xml | 4 +-
> .../bhyvexml2xmloutdata/bhyvexml2xmlout-serial.xml | 4 +-
> tests/bhyvexml2xmltest.c | 2 +
> 45 files changed, 279 insertions(+), 118 deletions(-)
>
> diff --git a/po/POTFILES.in b/po/POTFILES.in
> index e66bb7a3a..632aa7736 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -14,6 +14,7 @@ src/access/viraccessdriverpolkit.c
> src/access/viraccessmanager.c
> src/bhyve/bhyve_command.c
> src/bhyve/bhyve_device.c
> +src/bhyve/bhyve_domain.c
> src/bhyve/bhyve_driver.c
> src/bhyve/bhyve_monitor.c
> src/bhyve/bhyve_parse_command.c
> diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c
> index 8a29977ff..a2fd40378 100644
> --- a/src/bhyve/bhyve_command.c
> +++ b/src/bhyve/bhyve_command.c
> @@ -148,40 +148,97 @@ bhyveBuildConsoleArgStr(const virDomainDef *def, virCommandPtr
cmd)
> }
>
> static int
> -bhyveBuildDiskArgStr(const virDomainDef *def ATTRIBUTE_UNUSED,
> - virDomainDiskDefPtr disk,
> - virCommandPtr cmd)
> +bhyveBuildAHCIControllerArgStr(const virDomainDef *def,
> + virDomainControllerDefPtr controller,
> + virConnectPtr conn,
> + virCommandPtr cmd)
> {
> - const char *bus_type;
> + virBuffer buf = VIR_BUFFER_INITIALIZER;
> + virBuffer device = VIR_BUFFER_INITIALIZER;
> const char *disk_source;
> + size_t i;
> + int ret = -1;
> +
> + for (i = 0; i < def->ndisks; i++) {
> + virDomainDiskDefPtr disk = def->disks[i];
> + if (disk->bus != VIR_DOMAIN_DISK_BUS_SATA)
> + continue;
> +
> + if (disk->info.addr.drive.controller != controller->idx)
> + continue;
Took a minute for me to see why you were doing this - so all the disks
attached to a controller are put directly into the controller's
commandline arg rather than them being separate args with a ref back to
the controller.
True.
> +
> + VIR_DEBUG("disk %zu controller %d", i, controller->idx);
> +
> + if ((virDomainDiskGetType(disk) != VIR_STORAGE_TYPE_FILE) &&
> + (virDomainDiskGetType(disk) != VIR_STORAGE_TYPE_VOLUME)) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("unsupported disk type"));
> + goto error;
> + }
> +
> + if (virStorageTranslateDiskSourcePool(conn, disk) < 0)
> + goto error;
> +
> + disk_source = virDomainDiskGetSource(disk);
> +
> + if ((disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) &&
> + (disk_source == NULL)) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("cdrom device without source path "
> + "not supported"));
> + goto error;
> + }
>
> - switch (disk->bus) {
> - case VIR_DOMAIN_DISK_BUS_SATA:
> switch (disk->device) {
> case VIR_DOMAIN_DISK_DEVICE_DISK:
> - bus_type = "ahci-hd";
> + if ((bhyveDriverGetCaps(conn) & BHYVE_CAP_AHCI32SLOT) != 0)
The "!= 0" is superfluous.
Will fix.
> + virBufferAsprintf(&device,
",hd:%s", disk_source);
> + else
> + virBufferAsprintf(&device, "-hd,%s", disk_source);
> break;
> case VIR_DOMAIN_DISK_DEVICE_CDROM:
> - bus_type = "ahci-cd";
> + if ((bhyveDriverGetCaps(conn) & BHYVE_CAP_AHCI32SLOT) != 0)
Same here.
Will fix it here too.
> + virBufferAsprintf(&device, ",cd:%s", disk_source);
> + else
> + virBufferAsprintf(&device, "-cd,%s", disk_source);
It seems like there could be some consolidation of the multiple
nearly-identical printf's here. Possibly not worth the trouble though.
> break;
> default:
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> _("unsupported disk device"));
> - return -1;
> - }
> - break;
> - case VIR_DOMAIN_DISK_BUS_VIRTIO:
> - if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
> - bus_type = "virtio-blk";
> - } else {
> - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> - _("unsupported disk device"));
> - return -1;
> + goto error;
> }
> - break;
> - default:
> + virBufferAddBuffer(&buf, &device);
> + virBufferFreeAndReset(&device);
> + }
> +
> + if (virBufferCheckError(&buf) <0)
> + goto error;
> +
> + virCommandAddArg(cmd, "-s");
> + virCommandAddArgFormat(cmd, "%d:0,ahci%s",
> + controller->info.addr.pci.slot,
> + virBufferCurrentContent(&buf));
> +
> + ret = 0;
> + error:
> + virBufferFreeAndReset(&buf);
> + return ret;
> +}
> +
> +static int
> +bhyveBuildVirtIODiskArgStr(const virDomainDef *def ATTRIBUTE_UNUSED,
> + virDomainDiskDefPtr disk,
> + virConnectPtr conn,
> + virCommandPtr cmd)
> +{
> + const char *disk_source;
> +
> + if (virStorageTranslateDiskSourcePool(conn, disk) < 0)
> + return -1;
> +
> + if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> - _("unsupported disk bus type"));
> + _("unsupported disk device"));
> return -1;
> }
>
> @@ -194,17 +251,9 @@ bhyveBuildDiskArgStr(const virDomainDef *def ATTRIBUTE_UNUSED,
>
> disk_source = virDomainDiskGetSource(disk);
>
> - if ((disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) &&
> - (disk_source == NULL)) {
> - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> - _("cdrom device without source path "
> - "not supported"));
> - return -1;
> - }
> -
> virCommandAddArg(cmd, "-s");
> - virCommandAddArgFormat(cmd, "%d:0,%s,%s",
> - disk->info.addr.pci.slot, bus_type,
> + virCommandAddArgFormat(cmd, "%d:0,virtio-blk,%s",
> + disk->info.addr.pci.slot,
> disk_source);
>
> return 0;
> @@ -278,6 +327,22 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
>
> virCommandAddArgList(cmd, "-s", "0:0,hostbridge", NULL);
> /* Devices */
> + for (i = 0; i < def->ncontrollers; i++) {
> + virDomainControllerDefPtr controller = def->controllers[i];
> + switch (controller->type) {
> + case VIR_DOMAIN_CONTROLLER_TYPE_PCI:
> + if (controller->model != VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT)
{
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> + "%s", _("unsupported PCI
controller model: only PCI root supported"));
> + goto error;
> + }
> + break;
> + case VIR_DOMAIN_CONTROLLER_TYPE_SATA:
> + if (bhyveBuildAHCIControllerArgStr(def, controller, conn, cmd) <
0)
> + goto error;
> + break;
> + }
> + }
> for (i = 0; i < def->nnets; i++) {
> virDomainNetDefPtr net = def->nets[i];
> if (bhyveBuildNetArgStr(def, net, cmd, dryRun) < 0)
> @@ -286,11 +351,19 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn,
> for (i = 0; i < def->ndisks; i++) {
> virDomainDiskDefPtr disk = def->disks[i];
>
> - if (virStorageTranslateDiskSourcePool(conn, disk) < 0)
> - goto error;
> -
> - if (bhyveBuildDiskArgStr(def, disk, cmd) < 0)
> + switch (disk->bus) {
> + case VIR_DOMAIN_DISK_BUS_SATA:
> + /* Handled by AHCI controller */
> + break;
This is a bit odd, but I see why you're doing it. Maybe you should put
the full name of the function (bhyveBuildAHCIControllerArgStr) in the
comment rather than just "AHCI controller".
Good idea.
Aside from these minor nits, my only concern is that of compatibility
when migrating forward and backward, but since I don't have a system
with bhyve I can't test that, so I'll assume that you've done your due
diligence in that regard. (Also, I'm assuming that you've successfully
run make syntax-check in addition to make check). Based on those
assumptions, ACK.
Unfortunately, it's neither forward or backward compatible. I was
thinking about preparing a script that strips addresses for the SATA
devices so user can undefine/define a domain and let libvirt regenerate
the proper addresses.
Thanks,
Roman Bogorodskiy