[libvirt] [PATCH 1/3] util: capabilities detection for dnsmasq
Doug Goldstein
cardoe at cardoe.com
Thu Nov 22 05:26:27 UTC 2012
On Nov 21, 2012, at 8:55 PM, Laine Stump <laine at laine.org> wrote:
> In order to optionally take advantage of new features in dnsmasq when
> the host's version of dnsmasq supports them, but still be able to run
> on hosts that don't support the new features, we need to be able to
> detect the version of dnsmasq running on the host, and possibly
> determine from the help output what options are in this dnsmasq.
>
> This patch implements a greatly simplified version of the capabilities
> code we already have for qemu. A dnsmasqCaps device can be created and
> populated either from running a program on disk, reading a file with
> the concatenated output of "dnsmasq --version; dnsmasq --help", or
> examining a buffer in memory that contains the concatenated output of
> those two commands. Simple functions to retrieve capabilities flags,
> the version number, and the path of the binary are also included.
>
> bridge_driver.c creates a single dnsmasqCaps object at driver startup,
> and disposes of it at driver shutdown. Any time it must be used, the
> dnsmasqCapsRefresh method is called - it checks the mtime of the
> binary, and re-runs the checks if the binary has changed.
I would try it myself but I'm on vacation with only an iPad. What happens if no dnsmasq is installed? It doesn't impede libvirtd starting up if no networks are configured?
>
> networkxml2argvtest.c creates 2 "artificial" dnsmasqCaps objects at
> startup - one "restricted" (doesn't support --bind-dynamic) and one
> "full" (does support --bind-dynamic). Some of the test cases use one
> and some the other, to make sure both code pathes are tested.
> ---
> src/libvirt_private.syms | 8 +-
> src/network/bridge_driver.c | 59 ++++++----
> src/network/bridge_driver.h | 7 +-
> src/util/dnsmasq.c | 260 ++++++++++++++++++++++++++++++++++++++++++++
> src/util/dnsmasq.h | 20 +++-
> tests/networkxml2argvtest.c | 57 ++++++----
> 6 files changed, 366 insertions(+), 45 deletions(-)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 5a07139..24d2033 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -244,13 +244,19 @@ virDevicePCIAddressParseXML;
> # dnsmasq.h
> dnsmasqAddDhcpHost;
> dnsmasqAddHost;
> +dnsmasqCapsGet;
> +dnsmasqCapsGetBinaryPath;
> +dnsmasqCapsGetVersion;
> +dnsmasqCapsNewFromBuffer;
> +dnsmasqCapsNewFromFile;
> +dnsmasqCapsNewFromBinary;
> +dnsmasqCapsRefresh;
> dnsmasqContextFree;
> dnsmasqContextNew;
> dnsmasqDelete;
> dnsmasqReload;
> dnsmasqSave;
>
> -
> # domain_audit.h
> virDomainAuditCgroup;
> virDomainAuditCgroupMajor;
> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
> index c153d36..34923ea 100644
> --- a/src/network/bridge_driver.c
> +++ b/src/network/bridge_driver.c
> @@ -85,6 +85,7 @@ struct network_driver {
> char *networkConfigDir;
> char *networkAutostartDir;
> char *logDir;
> + dnsmasqCapsPtr dnsmasqCaps;
> };
>
>
> @@ -271,7 +272,8 @@ networkFindActiveConfigs(struct network_driver *driver) {
> char *radvdpidbase;
>
> ignore_value(virPidFileReadIfAlive(NETWORK_PID_DIR, obj->def->name,
> - &obj->dnsmasqPid, DNSMASQ));
> + &obj->dnsmasqPid,
> + dnsmasqCapsGetBinaryPath(driver->dnsmasqCaps)));
>
> if (!(radvdpidbase = networkRadvdPidfileBasename(obj->def->name))) {
> virReportOOMError();
> @@ -389,6 +391,9 @@ networkStartup(int privileged) {
> goto out_of_memory;
> }
>
> + if (!(driverState->dnsmasqCaps = dnsmasqCapsNewFromBinary(DNSMASQ))) {
> + /* attempt to continue anyway */
> + }
>
> if (virNetworkLoadAllConfigs(&driverState->networks,
> driverState->networkConfigDir,
> @@ -514,6 +519,8 @@ networkShutdown(void) {
> if (driverState->iptables)
> iptablesContextFree(driverState->iptables);
>
> + virObjectUnref(driverState->dnsmasqCaps);
> +
> networkDriverUnlock(driverState);
> virMutexDestroy(&driverState->lock);
>
> @@ -616,7 +623,8 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
> virNetworkIpDefPtr ipdef,
> const char *pidfile,
> virCommandPtr cmd,
> - dnsmasqContext *dctx)
> + dnsmasqContext *dctx,
> + dnsmasqCapsPtr caps ATTRIBUTE_UNUSED)
> {
> int r, ret = -1;
> int nbleases = 0;
> @@ -848,7 +856,8 @@ cleanup:
>
> int
> networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdout,
> - char *pidfile, dnsmasqContext *dctx)
> + char *pidfile, dnsmasqContext *dctx,
> + dnsmasqCapsPtr caps)
> {
> virCommandPtr cmd = NULL;
> int ret = -1, ii;
> @@ -876,8 +885,8 @@ networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network, virCommandPtr *cmdou
> if (!virNetworkDefGetIpByIndex(network->def, AF_UNSPEC, 0))
> return 0;
>
> - cmd = virCommandNew(DNSMASQ);
> - if (networkBuildDnsmasqArgv(network, ipdef, pidfile, cmd, dctx) < 0) {
> + cmd = virCommandNew(dnsmasqCapsGetBinaryPath(caps));
> + if (networkBuildDnsmasqArgv(network, ipdef, pidfile, cmd, dctx, caps) < 0) {
> goto cleanup;
> }
>
> @@ -891,7 +900,8 @@ cleanup:
> }
>
> static int
> -networkStartDhcpDaemon(virNetworkObjPtr network)
> +networkStartDhcpDaemon(struct network_driver *driver,
> + virNetworkObjPtr network)
> {
> virCommandPtr cmd = NULL;
> char *pidfile = NULL;
> @@ -935,7 +945,9 @@ networkStartDhcpDaemon(virNetworkObjPtr network)
> if (dctx == NULL)
> goto cleanup;
>
> - ret = networkBuildDhcpDaemonCommandLine(network, &cmd, pidfile, dctx);
> + dnsmasqCapsRefresh(driver->dnsmasqCaps, false);
> +
> + ret = networkBuildDhcpDaemonCommandLine(network, &cmd, pidfile, dctx, driver->dnsmasqCaps);
> if (ret < 0)
> goto cleanup;
>
> @@ -988,7 +1000,8 @@ cleanup:
> * Returns 0 on success, -1 on failure.
> */
> static int
> -networkRefreshDhcpDaemon(virNetworkObjPtr network)
> +networkRefreshDhcpDaemon(struct network_driver *driver,
> + virNetworkObjPtr network)
> {
> int ret = -1, ii;
> virNetworkIpDefPtr ipdef;
> @@ -996,7 +1009,7 @@ networkRefreshDhcpDaemon(virNetworkObjPtr network)
>
> /* if there's no running dnsmasq, just start it */
> if (network->dnsmasqPid <= 0 || (kill(network->dnsmasqPid, 0) < 0))
> - return networkStartDhcpDaemon(network);
> + return networkStartDhcpDaemon(driver, network);
>
> /* Look for first IPv4 address that has dhcp defined. */
> /* We support dhcp config on 1 IPv4 interface only. */
> @@ -1038,7 +1051,8 @@ cleanup:
> * Returns 0 on success, -1 on failure.
> */
> static int
> -networkRestartDhcpDaemon(virNetworkObjPtr network)
> +networkRestartDhcpDaemon(struct network_driver *driver,
> + virNetworkObjPtr network)
> {
> /* if there is a running dnsmasq, kill it */
> if (network->dnsmasqPid > 0) {
> @@ -1047,7 +1061,7 @@ networkRestartDhcpDaemon(virNetworkObjPtr network)
> network->dnsmasqPid = -1;
> }
> /* now start dnsmasq if it should be started */
> - return networkStartDhcpDaemon(network);
> + return networkStartDhcpDaemon(driver, network);
> }
>
> static int
> @@ -1245,7 +1259,8 @@ cleanup:
> }
>
> static int
> -networkRefreshRadvd(virNetworkObjPtr network)
> +networkRefreshRadvd(struct network_driver *driver ATTRIBUTE_UNUSED,
> + virNetworkObjPtr network)
> {
> /* if there's no running radvd, just start it */
> if (network->radvdPid <= 0 || (kill(network->radvdPid, 0) < 0))
> @@ -1265,7 +1280,8 @@ networkRefreshRadvd(virNetworkObjPtr network)
> #if 0
> /* currently unused, so it causes a build error unless we #if it out */
> static int
> -networkRestartRadvd(virNetworkObjPtr network)
> +networkRestartRadvd(struct network_driver *driver,
> + virNetworkObjPtr network)
> {
> char *radvdpidbase;
>
> @@ -1313,8 +1329,8 @@ networkRefreshDaemons(struct network_driver *driver)
> * dnsmasq and/or radvd, or restart them if they've
> * disappeared.
> */
> - networkRefreshDhcpDaemon(network);
> - networkRefreshRadvd(network);
> + networkRefreshDhcpDaemon(driver, network);
> + networkRefreshRadvd(driver, network);
> }
> virNetworkObjUnlock(network);
> }
> @@ -2224,7 +2240,8 @@ networkStartNetworkVirtual(struct network_driver *driver,
>
>
> /* start dnsmasq if there are any IP addresses (v4 or v6) */
> - if ((v4present || v6present) && networkStartDhcpDaemon(network) < 0)
> + if ((v4present || v6present) &&
> + networkStartDhcpDaemon(driver, network) < 0)
> goto err3;
>
> /* start radvd if there are any ipv6 addresses */
> @@ -2988,7 +3005,7 @@ networkUpdate(virNetworkPtr net,
> /* these sections all change things on the dnsmasq commandline,
> * so we need to kill and restart dnsmasq.
> */
> - if (networkRestartDhcpDaemon(network) < 0)
> + if (networkRestartDhcpDaemon(driver,network) < 0)
> goto cleanup;
>
> } else if (section == VIR_NETWORK_SECTION_IP_DHCP_HOST) {
> @@ -3009,8 +3026,8 @@ networkUpdate(virNetworkPtr net,
> }
>
> if ((newDhcpActive != oldDhcpActive &&
> - networkRestartDhcpDaemon(network) < 0) ||
> - networkRefreshDhcpDaemon(network) < 0) {
> + networkRestartDhcpDaemon(driver, network) < 0) ||
> + networkRefreshDhcpDaemon(driver, network) < 0) {
> goto cleanup;
> }
>
> @@ -3021,7 +3038,7 @@ networkUpdate(virNetworkPtr net,
> * can just update the config files and send SIGHUP to
> * dnsmasq.
> */
> - if (networkRefreshDhcpDaemon(network) < 0)
> + if (networkRefreshDhcpDaemon(driver, network) < 0)
> goto cleanup;
>
> }
> @@ -3030,7 +3047,7 @@ networkUpdate(virNetworkPtr net,
> /* only a change in IP addresses will affect radvd, and all of radvd's
> * config is stored in the conf file which will be re-read with a SIGHUP.
> */
> - if (networkRefreshRadvd(network) < 0)
> + if (networkRefreshRadvd(driver, network) < 0)
> goto cleanup;
> }
>
> diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h
> index 0fae275..3af74a1 100644
> --- a/src/network/bridge_driver.h
> +++ b/src/network/bridge_driver.h
> @@ -1,7 +1,7 @@
> /*
> * network_driver.h: core driver methods for managing networks
> *
> - * Copyright (C) 2006, 2007, 2011 Red Hat, Inc.
> + * Copyright (C) 2006-2012 Red Hat, Inc.
> * Copyright (C) 2006 Daniel P. Berrange
> *
> * This library is free software; you can redistribute it and/or
> @@ -48,7 +48,8 @@ int networkGetNetworkAddress(const char *netname, char **netaddr)
>
> int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network,
> virCommandPtr *cmdout, char *pidfile,
> - dnsmasqContext *dctx)
> + dnsmasqContext *dctx,
> + dnsmasqCapsPtr caps)
> ;
> # else
> /* Define no-op replacements that don't drag in any link dependencies. */
> @@ -56,7 +57,7 @@ int networkBuildDhcpDaemonCommandLine(virNetworkObjPtr network,
> # define networkNotifyActualDevice(iface) 0
> # define networkReleaseActualDevice(iface) 0
> # define networkGetNetworkAddress(netname, netaddr) (-2)
> -# define networkBuildDhcpDaemonCommandLine(network, cmdout, pidfile, dctx) 0
> +# define networkBuildDhcpDaemonCommandLine(network, cmdout, pidfile, dctx, caps) 0
> # endif
>
> typedef char *(*networkDnsmasqLeaseFileNameFunc)(const char *netname);
> diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c
> index 9d1c07b..03b3792 100644
> --- a/src/util/dnsmasq.c
> +++ b/src/util/dnsmasq.c
> @@ -39,8 +39,10 @@
>
> #include "internal.h"
> #include "datatypes.h"
> +#include "bitmap.h"
> #include "dnsmasq.h"
> #include "util.h"
> +#include "command.h"
> #include "memory.h"
> #include "virterror_internal.h"
> #include "logging.h"
> @@ -583,3 +585,261 @@ dnsmasqReload(pid_t pid ATTRIBUTE_UNUSED)
>
> return 0;
> }
> +
> +/*
> + * dnsmasqCapabilities functions - provide useful information about the
> + * version of dnsmasq on this machine.
> + *
> + */
> +struct _dnsmasqCaps {
> + virObject object;
> + char *binaryPath;
> + bool noRefresh;
> + time_t mtime;
> + virBitmapPtr flags;
> + unsigned long version;
> +};
> +
> +static virClassPtr dnsmasqCapsClass;
> +
> +static void
> +dnsmasqCapsDispose(void *obj)
> +{
> + dnsmasqCapsPtr caps = obj;
> +
> + virBitmapFree(caps->flags);
> + VIR_FREE(caps->binaryPath);
> +}
> +
> +static int dnsmasqCapsOnceInit(void)
> +{
> + if (!(dnsmasqCapsClass = virClassNew("dnsmasqCaps",
> + sizeof(dnsmasqCaps),
> + dnsmasqCapsDispose))) {
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +VIR_ONCE_GLOBAL_INIT(dnsmasqCaps)
> +
> +static void
> +dnsmasqCapsSet(dnsmasqCapsPtr caps,
> + dnsmasqCapsFlags flag)
> +{
> + ignore_value(virBitmapSetBit(caps->flags, flag));
> +}
> +
> +
> +#define SKIP_BLANKS(p) do { while ((*(p) == ' ') || (*(p) == '\t')) (p)++; } while (0)
> +#define DNSMASQ_VERSION_STR "Dnsmasq version "
> +
> +static int
> +dnsmasqCapsSetFromBuffer(dnsmasqCapsPtr caps, const char *buf)
> +{
> + const char *p;
> +
> + caps->noRefresh = true;
> +
> + p = buf;
> + if (!STRPREFIX(p, DNSMASQ_VERSION_STR))
> + goto fail;
> + p += strlen(DNSMASQ_VERSION_STR);
> + SKIP_BLANKS(p);
> + if (virParseVersionString(p, &caps->version, true) < 0)
> + goto fail;
> +
> + if (strstr(buf, "--bind-dynamic"))
> + dnsmasqCapsSet(caps, DNSMASQ_CAPS_BIND_DYNAMIC);
> +
> + VIR_INFO("dnsmasq version is %d.%d, --bind-dynamic is %s",
> + (int)caps->version / 1000000, (int)(caps->version % 1000000) / 1000,
> + dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC)
> + ? "present" : "NOT present");
> + return 0;
> +
> +fail:
> + p = strchr(buf, '\n');
> + if (!p)
> + p = strchr(buf, '\0');
> +
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("cannot parse %s version number in '%.*s'"),
> + caps->binaryPath, (int) (p - buf), buf);
> + return -1;
> +
> +}
> +
> +static int
> +dnsmasqCapsSetFromFile(dnsmasqCapsPtr caps, const char *path)
> +{
> + int ret = -1;
> + char *buf = NULL;
> +
> + if (virFileReadAll(path, 1024 * 1024, &buf) < 0)
> + goto cleanup;
> +
> + ret = dnsmasqCapsSetFromBuffer(caps, buf);
> +
> +cleanup:
> + VIR_FREE(buf);
> + return ret;
> +}
> +
> +int
> +dnsmasqCapsRefresh(dnsmasqCapsPtr caps, bool force)
> +{
> + int ret = -1;
> + struct stat sb;
> + virCommandPtr cmd = NULL;
> + char *help = NULL, *version = NULL, *complete = NULL;
> +
> + if (!caps || caps->noRefresh)
> + return 0;
> +
> + if (stat(caps->binaryPath, &sb) < 0) {
> + virReportSystemError(errno, _("Cannot check dnsmasq binary %s"),
> + caps->binaryPath);
> + return -1;
> + }
> + if (!force && caps->mtime == sb.st_mtime) {
> + return 0;
> + }
> + caps->mtime = sb.st_mtime;
> +
> + /* Make sure the binary we are about to try exec'ing exists.
> + * Technically we could catch the exec() failure, but that's
> + * in a sub-process so it's hard to feed back a useful error.
> + */
> + if (!virFileIsExecutable(caps->binaryPath)) {
> + virReportSystemError(errno, _("dnsmasq binary %s is not executable"),
> + caps->binaryPath);
> + goto cleanup;
> + }
> +
> + cmd = virCommandNewArgList(caps->binaryPath, "--version", NULL);
> + virCommandSetOutputBuffer(cmd, &version);
> + virCommandSetErrorBuffer(cmd, &version);
> + if (virCommandRun(cmd, NULL) < 0) {
> + virReportSystemError(errno, _("failed to run '%s --version': %s"),
> + caps->binaryPath, version);
> + goto cleanup;
> + }
> + virCommandFree(cmd);
> +
> + cmd = virCommandNewArgList(caps->binaryPath, "--help", NULL);
> + virCommandSetOutputBuffer(cmd, &help);
> + virCommandSetErrorBuffer(cmd, &help);
> + if (virCommandRun(cmd, NULL) < 0) {
> + virReportSystemError(errno, _("failed to run '%s --help': %s"),
> + caps->binaryPath, help);
> + goto cleanup;
> + }
> +
> + if (virAsprintf(&complete, "%s\n%s", version, help) < 0) {
> + virReportOOMError();
> + goto cleanup;
> + }
> +
> + ret = dnsmasqCapsSetFromBuffer(caps, complete);
> +
> +cleanup:
> + virCommandFree(cmd);
> + VIR_FREE(help);
> + VIR_FREE(version);
> + VIR_FREE(complete);
> + return ret;
> +}
> +
> +static dnsmasqCapsPtr
> +dnsmasqCapsNewEmpty(const char *binaryPath)
> +{
> + dnsmasqCapsPtr caps;
> +
> + if (dnsmasqCapsInitialize() < 0)
> + return NULL;
> + if (!(caps = virObjectNew(dnsmasqCapsClass)))
> + return NULL;
> + if (!(caps->flags = virBitmapNew(DNSMASQ_CAPS_LAST)))
> + goto error;
> + if (!(caps->binaryPath = strdup(binaryPath ? binaryPath : DNSMASQ)))
> + goto error;
> + return caps;
> +
> +error:
> + virReportOOMError();
> + virObjectUnref(caps);
> + return NULL;
> +}
> +
> +dnsmasqCapsPtr
> +dnsmasqCapsNewFromBuffer(const char *buf, const char *binaryPath)
> +{
> + dnsmasqCapsPtr caps = dnsmasqCapsNewEmpty(binaryPath);
> +
> + if (!caps)
> + return NULL;
> +
> + if (dnsmasqCapsSetFromBuffer(caps, buf) < 0) {
> + virObjectUnref(caps);
> + return NULL;
> + }
> + return caps;
> +}
> +
> +dnsmasqCapsPtr
> +dnsmasqCapsNewFromFile(const char *dataPath, const char *binaryPath)
> +{
> + dnsmasqCapsPtr caps = dnsmasqCapsNewEmpty(binaryPath);
> +
> + if (!caps)
> + return NULL;
> +
> + if (dnsmasqCapsSetFromFile(caps, dataPath) < 0) {
> + virObjectUnref(caps);
> + return NULL;
> + }
> + return caps;
> +}
> +
> +dnsmasqCapsPtr
> +dnsmasqCapsNewFromBinary(const char *binaryPath)
> +{
> + dnsmasqCapsPtr caps = dnsmasqCapsNewEmpty(binaryPath);
> +
> + if (!caps)
> + return NULL;
> +
> + if (dnsmasqCapsRefresh(caps, true) < 0) {
> + virObjectUnref(caps);
> + return NULL;
> + }
> + return caps;
> +}
> +
> +const char *
> +dnsmasqCapsGetBinaryPath(dnsmasqCapsPtr caps)
> +{
> + return caps ? caps->binaryPath : DNSMASQ;
> +}
> +
> +unsigned long
> +dnsmasqCapsGetVersion(dnsmasqCapsPtr caps)
> +{
> + if (caps)
> + return caps->version;
> + else
> + return 0;
> +}
> +
> +bool
> +dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag)
> +{
> + bool b;
> +
> + if (!caps || virBitmapGetBit(caps->flags, flag, &b) < 0)
> + return false;
> + else
> + return b;
> +}
> diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h
> index ad612be..48f0bf9 100644
> --- a/src/util/dnsmasq.h
> +++ b/src/util/dnsmasq.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (C) 2007-2010 Red Hat, Inc.
> + * Copyright (C) 2007-2012 Red Hat, Inc.
> * Copyright (C) 2010 Satoru SATOH <satoru.satoh at gmail.com>
> *
> * This library is free software; you can redistribute it and/or
> @@ -22,6 +22,7 @@
> #ifndef __DNSMASQ_H__
> # define __DNSMASQ_H__
>
> +# include "virobject.h"
> # include "virsocketaddr.h"
>
> typedef struct
> @@ -65,6 +66,16 @@ typedef struct
> dnsmasqAddnHostsfile *addnhostsfile;
> } dnsmasqContext;
>
> +typedef enum {
> + DNSMASQ_CAPS_BIND_DYNAMIC = 0, /* support for --bind-dynamic */
> +
> + DNSMASQ_CAPS_LAST, /* this must always be the last item */
> +} dnsmasqCapsFlags;
> +
> +typedef struct _dnsmasqCaps dnsmasqCaps;
> +typedef dnsmasqCaps *dnsmasqCapsPtr;
> +
> +
> dnsmasqContext * dnsmasqContextNew(const char *network_name,
> const char *config_dir);
> void dnsmasqContextFree(dnsmasqContext *ctx);
> @@ -79,4 +90,11 @@ int dnsmasqSave(const dnsmasqContext *ctx);
> int dnsmasqDelete(const dnsmasqContext *ctx);
> int dnsmasqReload(pid_t pid);
>
> +dnsmasqCapsPtr dnsmasqCapsNewFromBuffer(const char *buf, const char *binaryPath);
> +dnsmasqCapsPtr dnsmasqCapsNewFromFile(const char *dataPath, const char *binaryPath);
> +dnsmasqCapsPtr dnsmasqCapsNewFromBinary(const char *binaryPath);
> +int dnsmasqCapsRefresh(dnsmasqCapsPtr caps, bool force);
> +bool dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag);
> +const char *dnsmasqCapsGetBinaryPath(dnsmasqCapsPtr caps);
> +unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps);
> #endif /* __DNSMASQ_H__ */
> diff --git a/tests/networkxml2argvtest.c b/tests/networkxml2argvtest.c
> index 87519e4..69cbd1c 100644
> --- a/tests/networkxml2argvtest.c
> +++ b/tests/networkxml2argvtest.c
> @@ -46,7 +46,9 @@ static int replaceTokens(char **buf, const char *token, const char *replacement)
> return 0;
> }
>
> -static int testCompareXMLToArgvFiles(const char *inxml, const char *outargv) {
> +static int
> +testCompareXMLToArgvFiles(const char *inxml, const char *outargv, dnsmasqCapsPtr caps)
> +{
> char *inXmlData = NULL;
> char *outArgvData = NULL;
> char *actual = NULL;
> @@ -78,7 +80,7 @@ static int testCompareXMLToArgvFiles(const char *inxml, const char *outargv) {
> if (dctx == NULL)
> goto fail;
>
> - if (networkBuildDhcpDaemonCommandLine(obj, &cmd, pidfile, dctx) < 0)
> + if (networkBuildDhcpDaemonCommandLine(obj, &cmd, pidfile, dctx, caps) < 0)
> goto fail;
>
> if (!(actual = virCommandToString(cmd)))
> @@ -102,21 +104,27 @@ static int testCompareXMLToArgvFiles(const char *inxml, const char *outargv) {
> return ret;
> }
>
> +typedef struct {
> + const char *name;
> + dnsmasqCapsPtr caps;
> +} testInfo;
> +
> static int
> testCompareXMLToArgvHelper(const void *data)
> {
> int result = -1;
> + const testInfo *info = data;
> char *inxml = NULL;
> char *outxml = NULL;
>
> if (virAsprintf(&inxml, "%s/networkxml2argvdata/%s.xml",
> - abs_srcdir, (const char*)data) < 0 ||
> + abs_srcdir, info->name) < 0 ||
> virAsprintf(&outxml, "%s/networkxml2argvdata/%s.argv",
> - abs_srcdir, (const char*)data) < 0) {
> + abs_srcdir, info->name) < 0) {
> goto cleanup;
> }
>
> - result = testCompareXMLToArgvFiles(inxml, outxml);
> + result = testCompareXMLToArgvFiles(inxml, outxml, info->caps);
>
> cleanup:
> VIR_FREE(inxml);
> @@ -140,23 +148,34 @@ static int
> mymain(void)
> {
> int ret = 0;
> + dnsmasqCapsPtr restricted
> + = dnsmasqCapsNewFromBuffer("Dnsmasq version 2.48", DNSMASQ);
> + dnsmasqCapsPtr full
> + = dnsmasqCapsNewFromBuffer("Dnsmasq version 2.63\n--bind-dynamic", DNSMASQ);
>
> networkDnsmasqLeaseFileName = testDnsmasqLeaseFileName;
>
> -#define DO_TEST(name) \
> - if (virtTestRun("Network XML-2-Argv " name, \
> - 1, testCompareXMLToArgvHelper, (name)) < 0) \
> - ret = -1
> -
> - DO_TEST("isolated-network");
> - DO_TEST("routed-network");
> - DO_TEST("nat-network");
> - DO_TEST("netboot-network");
> - DO_TEST("netboot-proxy-network");
> - DO_TEST("nat-network-dns-txt-record");
> - DO_TEST("nat-network-dns-srv-record");
> - DO_TEST("nat-network-dns-srv-record-minimal");
> - DO_TEST("nat-network-dns-hosts");
> +#define DO_TEST(xname, xcaps) \
> + do { \
> + static testInfo info; \
> + \
> + info.name = xname; \
> + info.caps = xcaps; \
> + if (virtTestRun("Network XML-2-Argv " xname, \
> + 1, testCompareXMLToArgvHelper, &info) < 0) { \
> + ret = -1; \
> + } \
> + } while (0)
> +
> + DO_TEST("isolated-network", restricted);
> + DO_TEST("netboot-network", restricted);
> + DO_TEST("netboot-proxy-network", restricted);
> + DO_TEST("nat-network-dns-srv-record-minimal", restricted);
> + DO_TEST("routed-network", full);
> + DO_TEST("nat-network", full);
> + DO_TEST("nat-network-dns-txt-record", full);
> + DO_TEST("nat-network-dns-srv-record", full);
> + DO_TEST("nat-network-dns-hosts", full);
>
> return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
> }
> --
> 1.7.11.7
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
More information about the libvir-list
mailing list