On Thu, Feb 13, 2014 at 02:14:32PM +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]; > + > + if (disk->bus != VIR_DOMAIN_DISK_BUS_SATA) { > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("unsupported disk bus type")); > + return -1; > + } > + > + if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) { > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("unsupported disk type")); > + return -1; > + } We still need to validate disk->type before accessing disk->src otherwise you'll crash if someone uses type=network > + > + virCommandAddArg(cmd, "-s"); > + virCommandAddArgFormat(cmd, "2:0,ahci-hd,%s", disk->src); What is the '2:0' bit here ? Is that disk controller/unit number ? > +virCommandPtr > +virBhyveProcessBuildLoadCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED, > + virDomainObjPtr vm) > +{ > + virCommandPtr cmd; > + virDomainDiskDefPtr disk; > + > + if (vm->def->ndisks != 1) { > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("domain should have one and only one disk defined")); > + return NULL; > + } > + > + disk = vm->def->disks[0]; > + > + if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) { > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("unsupported disk type")); > + return NULL; > + } And validate disk->type again here > + > + 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); > + > + /* VM name */ > + virCommandAddArg(cmd, vm->def->name); > + > + return cmd; > +} > +static char * > +bhyveConnectGetCapabilities(virConnectPtr conn) > +{ > + bhyveConnPtr privconn = conn->privateData; > + char *xml; > + > + if (virConnectGetCapabilitiesEnsureACL(conn) < 0) > + return NULL; > + > + bhyveDriverLock(privconn); > + if ((xml = virCapabilitiesFormatXML(privconn->caps)) == NULL) > + virReportOOMError(); > + bhyveDriverUnlock(privconn); > + > + return xml; > +} Technically the lock/unlock isn't needed since you never change privconn->caps once you've created it. > +static virDrvOpenStatus > +bhyveConnectOpen(virConnectPtr conn, > + virConnectAuthPtr auth ATTRIBUTE_UNUSED, > + unsigned int flags) > +{ > + virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR); > + > + if (conn->uri == NULL) { > + if (bhyve_driver == NULL) > + return VIR_DRV_OPEN_DECLINED; > + > + if (!(conn->uri = virURIParse("bhyve:///system"))) > + return VIR_DRV_OPEN_ERROR; Nitpick indentation is too great in the two 'return' lines > + } else { > + 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; > + } > + } > + > + if (virConnectOpenEnsureACL(conn) < 0) > + 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")); Remove the 'virReportError' call, since that's already done for you by the parsing code. > + goto cleanup; > + } > + > + if (virDomainDefineXMLEnsureACL(conn, def) < 0) > + goto cleanup; > + > + if (!(vm = virDomainObjListAdd(privconn->domains, def, > + privconn->xmlopt, > + 0, &oldDef))) > + goto cleanup; > + def = NULL; > + > + 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; > + > +cleanup: > + virDomainDefFree(def); > + if (vm) > + virObjectUnlock(vm); > + > + return dom; > +} > + > + > +int > +virBhyveProcessStart(virConnectPtr conn, > + bhyveConnPtr driver, > + virDomainObjPtr vm, > + virDomainRunningReason reason) > +{ > + char *logfile = NULL; > + int logfd = -1; > + off_t pos = -1; > + char ebuf[1024]; > + virCommandPtr cmd = NULL; > + virCommandPtr load_cmd = NULL; > + bhyveConnPtr privconn = conn->privateData; > + int ret = -1, status; > + > + if (virAsprintf(&logfile, "%s/%s.log", > + BHYVE_LOG_DIR, vm->def->name) < 0) > + return -1; > + > + > + if ((logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, > + S_IRUSR|S_IWUSR)) < 0) { > + virReportSystemError(errno, > + _("Failed to open '%s'"), > + logfile); > + goto cleanup; > + } > + > + 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; > + > + virCommandSetOutputFD(cmd, &logfd); > + virCommandSetErrorFD(cmd, &logfd); > + virCommandWriteArgLog(cmd, logfd); > + virCommandSetPidFile(cmd, privconn->pidfile); > + virCommandDaemonize(cmd); > + > + /* Now bhyve command is constructed, meaning the > + * domain is ready to be started, so we can build > + * and execute bhyveload command */ > + if (!(load_cmd = virBhyveProcessBuildLoadCmd(driver, > + vm))) > + goto cleanup; > + virCommandSetOutputFD(load_cmd, &logfd); > + virCommandSetErrorFD(load_cmd, &logfd); > + > + /* Log generated command line */ > + virCommandWriteArgLog(load_cmd, logfd); > + if ((pos = lseek(logfd, 0, SEEK_END)) < 0) > + VIR_WARN("Unable to seek to end of logfile: %s", > + virStrerror(errno, ebuf, sizeof(ebuf))); > + > + VIR_INFO("Loading domain '%s'", vm->def->name); > + if (virCommandRun(load_cmd, &status) < 0) > + goto cleanup; > + > + if (status != 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Guest failed to load: %d"), status); > + goto cleanup; > + } > + > + /* Now we can start the domain */ > + VIR_INFO("Starting domain '%s'", vm->def->name); I'd suggest s/INFO/DEBUG/ here and earlier. If you want user visible log messages about key operations, then we should talk about what is needed to make viraudit.{c,h} work on FreeBSD, and use domain_audit.c for this. > + ret = virCommandRun(cmd, NULL); > + > + if (ret == 0) { > + if (virPidFileReadPath(privconn->pidfile, &vm->pid) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Domain %s didn't show up"), vm->def->name); > + goto cleanup; > + } > + > + vm->def->id = vm->pid; > + virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason); > + } else { > + goto cleanup; > + } > + > +cleanup: > + if (ret < 0) { > + virCommandPtr destroy_cmd; > + if ((destroy_cmd = virBhyveProcessBuildDestroyCmd(driver, vm)) != NULL) { > + virCommandSetOutputFD(load_cmd, &logfd); > + virCommandSetErrorFD(load_cmd, &logfd); > + ignore_value(virCommandRun(destroy_cmd, NULL)); > + virCommandFree(destroy_cmd); > + } > + } > + > + virCommandFree(load_cmd); > + virCommandFree(cmd); > + VIR_FREE(logfile); > + if (VIR_CLOSE(logfd) < 0) { > + virReportSystemError(errno, "%s", _("could not close logfile")); > + } You can use VIR_FORCE_CLOSE and ignore the error message here. > + return ret; > +} 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 :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list