
On Sun, Feb 09, 2014 at 06:46:12PM +0400, Roman Bogorodskiy wrote:
+static int +bhyveBuildDiskArgStr(const virDomainDef *def, virCommandPtr cmd) +{ + virDomainDiskDefPtr disk; + + if (def->ndisks != 1) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("domain should have one and only one disk defined")); + return -1; + } + + disk = def->disks[0]; + + virCommandAddArg(cmd, "-s"); + virCommandAddArgFormat(cmd, "2:0,ahci-hd,%s", disk->src);
Before accessing disk->src, you need to check what disk->type is - the 'src' field is only valid for file/block backed disks, not network backed ones. Also based on the fact that your arg contains the string 'ahci' is is correct to say this is exposing a SATA bus disk ? If so, you also want to validate disk->bus == VIR_DOMAIN_DISK_BUS_SATA and disk->device == VIR_DOMAIN_DISK_DEVICE_DISK and report CONFIG_UNSUPPORTED in both cases.
+ /* Clarification about -H and -P flags from Peter Grehan: + * -H and -P flags force the guest to exit when it executes IA32 HLT and PAUSE + * instructions respectively. + * + * For the HLT exit, bhyve uses that to infer that the guest is idling and can + * be put to sleep until an external event arrives. If this option is not used, + * the guest will always use 100% of CPU on the host. + * + * The PAUSE exit is most useful when there are large numbers of guest VMs running, + * since it forces the guest to exit when it spins on a lock acquisition. + */ + virCommandAddArg(cmd, "-H"); /* vmexit from guest on hlt */ + virCommandAddArg(cmd, "-P"); /* vmexit from guest on pause */
Ok, agree that both of those make sense to enable unconditionally.
+ virCommandAddArg(cmd, "-S"); + virCommandAddArg(cmd, "31,uart");
Hmm, this is enabling a serial port right ? If so, you only want todo this if you have def->nserials == 1 I reckon. What is the string '31' saying ?
+virCommandPtr +virBhyveProcessBuildLoadCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED, + virDomainObjPtr vm) +{ + virCommandPtr cmd; + virDomainDiskDefPtr disk = vm->def->disks[0]; + + cmd = virCommandNew(BHYVELOAD); + + /* Memory */ + virCommandAddArg(cmd, "-m"); + virCommandAddArgFormat(cmd, "%llu", + VIR_DIV_UP(vm->def->mem.max_balloon, 1024)); + + /* Image path */ + virCommandAddArg(cmd, "-d"); + virCommandAddArgFormat(cmd, disk->src);
Curious, so you have to repeat the disk specification in two commands. Same comment about validating the disk->type before accessing 'src'
diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c new file mode 100644 index 0000000..e8e082b --- /dev/null +++ b/src/bhyve/bhyve_driver.c +static virDrvOpenStatus +bhyveConnectOpen(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + unsigned int flags) +{ + virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR); + + if (!conn->uri) + return VIR_DRV_OPEN_DECLINED;
This means that you'll never be able to default to "bhyve" when URI == NULL. Generally we have this auto-detected eg if (conn->uri == NULL) { if (bhyve_driver == NULL) { return VIR_DRV_OPEN_DECLINED } ...accept... } else { ...all the logic below.... See qemuConnectOpen for an example of logic to follow
+ + if (!conn->uri->scheme || STRNEQ(conn->uri->scheme, "bhyve")) + return VIR_DRV_OPEN_DECLINED; + + if (conn->uri->server) + return VIR_DRV_OPEN_DECLINED; + + if (!STREQ_NULLABLE(conn->uri->path, "/system")) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected bhyve URI path '%s', try bhyve:///system"), + conn->uri->path); + return VIR_DRV_OPEN_ERROR; + } + + if (bhyve_driver == NULL) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("bhyve state driver is not active")); + return VIR_DRV_OPEN_ERROR; + } + + conn->privateData = bhyve_driver; + + return VIR_DRV_OPEN_SUCCESS; +}
+static virDomainPtr +bhyveDomainDefineXML(virConnectPtr conn, const char *xml) +{ + bhyveConnPtr privconn = conn->privateData; + virDomainPtr dom = NULL; + virDomainDefPtr def = NULL; + virDomainDefPtr oldDef = NULL; + virDomainObjPtr vm = NULL; + + if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt, + 1 << VIR_DOMAIN_VIRT_BHYVE, + VIR_DOMAIN_XML_INACTIVE)) == NULL) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Can't parse XML desc")); + goto cleanup; + } + + if (!(vm = virDomainObjListAdd(privconn->domains, def, + privconn->xmlopt, + 0, &oldDef))) + goto cleanup; + + VIR_INFO("Creating domain '%s'", vm->def->name); + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); + if (dom) dom->id = vm->def->id; + + if (virDomainSaveConfig(BHYVE_CONFIG_DIR, vm->def) < 0) { + goto cleanup; + }
Nit-pick: we avoid {} for a single-line body
+static int +bhyveConnectListDefinedDomains(virConnectPtr conn, char **const names, + int maxnames) +{ + bhyveConnPtr privconn = conn->privateData; + int n; + + memset(names, 0, sizeof(*names) * maxnames); + n = virDomainObjListGetInactiveNames(privconn->domains, names, + maxnames, NULL, NULL); + + return n; +} + +static int +bhyveConnectNumOfDefinedDomains(virConnectPtr conn) +{ + bhyveConnPtr privconn = conn->privateData; + int count; + + count = virDomainObjListNumOfDomains(privconn->domains, false, + NULL, NULL); + + return count; +} + +static int +bhyveConnectListAllDomains(virConnectPtr conn, + virDomainPtr **domains, + unsigned int flags) +{ + bhyveConnPtr privconn = conn->privateData; + int ret = -1; + + virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); + + ret = virDomainObjListExport(privconn->domains, conn, domains, + NULL, flags); + + return ret; +}
+int +virBhyveProcessStart(virConnectPtr conn, + bhyveConnPtr driver, + virDomainObjPtr vm, + virDomainRunningReason reason)
+ VIR_INFO("Loading domain '%s'", vm->def->name); + if (virCommandRun(cmd, &status) < 0) + goto cleanup;
Now the domain is loaded...
+ + if (status != 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Guest failed to load: %d"), status); + goto cleanup; + } + + virCommandFree(cmd); + + VIR_FREE(privconn->pidfile); + if (!(privconn->pidfile = virPidFileBuildPath(BHYVE_STATE_DIR, + vm->def->name))) { + virReportSystemError(errno, + "%s", _("Failed to build pidfile path.")); + goto cleanup; + } + + if (unlink(privconn->pidfile) < 0 && + errno != ENOENT) { + virReportSystemError(errno, + _("Cannot remove state PID file %s"), + privconn->pidfile); + goto cleanup; + } + + /* Call bhyve to start the VM */ + if (!(cmd = virBhyveProcessBuildBhyveCmd(driver, + vm))) + goto cleanup;
I'd suggest this building is done before loading the domain so you don't needlessly load the domain before we detect any possible user configuration errors. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|