A simple getopt-based argument parser is added for the /usr/sbin/bhyveload command, loosely based on its argument parser. The boot disk is guessed by iterating over all disks and matching their sources. If any non-default arguments are found, def->os.bootloaderArgs is set accordingly, and the bootloader is treated as a custom bootloader. Custom bootloader are supported by setting the def->os.bootloader and def->os.bootloaderArgs accordingly grub-bhyve is also treated as a custom bootloader. Since we don't get the device map in the native format anyways, we can't reconstruct the complete boot order. While it is possible to check what type the grub boot disk is by checking if the --root argument is "cd" or "hd0,msdos1", and then just use the first disk found, implementing the grub-bhyve argument parser as-is in the grub-bhyve source would mean adding a dependency to argp or duplicating lots of the code of argp. Therefore it's not really worth implementing that now. Signed-off-by: Fabian Freyer <fabian.freyer@xxxxxxxxxxxxxxxxxxx> --- src/bhyve/bhyve_parse_command.c | 122 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/src/bhyve/bhyve_parse_command.c b/src/bhyve/bhyve_parse_command.c index be4ff2a..6600111 100644 --- a/src/bhyve/bhyve_parse_command.c +++ b/src/bhyve/bhyve_parse_command.c @@ -712,6 +712,121 @@ error: return -1; } +/* + * Parse the /usr/sbin/bhyveload command line. + */ +static int +bhyveParseBhyveLoadCommandLine(virDomainDefPtr def, + int argc, char **argv) +{ + int c; + /* bhyveload called with default arguments when only -m and -d are given. + * Store this in a bit field and check if only those two options are given + * later */ + unsigned arguments = 0; + size_t memory = 0; + struct _getopt_data *parser; + int i = 0; + + const char optstr[] = "CSc:d:e:h:l:m:"; + + if (!argv) + goto error; + + if (VIR_ALLOC(parser) < 0) + goto error; + + while ((c = _getopt_internal_r(argc, argv, optstr, + NULL, NULL, 0, parser, 0)) != -1) { + switch (c) { + case 'd': + arguments |= 1; + /* Iterate over the disks of the domain trying to match up the + * source */ + for (i = 0; i < def->ndisks; i++) { + if (STREQ(virDomainDiskGetSource(def->disks[i]), + parser->optarg)) { + def->disks[i]->info.bootIndex = i; + break; + } + } + break; + case 'm': + arguments |= 2; + if (virStrToLong_ul(parser->optarg, NULL, 10, &memory) < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("Failed to parse Memory.")); + goto error; + } + if (memory < 1024) + memory *= 1024; + else + memory /= 1024UL; + if (def->mem.cur_balloon != 0 && def->mem.cur_balloon != memory) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("Failed to parse Memory: Memory size mismatch.")); + goto error; + } + def->mem.cur_balloon = memory; + virDomainDefSetMemoryTotal(def, memory); + break; + default: + arguments |= 4; + } + } + + if (arguments != 3) { + /* Set os.bootloader since virDomainDefFormatInternal will only format + * the bootloader arguments if os->bootloader is set. */ + if (VIR_STRDUP(def->os.bootloader, argv[0]) < 0) + goto error; + + def->os.bootloaderArgs = virStringJoin((const char**) &argv[1], " "); + } + + if (argc != parser->optind) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("Failed to parse arguments for bhyveload command.")); + goto error; + } + + if (def->name == NULL) { + if (VIR_STRDUP(def->name, argv[argc]) < 0) + goto error; + } + else if (STRNEQ(def->name, argv[argc])) { + /* the vm name of the loader and the bhyverun command differ, throw an + * error here */ + virReportError(VIR_ERR_OPERATION_FAILED, + _("Failed to parse arguments: VM name mismatch.")); + goto error; + } + + VIR_FREE(parser); + return 0; +error: + VIR_FREE(parser); + return -1; +} + +static int +bhyveParseCustomLoaderCommandLine(virDomainDefPtr def, + int argc ATTRIBUTE_UNUSED, + char **argv) +{ + if (!argv) + goto error; + + if (VIR_STRDUP(def->os.bootloader, argv[0]) < 0) + goto error; + + def->os.bootloaderArgs = virStringJoin((const char**) &argv[1], " "); + + return 0; +error: + return -1; +} + virDomainDefPtr bhyveParseCommandLineString(const char* nativeConfig, unsigned caps, @@ -745,6 +860,13 @@ bhyveParseCommandLineString(const char* nativeConfig, if (bhyveParseBhyveCommandLine(def, xmlopt, caps, bhyve_argc, bhyve_argv)) goto cleanup; + if (STREQ(loader_argv[0], "/usr/sbin/bhyveload")) { + if (bhyveParseBhyveLoadCommandLine(def, loader_argc, loader_argv)) + goto cleanup; + } + else if (loader_argv) + if (bhyveParseCustomLoaderCommandLine(def, loader_argc, loader_argv)) + goto cleanup; cleanup: virStringFreeList(loader_argv); -- 2.7.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list