[libvirt] [PATCH] hypervisor driver for Jailhouse

Daniel P. Berrange berrange at redhat.com
Fri Dec 11 14:51:40 UTC 2015


On Wed, Nov 25, 2015 at 02:39:17PM +0100, Christian Loehle wrote:
> The suggestions in your review should all be implemented now.


NB, as mentioned on IRC, for future postings please send as
a top-level patch, rather than in-reply to, and use
--subject-prefix 'PATCH v3' to indicate the 3rd posting
for example.


> diff --git a/libvirt-jailhousev2.patch b/libvirt-jailhousev2.patch
> new file mode 100644
> index 0000000..e69de29

This file probably shouldn't have been added

> 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 @@
> +
> +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])
> +

You need

    if test "$with_jailhouse" = "yes"; then
        AC_DEFINE_UNQUOTED([WITH_JAILHOUSE], 1, [whether jailhouse driver is enabled])
    fi

Without this, your code never gets enabled in libvirt.so,
so I'm not sure how you tested this patch, as the driver
is never loaded.

> +    AM_CONDITIONAL([WITH_JAILHOUSE], [test "$with_jailhouse" = "yes"])
> +])
> +
> +AC_DEFUN([LIBVIRT_DRIVER_RESULT_JAILHOUSE],[
> +    AC_MSG_NOTICE([Jailhouse: $with_jailhouse])
> +])

> 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).

As mentioned before, I really don't think we should be passing binary
names in the URI like this. For everything else in libvirt we just
rely on the binary being in $PATH. If someone has put jailhouse in
some unusual location, then can just pre-pend that location to $PATH

> +#define STATERUNNINGSTRING          "running         "
> +#define STATERUNNINGLOCKED 1
> +#define STATERUNNINGLOCKEDSTRING    "running/locked  "
> +#define STATESHUTDOWN 2
> +#define STATESHUTDOWNSTRING         "shut down       "
> +#define STATEFAILED 3
> +#define STATEFAILEDSTRING           "failed          "

Looks

> +#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;

You are not incrementing 'count' in the first patch of the
conditional, but you are incrementing it in the second.
As a result, as soon as you have more than one cell running
the following code will be a buffer overflow causing libvirt
to crash.  VIR_EXPAND_N copes just fine with cells being
NULL initially, so just get rid of the VIR_ALLOC and
always use VIR_EXPAND_N

> +    celldata->ncells++;
> +    if (virStrToLong_i(groups[0], &endptr, 0, &cells[count].id))
> +        return -1;

Then use 'count - 1' here, and on all subsequent lines

> +    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*" };

The regex is invalid, so again I'm not sure how you tested this
successfully.

If you want to include '-' in a character range, it must be the
first thing that is listed. Also 'A-z' is not valid as the end
is smaller than the start - you presumably mean 'A-Z'.

All in all the working regex would be

  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;

This causes you to silently ignore all errors from virJailhouseParseListOutput
which is clearly wrong - this hid the fact that your regex was broken and
so not returning any cell info for example.

You need to make this function return an 'int' and make sure all callers
check & propagate the error.


> +    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;
> +}

> +static virJailhouseCellPtr
> +virDomainPtrToCell(virDomainPtr dom)
> +{
> +    virJailhouseDriverPtr driver = (virJailhouseDriverPtr)dom->conn->privateData;

The cast '(virJailhouseDriverPtr)' is not needed - 'void*' casts to
any type automatically.

> +    size_t cellsCount;
> +    size_t i;
> +    virJailhouseGetCurrentCellList(dom->conn);

eg this must check for errors.


> +    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;

As mentioned earlier please drop this bit of URI parsing.

We should just accept the empty path or '/' as we do with
LXC, eg

        /* If path isn't '/' then they typoed, tell them correct path */
        if (conn->uri->path != NULL &&
            STRNEQ(conn->uri->path, "/")) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unexpected Jailhouse URI path '%s', try jailhouse:///"),
                           conn->uri->path);
            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;
> +}

In generall all this code would benefit from having some blank
lines inserted between logical blocks

> +
> +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;

Normally we expect all variables to be decalred before any code is
run. So please re-arrange this accordingly

> +    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;
> +}

The 'shutdown' command is intended to tell the guest init
system todo a graceful shutdown. AFAICT, this is not what
'cell shutdown' does - it is akin to immediately turning
off the power. So this should be called from the destroy
method in libvirt.

> +/*
> + *  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.
> + */

THis is bad - drivers should have consistent semantics for the
same operations, as apps using libvirt are not going to read this
comment.

> +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;

So this should be running 'shutdown' not 'destroy' IMHO

> +}
> +
> +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);

This causes libvirt to crash, because virDOmainDef is not an object,
you must call virDomainDefFree() instead

> +    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 */
> +};

Next time you post bump these versions to 1.3.1 since we've
released 1.3.0 now.

> +
> +static virConnectDriver jailhouseConnectDriver = {
> +    .hypervisorDriver = &jailhouseHypervisorDriver,
> +};
> +
> +int
> +jailhouseRegister(void)
> +{
> +    return virRegisterConnectDriver(&jailhouseConnectDriver,
> +                                    false);
> +}


In summary, there's nothing particularly bad about this, but this
patch clearly hasn't been tested, since there are 3 show stopping
bugs which prevent it working at all.

Please make sure patches are at least somewhat tested to work before
posting them

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 :|




More information about the libvir-list mailing list