Page MenuHomeFreeBSD

D2448.id5203.diff
No OneTemporary

D2448.id5203.diff

Index: share/examples/bhyve/guest.conf.sample
===================================================================
--- /dev/null
+++ share/examples/bhyve/guest.conf.sample
@@ -0,0 +1,11 @@
+#
+# Example: bhyve guest configuration file.
+#
+name = FreeBSD_Guest
+memory = 2048M
+vcpus = 2
+bootdisk = /path/bootable.img
+disk = "/path/disk1.img,/path/disk2.img"
+isofile = /path/FreeBSD-bootonly.iso
+iface = "tap1,tap2"
+console = "stdio"
Index: usr.sbin/bhyve/Makefile
===================================================================
--- usr.sbin/bhyve/Makefile
+++ usr.sbin/bhyve/Makefile
@@ -14,6 +14,7 @@
bhyverun.c \
block_if.c \
consport.c \
+ config.c \
dbgport.c \
inout.c \
ioapic.c \
@@ -43,7 +44,8 @@
.PATH: ${.CURDIR}/../../sys/amd64/vmm
SRCS+= vmm_instruction_emul.c
-LIBADD= vmmapi md pthread
+CFLAGS+=-I${.CURDIR}/../../contrib/libucl/include
+LIBADD= vmmapi md pthread ucl
WARNS?= 2
Index: usr.sbin/bhyve/bhyve.8
===================================================================
--- usr.sbin/bhyve/bhyve.8
+++ usr.sbin/bhyve/bhyve.8
@@ -41,6 +41,8 @@
.Op Fl s Ar slot,emulation Ns Op , Ns Ar conf
.Op Fl U Ar uuid
.Ar vmname
+.Nm
+.Op Fl f Ar guest.conf
.Sh DESCRIPTION
.Nm
is a hypervisor that runs guest operating systems inside a
@@ -260,6 +262,8 @@
Alphanumeric name of the guest.
This should be the same as that created by
.Xr bhyveload 8 .
+.It Fl f
+Use a configuration file.
.El
.Sh EXAMPLES
The guest operating system must have been loaded with
@@ -308,6 +312,11 @@
-l com1,/dev/nmdm0A \\
-A -H -P -m 8G
.Ed
+.Pp
+To create a virtual machine using a configuration file:
+.Bd -literal -offset ident
+bhyve -f guest.conf
+.Ed
.Sh SEE ALSO
.Xr bhyve 4 ,
.Xr nmdm 4 ,
Index: usr.sbin/bhyve/bhyverun.c
===================================================================
--- usr.sbin/bhyve/bhyverun.c
+++ usr.sbin/bhyve/bhyverun.c
@@ -67,6 +67,9 @@
#include "spinup_ap.h"
#include "rtc.h"
+#include "config.h"
+#include <ucl.h>
+
#define GUEST_NIO_PORT 0x488 /* guest upcalls via i/o port */
#define MB (1024UL * 1024)
@@ -697,6 +700,10 @@
struct vmctx *ctx;
uint64_t rip;
size_t memsize;
+ struct config_entry cb;
+ char temp[STR_SIZE];
+ char *multiface, *multidisk = NULL;
+ int slot = 0;
bvmcons = 0;
dump_guest_memory = 0;
@@ -707,8 +714,61 @@
mptgen = 1;
rtc_localtime = 1;
- while ((c = getopt(argc, argv, "abehuwxACHIPWYp:g:c:s:m:l:U:")) != -1) {
+ while ((c = getopt(argc, argv, "abehuwxACHIPWYp:g:c:s:m:l:U:f:")) != -1) {
switch (c) {
+ case 'f':
+ cb = parse_conf(optarg);
+ guest_ncpus = cb.vcpus;
+ vm_parse_memsize(cb.memsize, &memsize);
+ vmname = cb.vmname;
+ acpi = 1;
+ guest_vmexit_on_hlt = 1;
+ guest_vmexit_on_pause = 1;
+ gdb_port = 0;
+
+ snprintf(temp, sizeof(temp), "%d:0,hostbridge", slot);
+ pci_parse_slot(temp);
+ slot += 1;
+
+ memset(temp, '\0', STR_SIZE);
+ snprintf(temp, sizeof(temp), "%d:0,lpc", slot);
+ pci_parse_slot(temp);
+ slot += 1;
+
+ while ((multiface = strsep(&cb.iface, ",")) != NULL) {
+ memset(temp, '\0', STR_SIZE);
+ snprintf(temp, sizeof(temp), "%d:0,virtio-net,%s",
+ slot, multiface);
+ pci_parse_slot(temp);
+ slot += 1;
+ }
+
+ if (cb.isofile) {
+ memset(temp, '\0', STR_SIZE);
+ snprintf(temp, sizeof(temp), "%d:0,virtio-blk,%s",
+ slot, cb.isofile);
+ pci_parse_slot(temp);
+ slot += 1;
+ }
+
+ memset(temp, '\0', STR_SIZE);
+ snprintf(temp, sizeof(temp), "%d:0,virtio-blk,%s",
+ slot, cb.bootdisk);
+ pci_parse_slot(temp);
+ slot += 1;
+
+ while ((multidisk = strsep(&cb.vdisk, ",")) != NULL) {
+ memset(temp, '\0', STR_SIZE);
+ snprintf(temp, sizeof(temp), "%d:0,virtio-blk,%s",
+ slot, multidisk);
+ pci_parse_slot(temp);
+ slot += 1;
+ }
+
+ memset(temp, '\0', STR_SIZE);
+ snprintf(temp, sizeof(temp), "com1,%s", cb.console);
+ lpc_device_parse(temp);
+ break;
case 'a':
x2apic_mode = 0;
break;
@@ -794,10 +854,8 @@
argc -= optind;
argv += optind;
- if (argc != 1)
- usage(1);
-
- vmname = argv[0];
+ if (!vmname)
+ vmname = argv[0];
ctx = vm_open(vmname);
if (ctx == NULL) {
@@ -821,8 +879,9 @@
if (dump_guest_memory)
vm_set_memflags(ctx, VM_MEM_F_INCORE);
+
err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL);
- if (err) {
+ if (err) {
fprintf(stderr, "Unable to setup memory (%d)\n", err);
exit(1);
}
@@ -874,11 +933,6 @@
}
/*
- * Change the proc title to include the VM name.
- */
- setproctitle("%s", vmname);
-
- /*
* Add CPU 0
*/
fbsdrun_addcpu(ctx, BSP, BSP, rip);
Index: usr.sbin/bhyve/config.h
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/config.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2015 Marcelo Araujo <araujo@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#define STR_SIZE 254
+
+struct config_entry {
+ char *vmname;
+ char *memsize;
+ int vcpus;
+ char *iface;
+ char *console;
+ char *bootdisk;
+ char *vdisk;
+ char *isofile;
+};
+
+struct config_entry parse_conf(char *config_file);
+int load_config(const char *fname);
+int check_config(struct config_entry *config);
Index: usr.sbin/bhyve/config.c
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/config.c
@@ -0,0 +1,157 @@
+/*-
+ * Copyright (c) 2015 Marcelo Araujo <araujo@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/types.h>
+#include <err.h>
+#include <errno.h>
+#include <sysexits.h>
+#include <string.h>
+#include <stdio.h>
+#include <string.h>
+#include <ucl.h>
+#include <unistd.h>
+
+#include "config.h"
+
+struct config_entry cinit = {
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+/*
+ * Check if the config file exist.
+ */
+int
+load_config(const char *fname)
+{
+ FILE *file;
+ if ((file = fopen(fname, "r"))) {
+ fclose(file);
+ return 0;
+ }
+
+ errx(EX_USAGE, "Config file does not exist: %s", fname);
+ return 1;
+}
+
+/*
+ * Check if the basic variables are setting in
+ * the config file.
+ */
+int
+check_config(struct config_entry *config)
+{
+ if (!config->vmname)
+ errx(EX_USAGE, "name not defined");
+ else if (!config->memsize)
+ errx(EX_USAGE, "memory not defined");
+ else if (!config->vcpus)
+ errx(EX_USAGE, "vcpus not defined");
+ else if (!config->bootdisk)
+ errx(EX_USAGE, "no boot disk found");
+ else if (!config->iface)
+ errx(EX_USAGE, "iface not defined");
+ else if (!config->console)
+ errx(EX_USAGE, "console not defined");
+
+ return (0);
+}
+
+/*
+ * Parse the config file.
+ */
+struct config_entry
+parse_conf(char *config_file)
+{
+ struct config_entry *c = NULL;
+ const char *config = config_file;
+ struct ucl_parser *p = NULL;
+ ucl_object_t *obj = NULL;
+ const ucl_object_t *cur;
+ ucl_object_iter_t it = NULL;
+ const char *key, *value;
+
+ if (load_config(config) == 1) {
+ errx(EXIT_FAILURE, "No config file found: %s", config);
+ exit (1);
+ }
+
+ p = ucl_parser_new(0);
+ if (p == NULL)
+ errx(1, "Cant allocate p");
+
+ if (!ucl_parser_add_file(p, config)) {
+ if (errno != ENOENT)
+ errx(EXIT_FAILURE, "No config file found "
+ "file %s: %s", config, ucl_parser_get_error(p));
+ ucl_parser_free(p);
+ }
+
+ obj = ucl_parser_get_object(p);
+ if (obj->type != UCL_OBJECT)
+ warnx("Invalid configuration format.\n");
+
+ c = malloc(sizeof(struct config_entry));
+ c = &cinit;
+ while ((cur = ucl_iterate_object(obj, &it, true))) {
+ key = ucl_object_key(cur);
+ value = ucl_object_tostring_forced(cur);
+ if (strcasecmp(key, "name") == 0)
+ c->vmname = strdup(value);
+ else if (strcasecmp(key, "memory") == 0)
+ c->memsize = strdup(value);
+ else if (strcasecmp(key, "vcpus") == 0)
+ c->vcpus = atoi(strdup(value));
+ else if (strcasecmp(key, "bootdisk") == 0)
+ c->bootdisk = strdup(value);
+ else if (strcasecmp(key, "iface") == 0)
+ c->iface = strdup(value);
+ else if (strcasecmp(key, "console") == 0)
+ c->console = strdup(value);
+ else if (strcasecmp(key, "disk") == 0)
+ c->vdisk = strdup(value);
+ else if (strcasecmp(key, "isofile") == 0)
+ c->isofile = strdup(value);
+ }
+
+ check_config(c);
+
+ if (p != NULL)
+ ucl_parser_free(p);
+ if (obj != NULL)
+ ucl_object_unref(obj);
+
+ return *c;
+}
Index: usr.sbin/bhyveload/Makefile
===================================================================
--- usr.sbin/bhyveload/Makefile
+++ usr.sbin/bhyveload/Makefile
@@ -1,13 +1,18 @@
# $FreeBSD$
PROG= bhyveload
-SRCS= bhyveload.c
MAN= bhyveload.8
-LIBADD= vmmapi
+SRCS= bhyveload.c \
+ ${.CURDIR}/../bhyve/config.c
+
+LIBADD= vmmapi ucl
WARNS?= 3
+CFLAGS+=-g
CFLAGS+=-I${.CURDIR}/../../sys/boot/userboot
+CFLAGS+=-I${.CURDIR}/../bhyve
+CFLAGS+=-I${.CURDIR}/../../contrib/libucl/include
.include <bsd.prog.mk>
Index: usr.sbin/bhyveload/bhyveload.8
===================================================================
--- usr.sbin/bhyveload/bhyveload.8
+++ usr.sbin/bhyveload/bhyveload.8
@@ -41,6 +41,8 @@
.Op Fl h Ar host-path
.Op Fl m Ar mem-size
.Ar vmname
+.Nm
+.Op Fl f Ar guest.conf
.Sh DESCRIPTION
.Nm
is used to load a
@@ -111,6 +113,11 @@
The default value of
.Ar mem-size
is 256M.
+.It Fl f Ar guest.conf
+The
+.Ar guest.conf
+is the configuration file that contain all parameters
+necessary to load the guest.
.El
.Sh EXAMPLES
To create a virtual machine named
@@ -132,6 +139,10 @@
.Pa /dev/nmdm1B
.Pp
.Dl "bhyveload -m 256MB -h /usr/images/test -c /dev/nmdm1B test-vm"
+.Pp
+To create a virtual machine using a configuration file:
+.Pp
+.Dl "bhyveload -f guest.conf"
.Sh SEE ALSO
.Xr bhyve 4 ,
.Xr nmdm 4 ,
Index: usr.sbin/bhyveload/bhyveload.c
===================================================================
--- usr.sbin/bhyveload/bhyveload.c
+++ usr.sbin/bhyveload/bhyveload.c
@@ -82,6 +82,8 @@
#include <vmmapi.h>
+#include <config.h>
+
#include "userboot.h"
#define MB (1024 * 1024UL)
@@ -643,7 +645,7 @@
void (*func)(struct loader_callbacks *, void *, int, int);
uint64_t mem_size;
int opt, error, need_reinit;
-
+ struct config_entry config;
progname = basename(argv[0]);
mem_size = 256 * MB;
@@ -651,28 +653,45 @@
consin_fd = STDIN_FILENO;
consout_fd = STDOUT_FILENO;
- while ((opt = getopt(argc, argv, "c:d:e:h:m:")) != -1) {
+ while ((opt = getopt(argc, argv, "c:d:e:h:m:f:")) != -1) {
switch (opt) {
case 'c':
error = altcons_open(optarg);
if (error != 0)
errx(EX_USAGE, "Could not open '%s'", optarg);
break;
-
case 'd':
error = disk_open(optarg);
if (error != 0)
errx(EX_USAGE, "Could not open '%s'", optarg);
break;
-
case 'e':
addenv(optarg);
break;
-
+ case 'f':
+ if (load_config(optarg) == 0) {
+ config = parse_conf(optarg);
+ error = altcons_open(config.console);
+ if (error != 0)
+ errx(EX_USAGE, "Could not open console");
+ if (config.isofile)
+ error = disk_open(config.isofile);
+ else
+ error = disk_open(config.bootdisk);
+ if (error != 0 )
+ errx(EX_USAGE, "Could not open disk");
+ error = vm_parse_memsize(config.memsize, &mem_size);
+ if (error != 0)
+ errx(EX_USAGE, "Invalid memsize");
+ vmname = config.vmname;
+ } else {
+ errx(EX_USAGE, "Error to parse config file: %s", optarg);
+ exit (1);
+ }
+ break;
case 'h':
host_base = optarg;
break;
-
case 'm':
error = vm_parse_memsize(optarg, &mem_size);
if (error != 0)
@@ -686,10 +705,8 @@
argc -= optind;
argv += optind;
- if (argc != 1)
- usage();
-
- vmname = argv[0];
+ if (!vmname)
+ vmname = argv[0];
need_reinit = 0;
error = vm_create(vmname);

File Metadata

Mime Type
text/plain
Expires
Wed, Aug 5, 4:17 AM (21 h, 25 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35993163
Default Alt Text
D2448.id5203.diff (13 KB)

Event Timeline