The suggestions in your review should all be implemented now. -- Christian Loehle diff --git a/configure.ac b/configure.ac index 4b7c9ed..02db58e 100644 --- a/configure.ac +++ b/configure.ac @@ -1087,6 +1087,12 @@ dnl LIBVIRT_DRIVER_CHECK_BHYVE dnl +dnl Checks for Jailhouse driver +dnl + +LIBVIRT_DRIVER_CHECK_JAILHOUSE + +dnl dnl check for shell that understands <> redirection without truncation, dnl needed by src/qemu/qemu_monitor_{text,json}.c. dnl @@ -2830,6 +2836,7 @@ AC_MSG_NOTICE([ ESX: $with_esx]) AC_MSG_NOTICE([ Hyper-V: $with_hyperv]) LIBVIRT_DRIVER_RESULT_VZ LIBVIRT_DRIVER_RESULT_BHYVE +LIBVIRT_DRIVER_RESULT_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/libvirt-jailhousev2.patch b/libvirt-jailhousev2.patch new file mode 100644 index 0000000..e69de29 diff --git a/m4/virt-driver-jailhouse.m4 b/m4/virt-driver-jailhouse.m4 new file mode 100644 index 0000000..65d53f2 --- /dev/null +++ b/m4/virt-driver-jailhouse.m4 @@ -0,0 +1,31 @@ +dnl The Jailhouse driver +dnl +dnl Copyright (C) 2005-2015 Red Hat, Inc. +dnl +dnl This library is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Lesser General Public +dnl License as published by the Free Software Foundation; either +dnl version 2.1 of the License, or (at your option) any later version. +dnl +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Lesser General Public License for more details. +dnl +dnl You should have received a copy of the GNU Lesser General Public +dnl License along with this library. If not, see +dnl <http://www.gnu.org/licenses/>. +dnl + +AC_DEFUN([LIBVIRT_DRIVER_CHECK_JAILHOUSE],[ + AC_ARG_WITH([jailhouse], + [AS_HELP_STRING([--with-jailhouse], + [add Jailhouse support @<:@default=yes@:>@])]) + m4_divert_text([DEFAULTS], [with_jailhouse=yes]) + + AM_CONDITIONAL([WITH_JAILHOUSE], [test "$with_jailhouse" = "yes"]) +]) + +AC_DEFUN([LIBVIRT_DRIVER_RESULT_JAILHOUSE],[ + AC_MSG_NOTICE([Jailhouse: $with_jailhouse]) +]) 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 616bf80..c97bfab 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 8d43ee6..1493d73 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..02ba87d --- /dev/null +++ b/src/jailhouse/README @@ -0,0 +1,14 @@ +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 in $PATH +or passed when connecting a libvirt client to it +(e.g. virt-manager -c jailhouse:///path/to/jailhouse/tools/jailhouse). +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..0154b91 --- /dev/null +++ b/src/jailhouse/jailhouse_driver.c @@ -0,0 +1,558 @@ +/* + * virJailhouseDriver.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" +#include "capabilities.h" +#include "domain_conf.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" + +struct virJailhouseCell { + int id; + char name[NAMELENGTH+1]; + int state; + virBitmapPtr assignedCPUs; + virBitmapPtr failedCPUs; /* currently unused */ + unsigned char uuid[VIR_UUID_BUFLEN]; +}; +typedef struct virJailhouseCell virJailhouseCell; +typedef virJailhouseCell *virJailhouseCellPtr; + +/* + * Because virCommandRunRegex Callback gets called every line + */ +struct virJailhouseCellCallbackData { + size_t ncells; + virJailhouseCellPtr cells; +}; +typedef struct virJailhouseCellCallbackData virJailhouseCellCallbackData; +typedef virJailhouseCellCallbackData *virJailhouseCellCallbackDataPtr; + +/* + * 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 virJailhouseDriver { + char *binary; + size_t lastQueryCellsCount; + virJailhouseCellPtr lastQueryCells; +}; +typedef struct virJailhouseDriver virJailhouseDriver; +typedef virJailhouseDriver *virJailhouseDriverPtr; + +static int virJailhouseParseListOutputCallback(char **const groups, void *data) +{ + virJailhouseCellCallbackDataPtr celldata = (virJailhouseCellCallbackDataPtr) data; + virJailhouseCellPtr cells = celldata->cells; + size_t count = celldata->ncells; + char* endptr = groups[0] + strlen(groups[0]) - 1; + char* state = groups[2]; + if (cells == NULL) { + if (VIR_ALLOC(cells)) + return -1; + } + else if (VIR_EXPAND_N(cells, count, 1)) + return -1; + celldata->ncells++; + if (virStrToLong_i(groups[0], &endptr, 0, &cells[count].id)) + return -1; + if (!virStrcpy(cells[count].name, groups[1], NAMELENGTH+1)) + return -1; + if (STREQLEN(state, STATERUNNINGSTRING, STATELENGTH)) + cells[count].state = STATERUNNING; + else if (STREQLEN(state, STATESHUTDOWNSTRING, STATELENGTH)) + cells[count].state = STATESHUTDOWN; + else if (STREQLEN(state, STATERUNNINGLOCKEDSTRING, STATELENGTH)) + cells[count].state = STATERUNNINGLOCKED; + else + cells[count].state = STATEFAILED; + virBitmapParse(groups[3], 0, &cells[count].assignedCPUs, VIR_DOMAIN_CPUMASK_LEN); + virBitmapParse(groups[4], 0, &cells[count].failedCPUs, VIR_DOMAIN_CPUMASK_LEN); + celldata->cells = cells; + return 0; +} + +/* + * calls "jailhouse cell list" and parses the output in an array of virJailhouseCell + * example output: + * ID Name State Assigned CPUs Failed CPUs + * 0 QEMU-VM running 0-3 + */ +static ssize_t +virJailhouseParseListOutput(virConnectPtr conn, virJailhouseCellPtr *parsedCells) +{ + int nvars[] = { 5 }; + virJailhouseCellCallbackData callbackData; + const char *regex[] = { "([0-9]{1,8})\\s*([0-9a-zA-z-]{1,24})\\s*([a-z/ ]{1,16})\\s*([0-9,-]{1,24})?\\s*([0-9,-]{1,24})?\\s*" }; + virCommandPtr cmd = virCommandNew(((virJailhouseDriverPtr)conn->privateData)->binary); + virCommandAddArg(cmd, "cell"); + virCommandAddArg(cmd, "list"); + virCommandAddEnvPassCommon(cmd); + callbackData.cells = NULL; + callbackData.ncells = 0; + if (virCommandRunRegex(cmd, 1, regex, nvars, &virJailhouseParseListOutputCallback, &callbackData, NULL) < 0) { + virCommandFree(cmd); + return -1; + } + virCommandFree(cmd); + *parsedCells = callbackData.cells; + return callbackData.ncells; +} + +/* + * Returns the libvirts equivalent of the cell state passed to it + */ +static virDomainState +virJailhouseCellToState(virJailhouseCellPtr 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 virJailhouseCell + */ +static virDomainPtr +virJailhouseCellToDomainPtr(virConnectPtr conn, virJailhouseCellPtr 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 virJailhouseSetUUID(virJailhouseCellPtr cells, size_t count, virJailhouseCellPtr 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 +virJailhouseGetCurrentCellList(virConnectPtr conn) +{ + virJailhouseDriverPtr driver = (virJailhouseDriverPtr)conn->privateData; + ssize_t count; + size_t i; + size_t lastCount = driver->lastQueryCellsCount; + virJailhouseCellPtr lastCells = driver->lastQueryCells; + virJailhouseCellPtr cells = NULL; + count = virJailhouseParseListOutput(conn, &cells); + if (count == -1) + count = 0; + for (i = 0; i < count; i++) + virJailhouseSetUUID(lastCells, lastCount, cells+i); + for (i = 0; i < lastCount; i++) { + virBitmapFree(lastCells[i].assignedCPUs); + virBitmapFree(lastCells[i].failedCPUs); + } + VIR_FREE(lastCells); + driver->lastQueryCells = cells; + driver->lastQueryCellsCount = count; +} + +/* + * Converts libvirts virDomainPtr to the internal virJailhouseCell by parsing the "jailhouse cell list" output + * and looking up the name of the virDomainPtr, returns NULL if cell is no longer present + */ +static virJailhouseCellPtr +virDomainPtrToCell(virDomainPtr dom) +{ + virJailhouseDriverPtr driver = (virJailhouseDriverPtr)dom->conn->privateData; + size_t cellsCount; + size_t i; + virJailhouseGetCurrentCellList(dom->conn); + cellsCount = driver->lastQueryCellsCount; + virJailhouseCellPtr cells = driver->lastQueryCells; + 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); + char* binary; + char *output; + if (conn->uri->scheme == NULL || + STRNEQ(conn->uri->scheme, "jailhouse")) + return VIR_DRV_OPEN_DECLINED; + 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); + virCommandSetOutputBuffer(cmd, &output); + if (virCommandRun(cmd, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Executing '%s --version' failed."), + conn->uri->path); + 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); + goto error; + } + VIR_FREE(output); + virCommandFree(cmd); + virJailhouseDriverPtr driver; + if (VIR_ALLOC(driver) < 0) + return VIR_DRV_OPEN_ERROR; + driver->binary = binary; + driver->lastQueryCells = NULL; + driver->lastQueryCellsCount = 0; + conn->privateData = driver; + return VIR_DRV_OPEN_SUCCESS; + error: + VIR_FREE(output); + virCommandFree(cmd); + return VIR_DRV_OPEN_ERROR; +} + +static int +jailhouseConnectClose(virConnectPtr conn) +{ + + virJailhouseDriverPtr driver = (virJailhouseDriverPtr)conn->privateData; + size_t i; + size_t cellsCount = driver->lastQueryCellsCount; + virJailhouseCellPtr cells = driver->lastQueryCells; + for (i = 0; i < cellsCount; i++) { + virBitmapFree(cells[i].assignedCPUs); + virBitmapFree(cells[i].failedCPUs); + } + VIR_FREE(cells); + VIR_FREE(driver->binary); + VIR_FREE(driver); + conn->privateData = NULL; + return 0; +} + +static int +jailhouseConnectNumOfDomains(virConnectPtr conn) +{ + virJailhouseGetCurrentCellList(conn); + return ((virJailhouseDriverPtr)conn->privateData)->lastQueryCellsCount; +} + +static int +jailhouseConnectListDomains(virConnectPtr conn, int * ids, int maxids) +{ + virJailhouseDriverPtr driver = (virJailhouseDriverPtr)conn->privateData; + size_t cellsCount; + size_t i; + virJailhouseGetCurrentCellList(conn); + cellsCount = driver->lastQueryCellsCount; + virJailhouseCellPtr cells = driver->lastQueryCells; + 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); + virJailhouseDriverPtr driver = (virJailhouseDriverPtr)conn->privateData; + size_t cellsCount; + size_t i; + virJailhouseGetCurrentCellList(conn); + cellsCount = driver->lastQueryCellsCount; + virJailhouseCellPtr cells = driver->lastQueryCells; + if (cellsCount == -1) + goto error; + if (VIR_ALLOC_N(*domains, cellsCount+1) < 0) + goto error; + for (i = 0; i < cellsCount; i++) + (*domains)[i] = virJailhouseCellToDomainPtr(conn, cells+i); + (*domains)[cellsCount] = NULL; + return cellsCount; + error: + *domains = NULL; + return -1; +} + +static virDomainPtr +jailhouseDomainLookupByID(virConnectPtr conn, int id) +{ + virJailhouseDriverPtr driver = (virJailhouseDriverPtr)conn->privateData; + size_t cellsCount; + size_t i; + virJailhouseGetCurrentCellList(conn); + cellsCount = driver->lastQueryCellsCount; + if (cellsCount == -1) + return NULL; + virJailhouseCellPtr cells = driver->lastQueryCells; + for (i = 0; i < cellsCount; i++) + if (cells[i].id == id) + return virJailhouseCellToDomainPtr(conn, cells+i); + virReportError(VIR_ERR_NO_DOMAIN, NULL); + return NULL; +} + +static virDomainPtr +jailhouseDomainLookupByName(virConnectPtr conn, const char *lookupName) +{ + virJailhouseDriverPtr driver = (virJailhouseDriverPtr)conn->privateData; + size_t cellsCount; + size_t i; + virJailhouseGetCurrentCellList(conn); + cellsCount = driver->lastQueryCellsCount; + if (cellsCount == -1) + return NULL; + virJailhouseCellPtr cells = driver->lastQueryCells; + for (i = 0; i < cellsCount; i++) + if (STREQ(cells[i].name, lookupName)) + return virJailhouseCellToDomainPtr(conn, cells+i); + virReportError(VIR_ERR_NO_DOMAIN, NULL); + return NULL; +} + +static virDomainPtr +jailhouseDomainLookupByUUID(virConnectPtr conn, const unsigned char * uuid) +{ + virJailhouseDriverPtr driver = (virJailhouseDriverPtr)conn->privateData; + size_t cellsCount; + size_t i; + virJailhouseGetCurrentCellList(conn); + cellsCount = driver->lastQueryCellsCount; + if (cellsCount == -1) + return NULL; + virJailhouseCellPtr cells = driver->lastQueryCells; + for (i = 0; i < cellsCount; i++) + if (memcmp(cells[i].uuid, (const char*)uuid, VIR_UUID_BUFLEN) == 0) + return virJailhouseCellToDomainPtr(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) +{ + virJailhouseCellPtr cell = virDomainPtrToCell(domain); + if (cell == NULL) + return -1; + info->state = virJailhouseCellToState(cell); + info->maxMem = 0; + info->memory = 0; + info->nrVirtCpu = virBitmapCountBits(cell->assignedCPUs); + info->cpuTime = 0; + return 0; +} + +static int +jailhouseDomainGetState(virDomainPtr domain, int *state, + int *reason ATTRIBUTE_UNUSED, unsigned int flags) +{ + virCheckFlags(0, 0); + virJailhouseCellPtr cell = virDomainPtrToCell(domain); + if (cell == NULL) + return -1; + *state = virJailhouseCellToState(cell); + return 0; +} + +static int +jailhouseDomainShutdown(virDomainPtr domain) +{ + int resultcode; + virCommandPtr cmd = virCommandNew(((virJailhouseDriverPtr)domain->conn->privateData)->binary); + virCommandAddArg(cmd, "cell"); + virCommandAddArg(cmd, "shutdown"); + virCommandAddArgFormat(cmd, "%d", domain->id); + virCommandAddEnvPassCommon(cmd); + resultcode = virCommandRun(cmd, NULL); + virCommandFree(cmd); + 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) +{ + int resultcode; + virCommandPtr cmd = virCommandNew(((virJailhouseDriverPtr)domain->conn->privateData)->binary); + virCommandAddArg(cmd, "cell"); + virCommandAddArg(cmd, "destroy"); + virCommandAddArgFormat(cmd, "%d", domain->id); + virCommandAddEnvPassCommon(cmd); + resultcode = virCommandRun(cmd, NULL); + virCommandFree(cmd); + if (resultcode < 0) + return -1; + return 0; +} + +static int +jailhouseDomainCreate(virDomainPtr domain) +{ + int resultcode; + virCommandPtr cmd = virCommandNew(((virJailhouseDriverPtr)domain->conn->privateData)->binary); + virCommandAddArg(cmd, "cell"); + virCommandAddArg(cmd, "start"); + virCommandAddArgFormat(cmd, "%d", domain->id); + virCommandAddEnvPassCommon(cmd); + resultcode = virCommandRun(cmd, NULL); + virCommandFree(cmd); + 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) +{ + virCapsPtr caps = virCapabilitiesNew(VIR_ARCH_NONE, false, false); + char* xml = virCapabilitiesFormatXML(caps); + virObjectUnref(caps); + return xml; +} + +static char * +jailhouseDomainGetXMLDesc(virDomainPtr domain, unsigned int flags) +{ + virCheckFlags(0, NULL); + char* xml; + virDomainDefPtr domainDef = virDomainDefNewFull(domain->name, domain->uuid, domain->id); + xml = virDomainDefFormat(domainDef, 0); + virObjectUnref(domainDef); + return xml; +} + +static virHypervisorDriver jailhouseHypervisorDriver = { + .name = "jailhouse", + .connectOpen = jailhouseConnectOpen, /* 1.3.0 */ + .connectClose = jailhouseConnectClose, /* 1.3.0 */ + .connectGetCapabilities = jailhouseConnectGetCapabilities, /* 1.3.0 */ + .connectNumOfDomains = jailhouseConnectNumOfDomains, /* 1.3.0 */ + .connectListDomains = jailhouseConnectListDomains, /* 1.3.0 */ + .connectIsAlive = jailhouseConnectIsAlive, /* 1.3.0 */ + .connectListAllDomains = jailhouseConnectListAllDomains, /* 1.3.0 */ + .domainLookupByID = jailhouseDomainLookupByID, /* 1.3.0 */ + .domainLookupByName = jailhouseDomainLookupByName, /* 1.3.0 */ + .domainLookupByUUID = jailhouseDomainLookupByUUID, /* 1.3.0 */ + .domainGetInfo = jailhouseDomainGetInfo, /* 1.3.0 */ + .domainGetState = jailhouseDomainGetState, /* 1.3.0 */ + .domainGetXMLDesc = jailhouseDomainGetXMLDesc, /* 1.3.0 */ + .domainShutdown = jailhouseDomainShutdown, /* 1.3.0 */ + .domainDestroy = jailhouseDomainDestroy, /* 1.3.0 */ + .domainCreate = jailhouseDomainCreate, /* 1.3.0 */ + .nodeGetInfo = jailhouseNodeGetInfo /* 1.3.0 */ +}; + +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..4d5288b 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,6 +440,10 @@ virGlobalInit(void) if (vzRegister() == -1) goto error; # endif +#ifdef WITH_JAILHOUSE + if (jailhouseRegister() == -1) + goto error; +#endif #endif #ifdef WITH_REMOTE if (remoteRegister() == -1) @@ -1167,6 +1174,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