1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-03-07 17:28:15 +00:00

Convert dhcpStartDhcpDaemon from virRun to virCommand

This is pretty straightforward - even though dnsmasq gets daemonized
and uses a pid file, those things are both handled by the dnsmasq
binary itself. And libvirt doesn't need any of the output of the
dnsmasq command either, so we just setup the args and call
virRun(). Mainly it was just a (mostly) mechanical job of replacing
the APPEND_ARG() macro (and some other *printfs()) with
virCommandAddArg*().
This commit is contained in:
Laine Stump 2010-12-10 13:54:48 -05:00
parent c9006b6b1e
commit 044f2011aa

View File

@ -51,6 +51,7 @@
#include "event.h" #include "event.h"
#include "buf.h" #include "buf.h"
#include "util.h" #include "util.h"
#include "command.h"
#include "memory.h" #include "memory.h"
#include "uuid.h" #include "uuid.h"
#include "iptables.h" #include "iptables.h"
@ -390,25 +391,15 @@ networkSaveDnsmasqHostsfile(virNetworkObjPtr network,
static int static int
networkBuildDnsmasqArgv(virNetworkObjPtr network, networkBuildDnsmasqArgv(virNetworkObjPtr network,
const char *pidfile, const char *pidfile,
const char ***argv) { virCommandPtr cmd) {
int i, len, r; int r, ret = -1;
int nbleases = 0; int nbleases = 0;
char *pidfileArg; char *bridgeaddr;
char buf[1024];
unsigned int ranges;
char *ipAddr;
if (!(bridgeaddr = virSocketFormatAddr(&network->def->ipAddress)))
goto cleanup;
/* /*
* For static-only DHCP, i.e. with no range but at least one host element, * NB, be careful about syntax for dnsmasq options in long format.
* we have to add a special --dhcp-range option to enable the service in
* dnsmasq.
*/
ranges = network->def->nranges;
if (!ranges && network->def->nhosts)
ranges = 1;
/*
* NB, be careful about syntax for dnsmasq options in long format
* *
* If the flag has a mandatory argument, it can be given using * If the flag has a mandatory argument, it can be given using
* either syntax: * either syntax:
@ -422,66 +413,23 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
* --foo=bar * --foo=bar
* *
* It is hard to determine whether a flag is optional or not, * It is hard to determine whether a flag is optional or not,
* without reading the dnsmasq source :-( The manpages is not * without reading the dnsmasq source :-( The manpage is not
* very explicit on this * very explicit on this.
*/ */
len =
1 + /* dnsmasq */
1 + /* --strict-order */
1 + /* --bind-interfaces */
(network->def->domain?2:0) + /* --domain name */
2 + /* --pid-file /var/run/libvirt/network/$NAME.pid */
2 + /* --conf-file "" */
/*2 + *//* --interface virbr0 */
2 + /* --except-interface lo */
2 + /* --listen-address 10.0.0.1 */
(2 * ranges) + /* --dhcp-range 10.0.0.2,10.0.0.254 */
/* --dhcp-lease-max=xxx if needed */
(network->def->nranges ? 1 : 0) +
/* --dhcp-no-override if needed */
(ranges ? 1 : 0) +
/* --dhcp-hostsfile=/var/lib/dnsmasq/$NAME.hostsfile */
(network->def->nhosts > 0 ? 1 : 0) +
/* --enable-tftp --tftp-root /srv/tftp */
(network->def->tftproot ? 3 : 0) +
/* --dhcp-boot pxeboot.img[,,12.34.56.78] */
(network->def->bootfile ? 2 : 0) +
1; /* NULL */
if (VIR_ALLOC_N(*argv, len) < 0)
goto no_memory;
#define APPEND_ARG(v, n, s) do { \
if (!((v)[(n)] = strdup(s))) \
goto no_memory; \
} while (0)
#define APPEND_ARG_LIT(v, n, s) \
(v)[(n)] = s
i = 0;
APPEND_ARG(*argv, i++, DNSMASQ);
/* /*
* Needed to ensure dnsmasq uses same algorithm for processing * Needed to ensure dnsmasq uses same algorithm for processing
* multiple namedriver entries in /etc/resolv.conf as GLibC. * multiple namedriver entries in /etc/resolv.conf as GLibC.
*/ */
APPEND_ARG(*argv, i++, "--strict-order"); virCommandAddArgList(cmd, "--strict-order", "--bind-interfaces", NULL);
APPEND_ARG(*argv, i++, "--bind-interfaces");
if (network->def->domain) { if (network->def->domain)
APPEND_ARG(*argv, i++, "--domain"); virCommandAddArgList(cmd, "--domain", network->def->domain, NULL);
APPEND_ARG(*argv, i++, network->def->domain);
}
if (virAsprintf(&pidfileArg, "--pid-file=%s", pidfile) < 0) virCommandAddArgPair(cmd, "--pid-file", pidfile);
goto no_memory;
APPEND_ARG_LIT(*argv, i++, pidfileArg);
APPEND_ARG(*argv, i++, "--conf-file="); /* *no* conf file */
APPEND_ARG(*argv, i++, ""); virCommandAddArgList(cmd, "--conf-file=", "", NULL);
/* /*
* XXX does not actually work, due to some kind of * XXX does not actually work, due to some kind of
@ -489,166 +437,139 @@ networkBuildDnsmasqArgv(virNetworkObjPtr network,
* interface. A sleep(10) makes it work, but that's * interface. A sleep(10) makes it work, but that's
* clearly not practical * clearly not practical
* *
* APPEND_ARG(*argv, i++, "--interface"); * virCommandAddArg(cmd, "--interface");
* APPEND_ARG(*argv, i++, network->def->bridge); * virCommandAddArg(cmd, network->def->bridge);
*/ */
APPEND_ARG(*argv, i++, "--listen-address"); virCommandAddArgList(cmd,
if (!(ipAddr = virSocketFormatAddr(&network->def->ipAddress))) "--listen-address", bridgeaddr,
goto error; "--except-interface", "lo",
APPEND_ARG_LIT(*argv, i++, ipAddr); NULL);
APPEND_ARG(*argv, i++, "--except-interface");
APPEND_ARG(*argv, i++, "lo");
for (r = 0 ; r < network->def->nranges ; r++) { for (r = 0 ; r < network->def->nranges ; r++) {
char *saddr = virSocketFormatAddr(&network->def->ranges[r].start); char *saddr = virSocketFormatAddr(&network->def->ranges[r].start);
if (!saddr) if (!saddr)
goto error; goto cleanup;
char *eaddr = virSocketFormatAddr(&network->def->ranges[r].end); char *eaddr = virSocketFormatAddr(&network->def->ranges[r].end);
if (!eaddr) { if (!eaddr) {
VIR_FREE(saddr); VIR_FREE(saddr);
goto error; goto cleanup;
} }
char *range; virCommandAddArg(cmd, "--dhcp-range");
int rc = virAsprintf(&range, "%s,%s", saddr, eaddr); virCommandAddArgFormat(cmd, "%s,%s", saddr, eaddr);
VIR_FREE(saddr); VIR_FREE(saddr);
VIR_FREE(eaddr); VIR_FREE(eaddr);
if (rc < 0)
goto no_memory;
APPEND_ARG(*argv, i++, "--dhcp-range");
APPEND_ARG_LIT(*argv, i++, range);
nbleases += virSocketGetRange(&network->def->ranges[r].start, nbleases += virSocketGetRange(&network->def->ranges[r].start,
&network->def->ranges[r].end); &network->def->ranges[r].end);
} }
/*
* For static-only DHCP, i.e. with no range but at least one host element,
* we have to add a special --dhcp-range option to enable the service in
* dnsmasq.
*/
if (!network->def->nranges && network->def->nhosts) { if (!network->def->nranges && network->def->nhosts) {
char *ipaddr = virSocketFormatAddr(&network->def->ipAddress); virCommandAddArg(cmd, "--dhcp-range");
if (!ipaddr) virCommandAddArgFormat(cmd, "%s,static", bridgeaddr);
goto error;
char *range;
int rc = virAsprintf(&range, "%s,static", ipaddr);
VIR_FREE(ipaddr);
if (rc < 0)
goto no_memory;
APPEND_ARG(*argv, i++, "--dhcp-range");
APPEND_ARG_LIT(*argv, i++, range);
} }
if (network->def->nranges > 0) { if (network->def->nranges > 0) {
snprintf(buf, sizeof(buf), "--dhcp-lease-max=%d", nbleases); virCommandAddArgFormat(cmd, "--dhcp-lease-max=%d", nbleases);
APPEND_ARG(*argv, i++, buf);
} }
if (ranges) if (network->def->nranges || network->def->nhosts)
APPEND_ARG(*argv, i++, "--dhcp-no-override"); virCommandAddArg(cmd, "--dhcp-no-override");
if (network->def->nhosts > 0) { if (network->def->nhosts > 0) {
dnsmasqContext *dctx = dnsmasqContextNew(network->def->name, DNSMASQ_STATE_DIR); dnsmasqContext *dctx = dnsmasqContextNew(network->def->name,
char *hostsfileArg; DNSMASQ_STATE_DIR);
if (dctx == NULL) {
if (dctx == NULL) virReportOOMError();
goto no_memory; goto cleanup;
}
if (networkSaveDnsmasqHostsfile(network, dctx, false)) { if (networkSaveDnsmasqHostsfile(network, dctx, false)) {
if (virAsprintf(&hostsfileArg, "--dhcp-hostsfile=%s", dctx->hostsfile->path) < 0) { virCommandAddArgPair(cmd, "--dhcp-hostsfile",
dnsmasqContextFree(dctx); dctx->hostsfile->path);
goto no_memory;
} }
APPEND_ARG_LIT(*argv, i++, hostsfileArg);
}
dnsmasqContextFree(dctx); dnsmasqContextFree(dctx);
} }
if (network->def->tftproot) { if (network->def->tftproot) {
APPEND_ARG(*argv, i++, "--enable-tftp"); virCommandAddArgList(cmd, "--enable-tftp",
APPEND_ARG(*argv, i++, "--tftp-root"); "--tftp-root", network->def->tftproot,
APPEND_ARG(*argv, i++, network->def->tftproot); NULL);
} }
if (network->def->bootfile) { if (network->def->bootfile) {
char *ipaddr = NULL;
virCommandAddArg(cmd, "--dhcp-boot");
if (VIR_SOCKET_HAS_ADDR(&network->def->bootserver)) { if (VIR_SOCKET_HAS_ADDR(&network->def->bootserver)) {
if (!(ipaddr = virSocketFormatAddr(&network->def->bootserver))) char *bootserver = virSocketFormatAddr(&network->def->bootserver);
goto error;
}
char *boot;
int rc = virAsprintf(&boot, "%s%s%s",
network->def->bootfile,
ipaddr ? ",," : "",
ipaddr ? ipaddr : "");
VIR_FREE(ipaddr);
if (rc < 0)
goto no_memory;
APPEND_ARG(*argv, i++, "--dhcp-boot"); if (!bootserver)
APPEND_ARG_LIT(*argv, i++, boot); goto cleanup;
virCommandAddArgFormat(cmd, "%s%s%s",
network->def->bootfile, ",,", bootserver);
VIR_FREE(bootserver);
} else {
virCommandAddArg(cmd, network->def->bootfile);
}
} }
#undef APPEND_ARG ret = 0;
cleanup:
return 0; VIR_FREE(bridgeaddr);
return ret;
no_memory:
virReportOOMError();
error:
if (*argv) {
for (i = 0; (*argv)[i]; i++)
VIR_FREE((*argv)[i]);
VIR_FREE(*argv);
}
return -1;
} }
static int static int
dhcpStartDhcpDaemon(virNetworkObjPtr network) dhcpStartDhcpDaemon(virNetworkObjPtr network)
{ {
const char **argv; virCommandPtr cmd = NULL;
char *pidfile; char *pidfile = NULL;
int ret = -1, i, err; int ret = -1, err;
network->dnsmasqPid = -1; network->dnsmasqPid = -1;
if (!VIR_SOCKET_IS_FAMILY(&network->def->ipAddress, AF_INET)) { if (!VIR_SOCKET_IS_FAMILY(&network->def->ipAddress, AF_INET)) {
networkReportError(VIR_ERR_INTERNAL_ERROR, networkReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot start dhcp daemon without IPv4 address for server")); "%s", _("cannot start dhcp daemon without IPv4 address for server"));
return -1; goto cleanup;
} }
if ((err = virFileMakePath(NETWORK_PID_DIR)) != 0) { if ((err = virFileMakePath(NETWORK_PID_DIR)) != 0) {
virReportSystemError(err, virReportSystemError(err,
_("cannot create directory %s"), _("cannot create directory %s"),
NETWORK_PID_DIR); NETWORK_PID_DIR);
return -1; goto cleanup;
} }
if ((err = virFileMakePath(NETWORK_STATE_DIR)) != 0) { if ((err = virFileMakePath(NETWORK_STATE_DIR)) != 0) {
virReportSystemError(err, virReportSystemError(err,
_("cannot create directory %s"), _("cannot create directory %s"),
NETWORK_STATE_DIR); NETWORK_STATE_DIR);
return -1; goto cleanup;
} }
if (!(pidfile = virFilePid(NETWORK_PID_DIR, network->def->name))) { if (!(pidfile = virFilePid(NETWORK_PID_DIR, network->def->name))) {
virReportOOMError(); virReportOOMError();
return -1; goto cleanup;
} }
argv = NULL; cmd = virCommandNew(DNSMASQ);
if (networkBuildDnsmasqArgv(network, pidfile, &argv) < 0) { if (networkBuildDnsmasqArgv(network, pidfile, cmd) < 0) {
VIR_FREE(pidfile); VIR_FREE(pidfile);
return -1; goto cleanup;
} }
if (virRun(argv, NULL) < 0) if (virCommandRun(cmd, NULL) < 0)
goto cleanup; goto cleanup;
/* /*
* There really is no race here - when dnsmasq daemonizes, * There really is no race here - when dnsmasq daemonizes, its
* its leader process stays around until its child has * leader process stays around until its child has actually
* actually written its pidfile. So by time virRun exits * written its pidfile. So by time virCommandRun exits it has
* it has waitpid'd and guaranteed the proess has started * waitpid'd and guaranteed the proess has started and written a
* and written a pid * pid
*/ */
if (virFileReadPid(NETWORK_PID_DIR, network->def->name, if (virFileReadPid(NETWORK_PID_DIR, network->def->name,
@ -656,13 +577,9 @@ dhcpStartDhcpDaemon(virNetworkObjPtr network)
goto cleanup; goto cleanup;
ret = 0; ret = 0;
cleanup: cleanup:
VIR_FREE(pidfile); VIR_FREE(pidfile);
for (i = 0; argv[i]; i++) virCommandFree(cmd);
VIR_FREE(argv[i]);
VIR_FREE(argv);
return ret; return ret;
} }