[libvirt] [PATCH v5 4/5] Network: Add additional hosts internal infrastructure

Laine Stump laine at laine.org
Thu Jun 23 05:44:22 UTC 2011


On 06/14/2011 09:02 AM, Michal Novotny wrote:
> Signed-off-by: Michal Novotny<minovotn at redhat.com>
> ---
>   docs/formatnetwork.html.in  |   14 ++
>   src/libvirt_private.syms    |    1 +
>   src/network/bridge_driver.c |    3 +
>   src/util/dnsmasq.c          |  285 ++++++++++++++++++++++++++++++++++++++++---
>   src/util/dnsmasq.h          |   22 +++-
>   5 files changed, 305 insertions(+), 20 deletions(-)
>
> diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
> index 62e1e08..a036545 100644
> --- a/docs/formatnetwork.html.in
> +++ b/docs/formatnetwork.html.in
> @@ -218,6 +218,20 @@
>           element is used.  The BOOTP options currently have to be the same
>           for all address ranges and statically assigned addresses.<span
>           class="since">Since 0.7.1 (<code>server</code>  since 0.7.3).</span>
> +</dd>
> +<dt><code>host</code></dt>
> +<dd>The<code>host</code>  element is the definition of DNS hosts to be passed
> +         to the DNS service. The IP address is identified by the<code>ip</code>  attribute
> +         and the names for the IP addresses are identified in the<code>hostname</code>
> +         subelements of the<code>host</code>  element.
> +<span class="since">Since 0.9.1</span>
> +</dd>
> +<dt><code>host</code></dt>
> +<dd>The<code>host</code>  element is the definition of DNS hosts to be passed
> +        to the DNS service. The IP address is identified by the<code>ip</code>  attribute
> +        and the names for the IP addresses are identified in the<code>hostname</code>
> +        subelements of the<code>host</code>  element.
> +<span class="since">Since 0.9.1</span>
>         </dd>
>       </dl>
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 737cd31..71ef9cc 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -194,6 +194,7 @@ virUnrefStream;
>
>   # dnsmasq.h
>   dnsmasqAddDhcpHost;
> +dnsmasqAddHost;
>   dnsmasqContextFree;
>   dnsmasqContextNew;
>   dnsmasqDelete;
> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
> index 10bb928..f55f759 100644
> --- a/src/network/bridge_driver.c
> +++ b/src/network/bridge_driver.c
> @@ -607,6 +607,9 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
>               if (dctx->hostsfile->nhosts)
>                   virCommandAddArgPair(cmd, "--dhcp-hostsfile",
>                                        dctx->hostsfile->path);
> +            if (dctx->addnhostsfile->nhosts)
> +                virCommandAddArgPair(cmd, "--addn-hosts",
> +                                     dctx->addnhostsfile->path);
>
>               dnsmasqContextFree(dctx);
>           }
> diff --git a/src/util/dnsmasq.c b/src/util/dnsmasq.c
> index 2ba9355..04a912a 100644
> --- a/src/util/dnsmasq.c
> +++ b/src/util/dnsmasq.c
> @@ -48,6 +48,7 @@
>
>   #define VIR_FROM_THIS VIR_FROM_NETWORK
>   #define DNSMASQ_HOSTSFILE_SUFFIX "hostsfile"
> +#define DNSMASQ_ADDNHOSTSFILE_SUFFIX "addnhosts"
>
>   static void
>   dhcphostFree(dnsmasqDhcpHost *host)
> @@ -56,6 +57,235 @@ dhcphostFree(dnsmasqDhcpHost *host)
>   }
>
>   static void
> +addnhostFree(dnsmasqAddnHost *host)
> +{
> +    int i;
> +
> +    for (i = 0; i<  host->nhostnames; i++)
> +        VIR_FREE(host->hostnames[i]);
> +    VIR_FREE(host->hostnames);
> +    VIR_FREE(host->ip);
> +}
> +
> +static void
> +addnhostsFree(dnsmasqAddnHostsfile *addnhostsfile)
> +{
> +    unsigned int i;
> +
> +    if (addnhostsfile->hosts) {
> +        for (i = 0; i<  addnhostsfile->nhosts; i++)
> +            addnhostFree(&addnhostsfile->hosts[i]);
> +
> +        VIR_FREE(addnhostsfile->hosts);
> +
> +        addnhostsfile->nhosts = 0;
> +    }
> +
> +    VIR_FREE(addnhostsfile->path);
> +
> +    VIR_FREE(addnhostsfile);
> +}
> +
> +static int
> +addnhostsAdd(dnsmasqAddnHostsfile *addnhostsfile,
> +             virSocketAddr *ip,
> +             const char *name)
> +{
> +    char *ipstr = NULL;
> +    int idx = -1;
> +    int i;
> +
> +    if (!(ipstr = virSocketFormatAddr(ip)))
> +        return -1;
> +
> +    for (i = 0; i<  addnhostsfile->nhosts; i++) {
> +        if (STREQ((const char *)addnhostsfile->hosts[i].ip, (const char *)ipstr)) {
> +            idx = i;
> +            break;
> +        }
> +    }
> +
> +    if (idx<  0) {
> +        if (VIR_REALLOC_N(addnhostsfile->hosts, addnhostsfile->nhosts + 1)<  0)
> +            goto alloc_error;
> +
> +        idx = addnhostsfile->nhosts;
> +        if (VIR_ALLOC(addnhostsfile->hosts[idx].hostnames)<  0)
> +            goto alloc_error;
> +
> +        if (virAsprintf(&addnhostsfile->hosts[idx].ip, "%s", ipstr)<  0)
> +            goto alloc_error;
> +
> +        addnhostsfile->hosts[idx].nhostnames = 0;
> +        addnhostsfile->nhosts++;
> +    }
> +
> +    if (VIR_REALLOC_N(addnhostsfile->hosts[idx].hostnames, addnhostsfile->hosts[idx].nhostnames + 1)<  0)
> +        goto alloc_error;
> +
> +    if (virAsprintf(&addnhostsfile->hosts[idx].hostnames[addnhostsfile->hosts[idx].nhostnames], "%s", name)<  0)
> +        goto alloc_error;
> +
> +    VIR_FREE(ipstr);
> +
> +    addnhostsfile->hosts[idx].nhostnames++;
> +
> +    return 0;
> +
> + alloc_error:
> +    virReportOOMError();
> +    VIR_FREE(ipstr);
> +    return -1;
> +}
> +
> +static dnsmasqAddnHostsfile *
> +addnhostsNew(const char *name,
> +             const char *config_dir)
> +{
> +    int err;
> +    dnsmasqAddnHostsfile *addnhostsfile;
> +
> +    if (VIR_ALLOC(addnhostsfile)<  0) {
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    addnhostsfile->hosts = NULL;
> +    addnhostsfile->nhosts = 0;
> +
> +    if (virAsprintf(&addnhostsfile->path, "%s/%s.%s", config_dir, name,
> +                    DNSMASQ_ADDNHOSTSFILE_SUFFIX)<  0) {
> +        virReportOOMError();
> +        goto error;
> +    }
> +
> +    if ((err = virFileMakePath(config_dir))) {
> +        virReportSystemError(err, _("cannot create config directory '%s'"),
> +                             config_dir);
> +        goto error;
> +    }
> +
> +    return addnhostsfile;
> +
> + error:
> +    addnhostsFree(addnhostsfile);
> +    return NULL;
> +}
> +
> +static int
> +addnhostsWrite(const char *path,
> +               dnsmasqAddnHost *hosts,
> +               unsigned int nhosts)
> +{
> +    char *tmp;
> +    FILE *f;
> +    bool istmp = true;
> +    unsigned int i, ii;
> +    int rc = 0;
> +
> +    if (nhosts == 0)
> +        return rc;
> +
> +    if (virAsprintf(&tmp, "%s.new", path)<  0)
> +        return -ENOMEM;
> +
> +    if (!(f = fopen(tmp, "w"))) {
> +        istmp = false;
> +        if (!(f = fopen(path, "w"))) {
> +            rc = errno;
> +            goto cleanup;
> +        }
> +    }
> +
> +    for (i = 0; i<  nhosts; i++) {
> +        if (fputs(hosts[i].ip, f) == EOF || fputc('\t', f) == EOF) {
> +            rc = errno;
> +            VIR_FORCE_FCLOSE(f);
> +
> +            if (istmp)
> +                unlink(tmp);
> +
> +            goto cleanup;
> +        }
> +
> +        for (ii = 0; ii<  hosts[i].nhostnames; ii++) {
> +            if (fputs(hosts[i].hostnames[ii], f) == EOF || fputc('\t', f) == EOF) {
> +                rc = errno;
> +                VIR_FORCE_FCLOSE(f);
> +
> +                if (istmp)
> +                    unlink(tmp);
> +
> +                goto cleanup;
> +            }
> +        }
> +
> +        if (fputc('\n', f) == EOF) {
> +            rc = errno;
> +            VIR_FORCE_FCLOSE(f);
> +
> +            if (istmp)
> +                unlink(tmp);
> +
> +            goto cleanup;
> +        }
> +    }
> +
> +    if (VIR_FCLOSE(f) == EOF) {
> +        rc = errno;
> +        goto cleanup;
> +    }
> +
> +    if (istmp) {
> +        if (rename(tmp, path)<  0) {
> +            rc = errno;
> +            unlink(tmp);
> +            goto cleanup;
> +        }
> +
> +        if (unlink(tmp)<  0) {
> +            rc = errno;
> +            goto cleanup;
> +        }
> +    }
> +
> + cleanup:
> +    VIR_FREE(tmp);
> +
> +    return rc;
> +}
> +
> +static int
> +addnhostsSave(dnsmasqAddnHostsfile *addnhostsfile)
> +{
> +    int err = addnhostsWrite(addnhostsfile->path, addnhostsfile->hosts,
> +                             addnhostsfile->nhosts);
> +
> +    if (err<  0) {
> +        virReportSystemError(err, _("cannot write config file '%s'"),
> +                             addnhostsfile->path);
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +static int
> +genericFileDelete(char *path)
> +{
> +    if (!virFileExists(path))
> +        return 0;
> +
> +    if (unlink(path)<  0) {
> +        virReportSystemError(errno, _("cannot remove config file '%s'"),
> +                             path);
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +static void
>   hostsfileFree(dnsmasqHostsfile *hostsfile)
>   {
>       unsigned int i;
> @@ -220,21 +450,6 @@ hostsfileSave(dnsmasqHostsfile *hostsfile)
>       return 0;
>   }
>
> -static int
> -hostsfileDelete(dnsmasqHostsfile *hostsfile)
> -{
> -    if (!virFileExists(hostsfile->path))
> -        return 0;
> -
> -    if (unlink(hostsfile->path)<  0) {
> -        virReportSystemError(errno, _("cannot remove config file '%s'"),
> -                             hostsfile->path);
> -        return -1;
> -    }
> -
> -    return 0;
> -}
> -
>   /**
>    * dnsmasqContextNew:
>    *
> @@ -255,6 +470,8 @@ dnsmasqContextNew(const char *network_name,
>
>       if (!(ctx->hostsfile = hostsfileNew(network_name, config_dir)))
>           goto error;
> +    if (!(ctx->addnhostsfile = addnhostsNew(network_name, config_dir)))
> +        goto error;
>
>       return ctx;
>
> @@ -277,6 +494,8 @@ dnsmasqContextFree(dnsmasqContext *ctx)
>
>       if (ctx->hostsfile)
>           hostsfileFree(ctx->hostsfile);
> +    if (ctx->addnhostsfile)
> +        addnhostsFree(ctx->addnhostsfile);
>
>       VIR_FREE(ctx);
>   }
> @@ -300,6 +519,24 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx,
>           hostsfileAdd(ctx->hostsfile, mac, ip, name);
>   }
>
> +/*
> + * dnsmasqAddHost:
> + * @ctx: pointer to the dnsmasq context for each network
> + * @ip: pointer to the socket address contains ip of the host
> + * @name: pointer to the string contains hostname of the host
> + *
> + * Add additional host entry.
> + */
> +
> +void
> +dnsmasqAddHost(dnsmasqContext *ctx,
> +               virSocketAddr *ip,
> +               const char *name)
> +{
> +    if (ctx->addnhostsfile)
> +        addnhostsAdd(ctx->addnhostsfile, ip, name);
> +}
> +
>   /**
>    * dnsmasqSave:
>    * @ctx: pointer to the dnsmasq context for each network
> @@ -309,10 +546,16 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx,
>   int
>   dnsmasqSave(const dnsmasqContext *ctx)
>   {
> +    int ret = 0;
> +
>       if (ctx->hostsfile)
> -        return hostsfileSave(ctx->hostsfile);
> +        ret = hostsfileSave(ctx->hostsfile);
> +    if (ret == 0) {
> +        if (ctx->addnhostsfile)
> +            ret = addnhostsSave(ctx->addnhostsfile);
> +    }
>
> -    return 0;
> +    return ret;
>   }
>
>
> @@ -325,10 +568,14 @@ dnsmasqSave(const dnsmasqContext *ctx)
>   int
>   dnsmasqDelete(const dnsmasqContext *ctx)
>   {
> +    int ret = 0;
> +
>       if (ctx->hostsfile)
> -        return hostsfileDelete(ctx->hostsfile);
> +        ret = genericFileDelete(ctx->hostsfile->path);
> +    if (ctx->addnhostsfile)
> +        ret = genericFileDelete(ctx->addnhostsfile->path);
>
> -    return 0;
> +    return ret;
>   }
>
>   /**
> diff --git a/src/util/dnsmasq.h b/src/util/dnsmasq.h
> index 02a961f..3f6320a 100644
> --- a/src/util/dnsmasq.h
> +++ b/src/util/dnsmasq.h
> @@ -44,7 +44,24 @@ typedef struct
>
>   typedef struct
>   {
> -    dnsmasqHostsfile *hostsfile;
> +    unsigned int    nhostnames;
> +    char            *ip;
> +    char            **hostnames;

The way you've defined your struct here is how you need to define 
virNetworkDNSHostsDef in the next patch.

> +
> +} dnsmasqAddnHost;
> +
> +typedef struct
> +{
> +    unsigned int     nhosts;
> +    dnsmasqAddnHost *hosts;
> +
> +    char            *path;  /* Absolute path of dnsmasq's hostsfile. */
> +} dnsmasqAddnHostsfile;
> +
> +typedef struct
> +{
> +    dnsmasqHostsfile     *hostsfile;
> +    dnsmasqAddnHostsfile *addnhostsfile;
>   } dnsmasqContext;
>
>   dnsmasqContext * dnsmasqContextNew(const char *network_name,
> @@ -54,6 +71,9 @@ void             dnsmasqAddDhcpHost(dnsmasqContext *ctx,
>                                       const char *mac,
>                                       virSocketAddr *ip,
>                                       const char *name);
> +void             dnsmasqAddHost(dnsmasqContext *ctx,
> +                                virSocketAddr *ip,
> +                                const char *name);
>   int              dnsmasqSave(const dnsmasqContext *ctx);
>   int              dnsmasqDelete(const dnsmasqContext *ctx);
>   int              dnsmasqReload(pid_t pid);

ACK.




More information about the libvir-list mailing list