I'm sorry, I completely forgot the virCommandFree calls: diff --git a/src/jailhouse/jailhouse_driver.c b/src/jailhouse/jailhouse_driver.c index 21acbba..9f1ed70 100644 --- a/src/jailhouse/jailhouse_driver.c +++ b/src/jailhouse/jailhouse_driver.c @@ -201,6 +201,7 @@ parseListOutput(virConnectPtr conn, struct jailhouse_cell **parsedOutput) i++; // skip \n } VIR_FREE(output); + virCommandFree(cmd); return count; error: for (i = 0; i < count; i++) { @@ -211,6 +212,7 @@ parseListOutput(virConnectPtr conn, struct jailhouse_cell **parsedOutput) *parsedOutput = NULL; VIR_FREE(output); output = NULL; + virCommandFree(cmd); return -1; } @@ -323,17 +325,16 @@ jailhouseConnectOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED virReportError(VIR_ERR_INTERNAL_ERROR, _("Executing '%s --version' failed."), conn->uri->path); - VIR_FREE(output); - return VIR_DRV_OPEN_ERROR; + goto error; } if (STRNEQLEN(JAILHOUSEVERSIONOUTPUT, output, strlen(JAILHOUSEVERSIONOUTPUT))) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s doesn't seem to be a correct Jailhouse binary."), conn->uri->path); - VIR_FREE(output); - return VIR_DRV_OPEN_ERROR; + goto error; } VIR_FREE(output); + virCommandFree(cmd); struct jailhouse_driver *driver; if (VIR_ALLOC(driver)) return VIR_DRV_OPEN_ERROR; @@ -342,6 +343,10 @@ jailhouseConnectOpen(virConnectPtr conn, virConnectAuthPtr auth ATTRIBUTE_UNUSED driver->lastQueryCellsCount = 0; conn->privateData = driver; return VIR_DRV_OPEN_SUCCESS; + error: + VIR_FREE(output); + virCommandFree(cmd); + return VIR_DRV_OPEN_ERROR; } static int @@ -493,6 +498,7 @@ jailhouseDomainShutdown(virDomainPtr domain) virCommandAddArg(cmd, buf); virCommandAddEnvPassCommon(cmd); int resultcode = virCommandRun(cmd, NULL); + virCommandFree(cmd); if (resultcode < 0) return -1; return 0; @@ -513,6 +519,7 @@ jailhouseDomainDestroy(virDomainPtr domain) virCommandAddArg(cmd, buf); virCommandAddEnvPassCommon(cmd); int resultcode = virCommandRun(cmd, NULL); + virCommandFree(cmd); if (resultcode < 0) return -1; return 0; @@ -529,6 +536,7 @@ jailhouseDomainCreate(virDomainPtr domain) virCommandAddArg(cmd, buf); virCommandAddEnvPassCommon(cmd); int resultcode = virCommandRun(cmd, NULL); + virCommandFree(cmd); if (resultcode < 0) return -1; return 0; On 11/10/2015 01:17 PM, Christian Loehle wrote: > >From README: > The jailhouse hypervisor driver for the libvirt project aims to provide > rudimentary support for managing jailhouse with the libvirt library. The > main advantage of this is the possibility to use virt-manager as a GUI > to manage Jailhouse cells. Thus the driver is mainly built around the > API calls that virt-manager uses and needs. > Due to the concept of Jailhouse a lot of libvirt functions can't be > realized, so this driver isn't as full-featured as upstream drivers of > the libvirt project. > Currently the driver relies on the Jailhouse binary, which has to be > passed when connecting a libvirt client to it(e.g. virt-manager -c > jailhouse:///path/to/jailhouse/tools/jailhouse). This has the advantage > that remote support can be easily done by not passing the original > Jailhouse binary, but an executable that redirects its parameters > through ssh to the real Jailhouse binary and outputs that output. Be > aware though that the driver doesn't store any information about cells, > so most API calls use "jailhouse cell list" every time they're called to > get the current state. > > I would like to get Jailhouse support upstream, any feedback is greatly > appreciated. > -- > Christian Loehle > > > diff --git a/configure.ac b/configure.ac > index f481c50..8b68828 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -563,6 +563,10 @@ AC_ARG_WITH([hyperv], > [AS_HELP_STRING([--with-hyperv], > [add Hyper-V support @<:@default=check@:>@])]) > m4_divert_text([DEFAULTS], [with_hyperv=check]) > +AC_ARG_WITH([jailhouse], > + [AS_HELP_STRING([--with-jailhouse], > + [add Jailhouse support @<:@default=yes@:>@])]) > +m4_divert_text([DEFAULTS], [with_jailhouse=yes]) > AC_ARG_WITH([test], > [AS_HELP_STRING([--with-test], > [add test driver support @<:@default=yes@:>@])]) > @@ -722,6 +726,16 @@ AM_CONDITIONAL([WITH_VMWARE], [test "$with_vmware" > = "yes"]) > > > dnl > +dnl Checks for the Jailhouse driver > +dnl > + > +if test "$with_jailhouse" = "yes"; then > + AC_DEFINE_UNQUOTED([WITH_JAILHOUSE], 1, [whether Jailhouse driver > is enabled]) > +fi > +AM_CONDITIONAL([WITH_JAILHOUSE], [test "$with_jailhouse" = "yes"]) > + > + > +dnl > dnl check for XDR > dnl > > @@ -1087,6 +1101,12 @@ dnl > LIBVIRT_DRIVER_CHECK_BHYVE > > dnl > +dnl Checks for Jailhouse driver > +dnl > + > +AM_CONDITIONAL([WITH_JAILHOUSE], [test "$with_jailhouse" = "yes"]) > + > +dnl > dnl check for shell that understands <> redirection without truncation, > dnl needed by src/qemu/qemu_monitor_{text,json}.c. > dnl > @@ -2830,6 +2850,7 @@ AC_MSG_NOTICE([ ESX: $with_esx]) > AC_MSG_NOTICE([ Hyper-V: $with_hyperv]) > LIBVIRT_DRIVER_RESULT_VZ > LIBVIRT_DRIVER_RESULT_BHYVE > +AC_MSG_NOTICE([Jailhouse: $with_jailhouse]) > AC_MSG_NOTICE([ Test: $with_test]) > AC_MSG_NOTICE([ Remote: $with_remote]) > AC_MSG_NOTICE([ Network: $with_network]) > diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h > index f716cb9..c8fe2d3 100644 > --- a/include/libvirt/virterror.h > +++ b/include/libvirt/virterror.h > @@ -127,6 +127,7 @@ typedef enum { > VIR_FROM_POLKIT = 60, /* Error from polkit code */ > VIR_FROM_THREAD = 61, /* Error from thread utils */ > VIR_FROM_ADMIN = 62, /* Error from admin backend */ > + VIR_FROM_JAILHOUSE = 63, /* Error from Jailhouse driver */ > > # ifdef VIR_ENUM_SENTINELS > VIR_ERR_DOMAIN_LAST > diff --git a/po/POTFILES.in b/po/POTFILES.in > index 0cc5b99..2b144bf 100644 > --- a/po/POTFILES.in > +++ b/po/POTFILES.in > @@ -59,6 +59,7 @@ src/hyperv/hyperv_wmi.c > src/interface/interface_backend_netcf.c > src/interface/interface_backend_udev.c > src/internal.h > +src/jailhouse/jailhouse_driver.c > src/libvirt.c > src/libvirt-admin.c > src/libvirt-domain.c > diff --git a/src/Makefile.am b/src/Makefile.am > index 99b4993..10d59de 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -578,6 +578,7 @@ DRIVER_SOURCE_FILES = \ > $(VMWARE_DRIVER_SOURCES) \ > $(XEN_DRIVER_SOURCES) \ > $(XENAPI_DRIVER_SOURCES) \ > + $(JAILHOUSE_DRIVER_SOURCES) \ > $(NULL) > > STATEFUL_DRIVER_SOURCE_FILES = \ > @@ -860,6 +861,11 @@ BHYVE_DRIVER_SOURCES = \ > bhyve/bhyve_utils.h \ > $(NULL) > > +JAILHOUSE_DRIVER_SOURCES = \ > + jailhouse/jailhouse_driver.c \ > + jailhouse/jailhouse_driver.h \ > + $(NULL) > + > NETWORK_DRIVER_SOURCES = \ > network/bridge_driver.h network/bridge_driver.c \ > network/bridge_driver_platform.h \ > @@ -1436,6 +1442,14 @@ libvirt_driver_vz_la_LIBADD = > $(PARALLELS_SDK_LIBS) $(LIBNL_LIBS) > libvirt_driver_vz_la_SOURCES = $(VZ_DRIVER_SOURCES) > endif WITH_VZ > > +if WITH_JAILHOUSE > +noinst_LTLIBRARIES += libvirt_driver_jailhouse.la > +libvirt_la_BUILT_LIBADD += libvirt_driver_jailhouse.la > +libvirt_driver_jailhouse_la_CFLAGS = \ > + -I$(srcdir)/conf $(AM_CFLAGS) > +libvirt_driver_jailhouse_la_SOURCES = $(JAILHOUSE_DRIVER_SOURCES) > +endif WITH_JAILHOUSE > + > if WITH_BHYVE > noinst_LTLIBRARIES += libvirt_driver_bhyve_impl.la > libvirt_driver_bhyve_la_SOURCES = > @@ -1801,6 +1815,7 @@ EXTRA_DIST += \ > $(HYPERV_DRIVER_EXTRA_DIST) \ > $(VZ_DRIVER_SOURCES) \ > $(BHYVE_DRIVER_SOURCES) \ > + $(JAILHOUSE_DRIVER_SOURCES) \ > $(NETWORK_DRIVER_SOURCES) \ > $(INTERFACE_DRIVER_SOURCES) \ > $(STORAGE_DRIVER_SOURCES) \ > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 2edf123..00d17e9 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -121,7 +121,8 @@ VIR_ENUM_IMPL(virDomainVirt, VIR_DOMAIN_VIRT_LAST, > "phyp", > "parallels", > "bhyve", > - "vz") > + "vz", > + "jailhouse") > > VIR_ENUM_IMPL(virDomainOS, VIR_DOMAIN_OSTYPE_LAST, > "hvm", > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index f10b534..27beef0 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -225,6 +225,7 @@ typedef enum { > VIR_DOMAIN_VIRT_PARALLELS, > VIR_DOMAIN_VIRT_BHYVE, > VIR_DOMAIN_VIRT_VZ, > + VIR_DOMAIN_VIRT_JAILHOUSE, > > VIR_DOMAIN_VIRT_LAST > } virDomainVirtType; > diff --git a/src/jailhouse/README b/src/jailhouse/README > new file mode 100644 > index 0000000..564cfbd > --- /dev/null > +++ b/src/jailhouse/README > @@ -0,0 +1,3 @@ > +The jailhouse hypervisor driver for the libvirt project aims to provide > rudimentary support for managing jailhouse with the libvirt library. The > main advantage of this is the possibility to use virt-manager as a GUI > to manage Jailhouse cells. Thus the driver is mainly built around the > API calls that virt-manager uses and needs. > +Due to the concept of Jailhouse a lot of libvirt functions can't be > realized, so this driver isn't as full-featured as upstream drivers of > the libvirt project. > +Currently the driver relies on the Jailhouse binary, which has to be > passed when connecting a libvirt client to it(e.g. virt-manager -c > jailhouse:///path/to/jailhouse/tools/jailhouse). This has the advantage > that remote support can be easily done by not passing the original > Jailhouse binary, but an executable that redirects its parameters > through ssh to the real Jailhouse binary and outputs that output. Be > aware though that the driver doesn't store any information about cells, > so most API calls use "jailhouse cell list" every time they're called to > get the current state. > diff --git a/src/jailhouse/jailhouse_driver.c > b/src/jailhouse/jailhouse_driver.c > new file mode 100644 > index 0000000..21acbba > --- /dev/null > +++ b/src/jailhouse/jailhouse_driver.c > @@ -0,0 +1,614 @@ > +/* > + * jailhouse_driver.c: hypervisor driver for managing Jailhouse cells > + * > + * Copyright (C) 2015 Linutronix GmbH > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library. If not, see > + * <http://www.gnu.org/licenses/>. > + * > + * Author: Christian Loehle > + */ > + > +#include <config.h> > +#include <string.h> > +#include "jailhouse_driver.h" > +#include "datatypes.h" > +#include "virerror.h" > +#include "viralloc.h" > +#include "virlog.h" > +#include "vircommand.h" > +#include "virxml.h" > +#include "configmake.h" > +#include "virfile.h" > +#include "virtypedparam.h" > +#include "virstring.h" > +#include "nodeinfo.h" > + > +#define VIR_FROM_THIS VIR_FROM_JAILHOUSE > + > +#define IDLENGTH 8 > +#define NAMELENGTH 24 > +#define STATELENGTH 16 > +#define CPULENGTH 24 > +#define STATERUNNING 0 > +#define STATERUNNINGSTRING "running " > +#define STATERUNNINGLOCKED 1 > +#define STATERUNNINGLOCKEDSTRING "running/locked " > +#define STATESHUTDOWN 2 > +#define STATESHUTDOWNSTRING "shut down " > +#define STATEFAILED 3 > +#define STATEFAILEDSTRING "failed " > +#define JAILHOUSEVERSIONOUTPUT "Jailhouse management tool" > + > +/* > + * The driver requeries the cells on most calls, it stores the result > of the last query, so it can copy the UUIDs in the new query if the cell > is the same(otherwise it just generates a new one) > + * not preserving the UUID results in a lot of bugs in libvirts clients. > + */ > +struct jailhouse_driver { > + char *binary; > + size_t lastQueryCellsCount; > + struct jailhouse_cell* lastQueryCells; > +}; > + > +/* > + * CPUs are currently unused but this might change > + */ > +struct jailhouse_cell { > + int id; > + char name[NAMELENGTH+1]; > + int state; > + int *assignedCPUs; //Don't use cpumask because remote system might > have different # of cpus > + int assignedCPUsLength; > + int *failedCPUs; > + int failedCPUsLength; > + unsigned char uuid[VIR_UUID_BUFLEN]; > +}; > + > +/* > + * helper function that returns the number as an integer and sets i to > be the first char after the number > + */ > +static int > +charsToInt(char* chars, size_t *i) > +{ > + int result = 0; > + while (chars[*i] != ',' && chars[*i] != '-' && chars[*i] != ' ') { > + result *= 10; > + result += chars[*i] - '0'; > + (*i)++; > + } > + return result; > +} > + > +/* > + * Takes a string in the format of "jailhouse cell list" as input, > + * allocates an int array in which every CPU is explicitly listed and > saves a pointer in cpusptr > + */ > +static size_t > +parseCPUs(char* output, int **cpusptr) > +{ > + size_t i; > + size_t count = 1; > + int number; > + int* cpus; > + if (output[0] == ' ') { > + *cpusptr = NULL; > + return 0; > + } > + for (i = 0; i<CPULENGTH; i++) { > + number = charsToInt(output, &i); > + if (output[i] == ',') { > + count++; > + } else if (output[i] == '-') { > + i++; > + count += charsToInt(output, &i) - number; > + } > + } > + if (VIR_ALLOC_N(cpus, count)) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to allocate CPUs array of size %zu"), count); > + return 0; > + } > + size_t j = 0; > + i = 0; > + while (output[i] != ' ') { > + number = charsToInt(output, &i); > + if (output[i] == ',' || output[i] == ' ') { > + cpus[j++] = number; > + } else if (output[i] == '-') { > + i++; > + int nextNumber = charsToInt(output, &i); > + for (; number <= nextNumber; number++) cpus[j++] = number; > + } > + i++; > + } > + *cpusptr = cpus; > + return count; > +} > + > +/* > + * calls "jailhouse cell list" and parses the output in an array of > jailhouse_cell > + */ > +static size_t > +parseListOutput(virConnectPtr conn, struct jailhouse_cell **parsedOutput) > +{ > + virCommandPtr cmd = virCommandNew(((struct jailhouse_driver > *)conn->privateData)->binary); > + virCommandAddArg(cmd, "cell"); > + virCommandAddArg(cmd, "list"); > + virCommandAddEnvPassCommon(cmd); > + char *output; > + virCommandSetOutputBuffer(cmd, &output); > + size_t count = -1; // Don't count table header line > + size_t i = 0; > + if (virCommandRun(cmd, NULL) < 0) > + goto error; > + while (output[i] != '\0') { > + if (output[i] == '\n') count++; > + i++; > + } > + if (VIR_ALLOC_N(*parsedOutput, count)) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to allocate jailhouse_cell array of size > %zu"), count); > + goto error; > + } > + if (*parsedOutput == NULL) > + goto error; > + i = 0; > + size_t j; > + while (output[i++] != '\n'); // Skip table header line > + for (j = 0; j < count; j++) { > + size_t k; > + for (k = 0; k <= IDLENGTH; k++) // char after number needs to > be NUL for virStrToLong > + if (output[i+k] == ' ') { > + output[i+k] = '\0'; > + break; > + } > + char c = output[i+IDLENGTH]; > + output[i+IDLENGTH] = '\0'; // in case ID is 8 chars long, so > beginning of name won't get parsed > + if (virStrToLong_i(output+i, NULL, 0, &(*parsedOutput)[j].id)) > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to parse id to long: %s"), output+i); > + output[i+IDLENGTH] = c; > + i += IDLENGTH; > + if (virStrncpy((*parsedOutput)[j].name, output+i, NAMELENGTH, > NAMELENGTH+1) == NULL) > + // should never happen > + goto error; > + (*parsedOutput)[j].name[NAMELENGTH] = '\0'; > + for (k = 0; k < NAMELENGTH; k++) > + if ((*parsedOutput)[j].name[k] == ' ') > + break; > + (*parsedOutput)[j].name[k] = '\0'; > + i += NAMELENGTH; > + if (STREQLEN(output+i, STATERUNNINGSTRING, STATELENGTH)) > (*parsedOutput)[j].state = STATERUNNING; > + else if (STREQLEN(output+i, STATESHUTDOWNSTRING, STATELENGTH)) > (*parsedOutput)[j].state = STATESHUTDOWN; > + else if (STREQLEN(output+i, STATEFAILEDSTRING, STATELENGTH)) > (*parsedOutput)[j].state = STATEFAILED; > + else if (STREQLEN(output+i, STATERUNNINGLOCKEDSTRING, > STATELENGTH)) (*parsedOutput)[j].state = STATERUNNINGLOCKED; > + i += STATELENGTH; > + (*parsedOutput)[j].assignedCPUsLength = parseCPUs(output+i, > &((*parsedOutput)[j].assignedCPUs)); > + i += CPULENGTH; > + (*parsedOutput)[j].failedCPUsLength = parseCPUs(output+i, > &((*parsedOutput)[j].failedCPUs)); > + i += CPULENGTH; > + i++; // skip \n > + } > + VIR_FREE(output); > + return count; > + error: > + for (i = 0; i < count; i++) { > + VIR_FREE((*parsedOutput)[i].assignedCPUs); > + VIR_FREE((*parsedOutput)[i].failedCPUs); > + } > + VIR_FREE(*parsedOutput); > + *parsedOutput = NULL; > + VIR_FREE(output); > + output = NULL; > + return -1; > +} > + > +/* > + * Returns the libvirts equivalent of the cell state passed to it > + */ > +static virDomainState > +cellToVirDomainState(struct jailhouse_cell *cell) > +{ > + switch (cell->state) { > + case STATERUNNING: return VIR_DOMAIN_RUNNING; > + case STATERUNNINGLOCKED: return VIR_DOMAIN_RUNNING; > + case STATESHUTDOWN: return VIR_DOMAIN_SHUTOFF; > + case STATEFAILED: return VIR_DOMAIN_CRASHED; > + default: return VIR_DOMAIN_NOSTATE; > + } > +} > + > +/* > + * Returns a new virDomainPtr filled with the data of the jailhouse_cell > + */ > +static virDomainPtr > +cellToVirDomainPtr(virConnectPtr conn, struct jailhouse_cell *cell) > +{ > + virDomainPtr dom = virGetDomain(conn, cell->name, cell->uuid); > + dom->id = cell->id; > + return dom; > +} > + > +/* > + * Check cells for cell and copies UUID if found, otherwise generates > a new one, this is to preserve UUID in libvirt > + */ > +static void setUUID(struct jailhouse_cell *cells, size_t count, struct > jailhouse_cell* cell) { > + size_t i; > + for (i = 0; i < count; i++) { > + if (strncmp(cells[i].name, cell->name, NAMELENGTH+1)) > + continue; > + memcpy(cell->uuid, cells[i].uuid, VIR_UUID_BUFLEN); > + return; > + } > + virUUIDGenerate(cell->uuid); > +} > + > +/* > + * Frees the old list of cells, gets the new one and preserves UUID if > cells were present in the old > + */ > +static void > +getCurrentCellList(virConnectPtr conn) > +{ > + size_t lastCount = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCellsCount; > + struct jailhouse_cell *lastCells = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCells; > + struct jailhouse_cell *cells = NULL; > + size_t i; > + size_t count = parseListOutput(conn, &cells); > + for (i = 0; i < count; i++) > + setUUID(lastCells, lastCount, cells+i); > + for (i = 0; i < lastCount; i++) { > + VIR_FREE(lastCells[i].assignedCPUs); > + VIR_FREE(lastCells[i].failedCPUs); > + } > + VIR_FREE(lastCells); > + ((struct jailhouse_driver *)conn->privateData)->lastQueryCells = cells; > + ((struct jailhouse_driver *)conn->privateData)->lastQueryCellsCount > = count; > +} > + > +/* > + * Converts libvirts virDomainPtr to the internal jailhouse_cell by > parsing the "jailhouse cell list" output > + * and looking up the name of the virDomainPtr, returns NULL if cell > is no longer present > + */ > +static struct jailhouse_cell * > +virDomainPtrToCell(virDomainPtr dom) > +{ > + getCurrentCellList(dom->conn); > + size_t cellsCount = ((struct jailhouse_driver > *)dom->conn->privateData)->lastQueryCellsCount; > + struct jailhouse_cell *cells = ((struct jailhouse_driver > *)dom->conn->privateData)->lastQueryCells; > + size_t i; > + for (i = 0; i < cellsCount; i++) > + if (dom->id == cells[i].id) > + return cells+i; > + return NULL; > +} > + > +static virDrvOpenStatus > +jailhouseConnectOpen(virConnectPtr conn, virConnectAuthPtr auth > ATTRIBUTE_UNUSED, unsigned int flags) > +{ > + virCheckFlags(0, VIR_DRV_OPEN_ERROR); > + if (conn->uri->scheme == NULL || > + STRNEQ(conn->uri->scheme, "jailhouse")) > + return VIR_DRV_OPEN_DECLINED; > + char* binary; > + if (conn->uri->path == NULL) { > + if (VIR_STRDUP(binary, "jailhouse") != 1) > + return VIR_DRV_OPEN_ERROR; > + } else { > + if (!virFileIsExecutable(conn->uri->path)) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Path '%s', is not a valid executable file."), > + conn->uri->path); > + return VIR_DRV_OPEN_ERROR; > + } > + if (VIR_STRDUP(binary, conn->uri->path) != 1) > + return VIR_DRV_OPEN_ERROR; > + } > + virCommandPtr cmd = virCommandNew(binary); > + virCommandAddArg(cmd, "--version"); > + virCommandAddEnvPassCommon(cmd); > + char *output; > + virCommandSetOutputBuffer(cmd, &output); > + if (virCommandRun(cmd, NULL) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Executing '%s --version' failed."), > + conn->uri->path); > + VIR_FREE(output); > + return VIR_DRV_OPEN_ERROR; > + } > + if (STRNEQLEN(JAILHOUSEVERSIONOUTPUT, output, > strlen(JAILHOUSEVERSIONOUTPUT))) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("%s doesn't seem to be a correct Jailhouse > binary."), > + conn->uri->path); > + VIR_FREE(output); > + return VIR_DRV_OPEN_ERROR; > + } > + VIR_FREE(output); > + struct jailhouse_driver *driver; > + if (VIR_ALLOC(driver)) > + return VIR_DRV_OPEN_ERROR; > + driver->binary = binary; > + driver->lastQueryCells = NULL; > + driver->lastQueryCellsCount = 0; > + conn->privateData = driver; > + return VIR_DRV_OPEN_SUCCESS; > +} > + > +static int > +jailhouseConnectClose(virConnectPtr conn) > +{ > + size_t i; > + size_t cellsCount = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCellsCount; > + struct jailhouse_cell *cells = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCells; > + for (i = 0; i < cellsCount; i++) { > + VIR_FREE(cells[i].assignedCPUs); > + VIR_FREE(cells[i].failedCPUs); > + } > + VIR_FREE(cells); > + VIR_FREE(((struct jailhouse_driver *)conn->privateData)->binary); > + VIR_FREE(conn->privateData); > + conn->privateData = NULL; > + return 0; > +} > + > +static int > +jailhouseConnectNumOfDomains(virConnectPtr conn) > +{ > + getCurrentCellList(conn); > + return ((struct jailhouse_driver > *)conn->privateData)->lastQueryCellsCount; > +} > + > +static int > +jailhouseConnectListDomains(virConnectPtr conn, int * ids, int maxids) > +{ > + getCurrentCellList(conn); > + size_t cellsCount = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCellsCount; > + struct jailhouse_cell *cells = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCells; > + size_t i; > + for (i = 0; i < maxids && i < cellsCount; i++) > + ids[i] = cells[i].id; > + return i; > +} > + > +static int > +jailhouseConnectListAllDomains(virConnectPtr conn, virDomainPtr ** > domains, unsigned int flags) > +{ > + virCheckFlags(VIR_CONNECT_LIST_DOMAINS_ACTIVE, 0); > + getCurrentCellList(conn); > + size_t cellsCount = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCellsCount; > + struct jailhouse_cell *cells = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCells; > + if (cellsCount == -1) > + goto error; > + if (VIR_ALLOC_N(*domains, cellsCount+1)) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("Failed to allocate virDomainPtr array of size > %zu"), cellsCount+1); > + goto error; > + } > + size_t i; > + for (i = 0; i < cellsCount; i++) > + (*domains)[i] = cellToVirDomainPtr(conn, cells+i); > + (*domains)[cellsCount] = NULL; > + return cellsCount; > + error: > + *domains = NULL; > + return -1; > +} > + > +static virDomainPtr > +jailhouseDomainLookupByID(virConnectPtr conn, int id) > +{ > + getCurrentCellList(conn); > + size_t cellsCount = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCellsCount; > + if (cellsCount == -1) > + return NULL; > + struct jailhouse_cell *cells = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCells; > + size_t i; > + for (i = 0; i < cellsCount; i++) > + if (cells[i].id == id) > + return cellToVirDomainPtr(conn, cells+i); > + virReportError(VIR_ERR_NO_DOMAIN, NULL); > + return NULL; > +} > + > +static virDomainPtr > +jailhouseDomainLookupByName(virConnectPtr conn, const char *lookupName) > +{ > + getCurrentCellList(conn); > + size_t cellsCount = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCellsCount; > + if (cellsCount == -1) > + return NULL; > + struct jailhouse_cell *cells = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCells; > + size_t i; > + for (i = 0; i < cellsCount; i++) > + if (STREQ(cells[i].name, lookupName)) > + return cellToVirDomainPtr(conn, cells+i); > + virReportError(VIR_ERR_NO_DOMAIN, NULL); > + return NULL; > +} > + > +static virDomainPtr > +jailhouseDomainLookupByUUID(virConnectPtr conn, const unsigned char * uuid) > +{ > + getCurrentCellList(conn); > + size_t cellsCount = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCellsCount; > + if (cellsCount == -1) > + return NULL; > + struct jailhouse_cell *cells = ((struct jailhouse_driver > *)conn->privateData)->lastQueryCells; > + size_t i; > + for (i = 0; i < cellsCount; i++) > + if (memcmp(cells[i].uuid, (const char*)uuid, VIR_UUID_BUFLEN) == 0) > + return cellToVirDomainPtr(conn, cells+i); > + virReportError(VIR_ERR_NO_DOMAIN, NULL); > + return NULL; > +} > + > +/* > + * There currently is no straightforward way for the driver to > retrieve those, > + * so maxMem, memory and cpuTime have dummy values > + */ > +static int > +jailhouseDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) > +{ > + struct jailhouse_cell *cell = virDomainPtrToCell(domain); > + if (cell == NULL) > + return -1; > + info->state = cellToVirDomainState(cell); > + info->maxMem = 1; > + info->memory = 1; > + info->nrVirtCpu = cell->assignedCPUsLength; > + info->cpuTime = 1; > + return 0; > +} > + > +static int > +jailhouseDomainGetState(virDomainPtr domain, int *state, > + int *reason ATTRIBUTE_UNUSED, unsigned int flags) > +{ > + virCheckFlags(0, 0); > + struct jailhouse_cell *cell = virDomainPtrToCell(domain); > + if (cell == NULL) > + return -1; > + *state = cellToVirDomainState(cell); > + return 0; > +} > + > +static int > +jailhouseDomainShutdown(virDomainPtr domain) > +{ > + virCommandPtr cmd = virCommandNew(((struct jailhouse_driver > *)domain->conn->privateData)->binary); > + virCommandAddArg(cmd, "cell"); > + virCommandAddArg(cmd, "shutdown"); > + char buf[IDLENGTH+1]; > + snprintf(buf, IDLENGTH+1, "%d", domain->id); > + virCommandAddArg(cmd, buf); > + virCommandAddEnvPassCommon(cmd); > + int resultcode = virCommandRun(cmd, NULL); > + if (resultcode < 0) > + return -1; > + return 0; > +} > + > +/* > + * CAREFUL, this is the Jailhouse destroy, not the libvirt destroy, > cell will be deleted and would need to be created and loaded again. > + * This is implemented anyway, so libvirt clients have an option to > use jailhouse destroy too. > + */ > +static int > +jailhouseDomainDestroy(virDomainPtr domain) > +{ > + virCommandPtr cmd = virCommandNew(((struct jailhouse_driver > *)domain->conn->privateData)->binary); > + virCommandAddArg(cmd, "cell"); > + virCommandAddArg(cmd, "destroy"); > + char buf[IDLENGTH+1]; > + snprintf(buf, IDLENGTH+1, "%d", domain->id); > + virCommandAddArg(cmd, buf); > + virCommandAddEnvPassCommon(cmd); > + int resultcode = virCommandRun(cmd, NULL); > + if (resultcode < 0) > + return -1; > + return 0; > +} > + > +static int > +jailhouseDomainCreate(virDomainPtr domain) > +{ > + virCommandPtr cmd = virCommandNew(((struct jailhouse_driver > *)domain->conn->privateData)->binary); > + virCommandAddArg(cmd, "cell"); > + virCommandAddArg(cmd, "start"); > + char buf[IDLENGTH+1]; > + snprintf(buf, IDLENGTH+1, "%d", domain->id); > + virCommandAddArg(cmd, buf); > + virCommandAddEnvPassCommon(cmd); > + int resultcode = virCommandRun(cmd, NULL); > + if (resultcode < 0) > + return -1; > + return 0; > +} > + > +/* > + * There currently is no reason why it shouldn't be > + */ > +static int > +jailhouseConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) > +{ > + return 1; > +} > + > +static int > +jailhouseNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, > virNodeInfoPtr info) > +{ > + return nodeGetInfo(NULL, info); > +} > + > +/* > + * Returns a dummy capabilities XML for virt-manager > + */ > +static char * > +jailhouseConnectGetCapabilities(virConnectPtr conn ATTRIBUTE_UNUSED) > +{ > + char* caps; > + if (VIR_STRDUP(caps, "<capabilities></capabilities>") != 1) > + return NULL; > + return caps; > +} > + > +/* > + * Returns a dummy XML for virt-manager > + */ > +static char * > +jailhouseDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) > +{ > + virCheckFlags(0, NULL); > + char buf[200]; > + char uuid[VIR_UUID_STRING_BUFLEN]; > + virDomainGetUUIDString(domain, uuid); > + snprintf(buf, 200, "<domain type =\"jailhouse\">\n\ > + <name>%s</name>\n\ > + <uuid>%s</uuid>\n\ > + </domain>", domain->name, uuid); > + char* result; > + if (VIR_STRDUP(result, buf) != 1) > + return NULL; > + return result; > +} > + > +static virHypervisorDriver jailhouseHypervisorDriver = { > + .name = "jailhouse", > + .connectOpen = jailhouseConnectOpen, /* 1.2.22 */ > + .connectClose = jailhouseConnectClose, /* 1.2.22 */ > + .connectGetCapabilities = jailhouseConnectGetCapabilities, /* 1.2.22 */ > + .connectNumOfDomains = jailhouseConnectNumOfDomains, /* 1.2.22 */ > + .connectListDomains = jailhouseConnectListDomains, /* 1.2.22 */ > + .connectIsAlive = jailhouseConnectIsAlive, /* 1.2.22 */ > + .connectListAllDomains = jailhouseConnectListAllDomains, /* 1.2.22 */ > + .domainLookupByID = jailhouseDomainLookupByID, /* 1.2.22 */ > + .domainLookupByName = jailhouseDomainLookupByName, /* 1.2.22 */ > + .domainLookupByUUID = jailhouseDomainLookupByUUID, /* 1.2.22 */ > + .domainGetInfo = jailhouseDomainGetInfo, /* 1.2.22 */ > + .domainGetState = jailhouseDomainGetState, /* 1.2.22 */ > + .domainGetXMLDesc = jailhouseDomainGetXMLDesc, /* 1.2.22 */ > + .domainShutdown = jailhouseDomainShutdown, /* 1.2.22 */ > + .domainDestroy = jailhouseDomainDestroy, /* 1.2.22 */ > + .domainCreate = jailhouseDomainCreate, /* 1.2.22 */ > + .nodeGetInfo = jailhouseNodeGetInfo /* 1.2.22 */ > +}; > + > +static virConnectDriver jailhouseConnectDriver = { > + .hypervisorDriver = &jailhouseHypervisorDriver, > +}; > + > +int > +jailhouseRegister(void) > +{ > + return virRegisterConnectDriver(&jailhouseConnectDriver, > + false); > +} > diff --git a/src/jailhouse/jailhouse_driver.h > b/src/jailhouse/jailhouse_driver.h > new file mode 100644 > index 0000000..47c17e7 > --- /dev/null > +++ b/src/jailhouse/jailhouse_driver.h > @@ -0,0 +1,28 @@ > +/* > + * jailhouse_driver.h: hypervisor driver for managing Jailhouse cells > + * > + * Copyright (C) 2015 Linutronix GmbH > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library. If not, see > + * <http://www.gnu.org/licenses/>. > + * > + * Author: Christian Loehle > + */ > + > +#ifndef JAILHOUSE_DRIVER_H > +# define JAILHOUSE_DRIVER_H > + > +int jailhouseRegister(void); > + > +#endif > diff --git a/src/libvirt.c b/src/libvirt.c > index 25a0040..7626353 100644 > --- a/src/libvirt.c > +++ b/src/libvirt.c > @@ -98,6 +98,9 @@ > #ifdef WITH_BHYVE > # include "bhyve/bhyve_driver.h" > #endif > +#ifdef WITH_JAILHOUSE > +# include "jailhouse/jailhouse_driver.h" > +#endif > > #define VIR_FROM_THIS VIR_FROM_NONE > > @@ -437,12 +440,17 @@ virGlobalInit(void) > if (vzRegister() == -1) > goto error; > # endif > +#ifdef WITH_JAILHOUSE > + if (jailhouseRegister() == -1) > + goto error; > +#endif > #endif > #ifdef WITH_REMOTE > if (remoteRegister() == -1) > goto error; > #endif > > + > return; > > error: > @@ -1167,6 +1175,9 @@ do_open(const char *name, > #ifndef WITH_VZ > STRCASEEQ(ret->uri->scheme, "parallels") || > #endif > +#ifndef WITH_JAILHOUSE > + STRCASEEQ(ret->uri->scheme, "jailhouse") || > +#endif > false)) { > virReportErrorHelper(VIR_FROM_NONE, VIR_ERR_CONFIG_UNSUPPORTED, > __FILE__, __FUNCTION__, __LINE__, > diff --git a/src/util/virerror.c b/src/util/virerror.c > index 6dc05f4..0d480c0 100644 > --- a/src/util/virerror.c > +++ b/src/util/virerror.c > @@ -134,6 +134,7 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST, > "Polkit", /* 60 */ > "Thread jobs", > "Admin Interface", > + "Jailhouse Driver", > ) > > > > -- > libvir-list mailing list > libvir-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list