提交 97a0aa24 编写于 作者: J Julio Faracco 提交者: Michal Privoznik

conf: Add <lease/> option for <dhcp/> settings

If an user is trying to configure a dhcp neetwork settings, it is not
possible to change the leasetime of a range or a host entry. This is
available using dnsmasq extra options, but they are associated with
dhcp-range or dhcp-hosts fields. This patch implements a leasetime for
range and hosts tags. They can be defined under that settings:

    <dhcp>
      <range ...>
        <lease/>
      </range>
      <host ...>
        <lease/>
      </host>
    </dhcp>

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=913446Signed-off-by: NJulio Faracco <jcfaracco@gmail.com>
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
Reviewed-by: NMichal Privoznik <mprivozn@redhat.com>
上级 5670fb57
...@@ -607,4 +607,12 @@ ...@@ -607,4 +607,12 @@
</element> </element>
</define> </define>
<define name="leaseUnit">
<choice>
<value>seconds</value>
<value>minutes</value>
<value>hours</value>
</choice>
</define>
</grammar> </grammar>
...@@ -371,6 +371,16 @@ ...@@ -371,6 +371,16 @@
<element name="range"> <element name="range">
<attribute name="start"><ref name="ipAddr"/></attribute> <attribute name="start"><ref name="ipAddr"/></attribute>
<attribute name="end"><ref name="ipAddr"/></attribute> <attribute name="end"><ref name="ipAddr"/></attribute>
<interleave>
<optional>
<element name="lease">
<attribute name="expiry"><ref name="unsignedLong"/></attribute>
<optional>
<attribute name="unit"><ref name="leaseUnit"/></attribute>
</optional>
</element>
</optional>
</interleave>
</element> </element>
</zeroOrMore> </zeroOrMore>
<zeroOrMore> <zeroOrMore>
...@@ -388,6 +398,16 @@ ...@@ -388,6 +398,16 @@
<attribute name="name"><text/></attribute> <attribute name="name"><text/></attribute>
</choice> </choice>
<attribute name="ip"><ref name="ipAddr"/></attribute> <attribute name="ip"><ref name="ipAddr"/></attribute>
<interleave>
<optional>
<element name="lease">
<attribute name="expiry"><ref name="unsignedLong"/></attribute>
<optional>
<attribute name="unit"><ref name="leaseUnit"/></attribute>
</optional>
</element>
</optional>
</interleave>
</element> </element>
</zeroOrMore> </zeroOrMore>
<optional> <optional>
......
...@@ -70,6 +70,13 @@ VIR_ENUM_IMPL(virNetworkTaint, ...@@ -70,6 +70,13 @@ VIR_ENUM_IMPL(virNetworkTaint,
"hook-script", "hook-script",
); );
VIR_ENUM_IMPL(virNetworkDHCPLeaseTimeUnit,
VIR_NETWORK_DHCP_LEASETIME_UNIT_LAST,
"seconds",
"minutes",
"hours",
);
static virClassPtr virNetworkXMLOptionClass; static virClassPtr virNetworkXMLOptionClass;
static void static void
...@@ -132,12 +139,20 @@ virNetworkForwardPfDefClear(virNetworkForwardPfDefPtr def) ...@@ -132,12 +139,20 @@ virNetworkForwardPfDefClear(virNetworkForwardPfDefPtr def)
} }
static void
virNetworkDHCPLeaseTimeDefClear(virNetworkDHCPLeaseTimeDefPtr lease)
{
VIR_FREE(lease);
}
static void static void
virNetworkDHCPHostDefClear(virNetworkDHCPHostDefPtr def) virNetworkDHCPHostDefClear(virNetworkDHCPHostDefPtr def)
{ {
VIR_FREE(def->mac); VIR_FREE(def->mac);
VIR_FREE(def->id); VIR_FREE(def->id);
VIR_FREE(def->name); VIR_FREE(def->name);
VIR_FREE(def->lease);
} }
...@@ -145,6 +160,9 @@ static void ...@@ -145,6 +160,9 @@ static void
virNetworkIPDefClear(virNetworkIPDefPtr def) virNetworkIPDefClear(virNetworkIPDefPtr def)
{ {
VIR_FREE(def->family); VIR_FREE(def->family);
while (def->nranges)
virNetworkDHCPLeaseTimeDefClear(def->ranges[--def->nranges].lease);
VIR_FREE(def->ranges); VIR_FREE(def->ranges);
while (def->nhosts) while (def->nhosts)
...@@ -391,11 +409,62 @@ int virNetworkIPDefNetmask(const virNetworkIPDef *def, ...@@ -391,11 +409,62 @@ int virNetworkIPDefNetmask(const virNetworkIPDef *def,
static int static int
virSocketAddrRangeParseXML(const char *networkName, virNetworkDHCPLeaseTimeDefParseXML(virNetworkDHCPLeaseTimeDefPtr *lease,
virNetworkIPDefPtr ipdef, xmlNodePtr node)
xmlNodePtr node,
virSocketAddrRangePtr range)
{ {
virNetworkDHCPLeaseTimeDefPtr new_lease = *lease;
g_autofree char *expiry = NULL;
g_autofree char *unit = NULL;
int unitInt;
if (!(expiry = virXMLPropString(node, "expiry")))
return 0;
if (VIR_ALLOC(new_lease) < 0)
return -1;
new_lease->unit = VIR_NETWORK_DHCP_LEASETIME_UNIT_MINUTES;
if (virStrToLong_ul(expiry, NULL, 10, &new_lease->expiry) < 0)
return -1;
if ((unit = virXMLPropString(node, "unit"))) {
if ((unitInt = virNetworkDHCPLeaseTimeUnitTypeFromString(unit)) < 0) {
virReportError(VIR_ERR_XML_ERROR,
_("Invalid unit: %s"), unit);
return -1;
}
new_lease->unit = unitInt;
}
/* infinite */
if (new_lease->expiry > 0) {
/* This boundary check is related to dnsmasq man page settings:
* "The minimum lease time is two minutes." */
if ((new_lease->unit == VIR_NETWORK_DHCP_LEASETIME_UNIT_SECONDS &&
new_lease->expiry < 120) ||
(new_lease->unit == VIR_NETWORK_DHCP_LEASETIME_UNIT_MINUTES &&
new_lease->expiry < 2)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("The minimum lease time should be greater "
"than 2 minutes"));
return -1;
}
}
*lease = new_lease;
return 0;
}
static int
virNetworkDHCPRangeDefParseXML(const char *networkName,
virNetworkIPDefPtr ipdef,
xmlNodePtr node,
virNetworkDHCPRangeDefPtr range)
{
virSocketAddrRangePtr addr = &range->addr;
xmlNodePtr cur = node->children;
char *start = NULL, *end = NULL; char *start = NULL, *end = NULL;
int ret = -1; int ret = -1;
...@@ -405,7 +474,7 @@ virSocketAddrRangeParseXML(const char *networkName, ...@@ -405,7 +474,7 @@ virSocketAddrRangeParseXML(const char *networkName,
networkName); networkName);
goto cleanup; goto cleanup;
} }
if (virSocketAddrParse(&range->start, start, AF_UNSPEC) < 0) if (virSocketAddrParse(&addr->start, start, AF_UNSPEC) < 0)
goto cleanup; goto cleanup;
if (!(end = virXMLPropString(node, "end"))) { if (!(end = virXMLPropString(node, "end"))) {
...@@ -414,14 +483,24 @@ virSocketAddrRangeParseXML(const char *networkName, ...@@ -414,14 +483,24 @@ virSocketAddrRangeParseXML(const char *networkName,
networkName); networkName);
goto cleanup; goto cleanup;
} }
if (virSocketAddrParse(&range->end, end, AF_UNSPEC) < 0) if (virSocketAddrParse(&addr->end, end, AF_UNSPEC) < 0)
goto cleanup; goto cleanup;
/* do a sanity check of the range */ /* do a sanity check of the range */
if (virSocketAddrGetRange(&range->start, &range->end, &ipdef->address, if (virSocketAddrGetRange(&addr->start, &addr->end, &ipdef->address,
virNetworkIPDefPrefix(ipdef)) < 0) virNetworkIPDefPrefix(ipdef)) < 0)
goto cleanup; goto cleanup;
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE &&
virXMLNodeNameEqual(cur, "lease")) {
if (virNetworkDHCPLeaseTimeDefParseXML(&range->lease, cur) < 0)
goto cleanup;
}
cur = cur->next;
}
ret = 0; ret = 0;
cleanup: cleanup:
...@@ -441,6 +520,7 @@ virNetworkDHCPHostDefParseXML(const char *networkName, ...@@ -441,6 +520,7 @@ virNetworkDHCPHostDefParseXML(const char *networkName,
char *mac = NULL, *name = NULL, *ip = NULL, *id = NULL; char *mac = NULL, *name = NULL, *ip = NULL, *id = NULL;
virMacAddr addr; virMacAddr addr;
virSocketAddr inaddr; virSocketAddr inaddr;
xmlNodePtr cur = node->children;
int ret = -1; int ret = -1;
mac = virXMLPropString(node, "mac"); mac = virXMLPropString(node, "mac");
...@@ -533,6 +613,16 @@ virNetworkDHCPHostDefParseXML(const char *networkName, ...@@ -533,6 +613,16 @@ virNetworkDHCPHostDefParseXML(const char *networkName,
} }
} }
while (cur != NULL) {
if (cur->type == XML_ELEMENT_NODE &&
virXMLNodeNameEqual(cur, "lease")) {
if (virNetworkDHCPLeaseTimeDefParseXML(&host->lease, cur) < 0)
goto cleanup;
}
cur = cur->next;
}
host->mac = mac; host->mac = mac;
mac = NULL; mac = NULL;
host->id = id; host->id = id;
...@@ -559,7 +649,7 @@ virNetworkDHCPDefParseXML(const char *networkName, ...@@ -559,7 +649,7 @@ virNetworkDHCPDefParseXML(const char *networkName,
{ {
int ret = -1; int ret = -1;
xmlNodePtr cur; xmlNodePtr cur;
virSocketAddrRange range; virNetworkDHCPRangeDef range;
virNetworkDHCPHostDef host; virNetworkDHCPHostDef host;
memset(&range, 0, sizeof(range)); memset(&range, 0, sizeof(range));
...@@ -570,7 +660,7 @@ virNetworkDHCPDefParseXML(const char *networkName, ...@@ -570,7 +660,7 @@ virNetworkDHCPDefParseXML(const char *networkName,
if (cur->type == XML_ELEMENT_NODE && if (cur->type == XML_ELEMENT_NODE &&
virXMLNodeNameEqual(cur, "range")) { virXMLNodeNameEqual(cur, "range")) {
if (virSocketAddrRangeParseXML(networkName, def, cur, &range) < 0) if (virNetworkDHCPRangeDefParseXML(networkName, def, cur, &range) < 0)
goto cleanup; goto cleanup;
if (VIR_APPEND_ELEMENT(def->ranges, def->nranges, range) < 0) if (VIR_APPEND_ELEMENT(def->ranges, def->nranges, range) < 0)
goto cleanup; goto cleanup;
...@@ -583,7 +673,6 @@ virNetworkDHCPDefParseXML(const char *networkName, ...@@ -583,7 +673,6 @@ virNetworkDHCPDefParseXML(const char *networkName,
goto cleanup; goto cleanup;
if (VIR_APPEND_ELEMENT(def->hosts, def->nhosts, host) < 0) if (VIR_APPEND_ELEMENT(def->hosts, def->nhosts, host) < 0)
goto cleanup; goto cleanup;
} else if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) && } else if (VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) &&
cur->type == XML_ELEMENT_NODE && cur->type == XML_ELEMENT_NODE &&
virXMLNodeNameEqual(cur, "bootp")) { virXMLNodeNameEqual(cur, "bootp")) {
...@@ -2300,20 +2389,39 @@ virNetworkIPDefFormat(virBufferPtr buf, ...@@ -2300,20 +2389,39 @@ virNetworkIPDefFormat(virBufferPtr buf,
virBufferAdjustIndent(buf, 2); virBufferAdjustIndent(buf, 2);
for (i = 0; i < def->nranges; i++) { for (i = 0; i < def->nranges; i++) {
char *saddr = virSocketAddrFormat(&def->ranges[i].start); virSocketAddrRange addr = def->ranges[i].addr;
virNetworkDHCPLeaseTimeDefPtr lease = def->ranges[i].lease;
char *saddr = virSocketAddrFormat(&addr.start);
if (!saddr) if (!saddr)
return -1; return -1;
char *eaddr = virSocketAddrFormat(&def->ranges[i].end); char *eaddr = virSocketAddrFormat(&addr.end);
if (!eaddr) { if (!eaddr) {
VIR_FREE(saddr); VIR_FREE(saddr);
return -1; return -1;
} }
virBufferAsprintf(buf, "<range start='%s' end='%s'/>\n", virBufferAsprintf(buf, "<range start='%s' end='%s'",
saddr, eaddr); saddr, eaddr);
if (lease) {
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
if (!lease->expiry) {
virBufferAddLit(buf, "<lease expiry='0'/>\n");
} else {
virBufferAsprintf(buf, "<lease expiry='%lu' unit='%s'/>\n",
lease->expiry,
virNetworkDHCPLeaseTimeUnitTypeToString(lease->unit));
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</range>\n");
} else {
virBufferAddLit(buf, "/>\n");
}
VIR_FREE(saddr); VIR_FREE(saddr);
VIR_FREE(eaddr); VIR_FREE(eaddr);
} }
for (i = 0; i < def->nhosts; i++) { for (i = 0; i < def->nhosts; i++) {
virNetworkDHCPLeaseTimeDefPtr lease = def->hosts[i].lease;
virBufferAddLit(buf, "<host"); virBufferAddLit(buf, "<host");
if (def->hosts[i].mac) if (def->hosts[i].mac)
virBufferAsprintf(buf, " mac='%s'", def->hosts[i].mac); virBufferAsprintf(buf, " mac='%s'", def->hosts[i].mac);
...@@ -2328,7 +2436,21 @@ virNetworkIPDefFormat(virBufferPtr buf, ...@@ -2328,7 +2436,21 @@ virNetworkIPDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " ip='%s'", ipaddr); virBufferAsprintf(buf, " ip='%s'", ipaddr);
VIR_FREE(ipaddr); VIR_FREE(ipaddr);
} }
virBufferAddLit(buf, "/>\n"); if (lease) {
virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2);
if (!lease->expiry) {
virBufferAddLit(buf, "<lease expiry='0'/>\n");
} else {
virBufferAsprintf(buf, "<lease expiry='%lu' unit='%s'/>\n",
lease->expiry,
virNetworkDHCPLeaseTimeUnitTypeToString(lease->unit));
}
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</host>\n");
} else {
virBufferAddLit(buf, "/>\n");
}
} }
if (def->bootfile) { if (def->bootfile) {
virBufferEscapeString(buf, "<bootp file='%s'", virBufferEscapeString(buf, "<bootp file='%s'",
...@@ -2343,7 +2465,6 @@ virNetworkIPDefFormat(virBufferPtr buf, ...@@ -2343,7 +2465,6 @@ virNetworkIPDefFormat(virBufferPtr buf,
virBufferAddLit(buf, "/>\n"); virBufferAddLit(buf, "/>\n");
} }
virBufferAdjustIndent(buf, -2); virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</dhcp>\n"); virBufferAddLit(buf, "</dhcp>\n");
} }
...@@ -3080,7 +3201,7 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def, ...@@ -3080,7 +3201,7 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
{ {
size_t i; size_t i;
virNetworkIPDefPtr ipdef = virNetworkIPDefByIndex(def, parentIndex); virNetworkIPDefPtr ipdef = virNetworkIPDefByIndex(def, parentIndex);
virSocketAddrRange range; virNetworkDHCPRangeDef range;
memset(&range, 0, sizeof(range)); memset(&range, 0, sizeof(range));
...@@ -3100,11 +3221,11 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def, ...@@ -3100,11 +3221,11 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
return -1; return -1;
} }
if (virSocketAddrRangeParseXML(def->name, ipdef, ctxt->node, &range) < 0) if (virNetworkDHCPRangeDefParseXML(def->name, ipdef, ctxt->node, &range) < 0)
return -1; return -1;
if (VIR_SOCKET_ADDR_FAMILY(&ipdef->address) if (VIR_SOCKET_ADDR_FAMILY(&ipdef->address)
!= VIR_SOCKET_ADDR_FAMILY(&range.start)) { != VIR_SOCKET_ADDR_FAMILY(&range.addr.start)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s", virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("the address family of a dhcp range must match " _("the address family of a dhcp range must match "
"the address family of the dhcp element's parent")); "the address family of the dhcp element's parent"));
...@@ -3113,8 +3234,9 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def, ...@@ -3113,8 +3234,9 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
/* check if an entry with same name/address/ip already exists */ /* check if an entry with same name/address/ip already exists */
for (i = 0; i < ipdef->nranges; i++) { for (i = 0; i < ipdef->nranges; i++) {
if (virSocketAddrEqual(&range.start, &ipdef->ranges[i].start) && virSocketAddrRange addr = ipdef->ranges[i].addr;
virSocketAddrEqual(&range.end, &ipdef->ranges[i].end)) { if (virSocketAddrEqual(&range.addr.start, &addr.start) &&
virSocketAddrEqual(&range.addr.end, &addr.end)) {
break; break;
} }
} }
...@@ -3126,8 +3248,8 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def, ...@@ -3126,8 +3248,8 @@ virNetworkDefUpdateIPDHCPRange(virNetworkDefPtr def,
return -1; return -1;
if (i < ipdef->nranges) { if (i < ipdef->nranges) {
char *startip = virSocketAddrFormat(&range.start); char *startip = virSocketAddrFormat(&range.addr.start);
char *endip = virSocketAddrFormat(&range.end); char *endip = virSocketAddrFormat(&range.addr.end);
virReportError(VIR_ERR_OPERATION_INVALID, virReportError(VIR_ERR_OPERATION_INVALID,
_("there is an existing dhcp range entry in " _("there is an existing dhcp range entry in "
......
...@@ -80,6 +80,16 @@ typedef enum { ...@@ -80,6 +80,16 @@ typedef enum {
VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST, VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST,
} virNetworkForwardHostdevDeviceType; } virNetworkForwardHostdevDeviceType;
typedef enum {
VIR_NETWORK_DHCP_LEASETIME_UNIT_SECONDS = 0,
VIR_NETWORK_DHCP_LEASETIME_UNIT_MINUTES,
VIR_NETWORK_DHCP_LEASETIME_UNIT_HOURS,
VIR_NETWORK_DHCP_LEASETIME_UNIT_LAST,
} virNetworkDHCPLeaseTimeUnitType;
VIR_ENUM_DECL(virNetworkDHCPLeaseTimeUnit);
/* The backend driver used for devices from the pool. Currently used /* The backend driver used for devices from the pool. Currently used
* only for PCI devices (vfio vs. kvm), but could be used for other * only for PCI devices (vfio vs. kvm), but could be used for other
* device types in the future. * device types in the future.
...@@ -94,6 +104,20 @@ typedef enum { ...@@ -94,6 +104,20 @@ typedef enum {
VIR_ENUM_DECL(virNetworkForwardDriverName); VIR_ENUM_DECL(virNetworkForwardDriverName);
typedef struct _virNetworkDHCPLeaseTimeDef virNetworkDHCPLeaseTimeDef;
typedef virNetworkDHCPLeaseTimeDef *virNetworkDHCPLeaseTimeDefPtr;
struct _virNetworkDHCPLeaseTimeDef {
unsigned long expiry;
virNetworkDHCPLeaseTimeUnitType unit;
};
typedef struct _virNetworkDHCPRangeDef virNetworkDHCPRangeDef;
typedef virNetworkDHCPRangeDef *virNetworkDHCPRangeDefPtr;
struct _virNetworkDHCPRangeDef {
virSocketAddrRange addr;
virNetworkDHCPLeaseTimeDefPtr lease;
};
typedef struct _virNetworkDHCPHostDef virNetworkDHCPHostDef; typedef struct _virNetworkDHCPHostDef virNetworkDHCPHostDef;
typedef virNetworkDHCPHostDef *virNetworkDHCPHostDefPtr; typedef virNetworkDHCPHostDef *virNetworkDHCPHostDefPtr;
struct _virNetworkDHCPHostDef { struct _virNetworkDHCPHostDef {
...@@ -101,6 +125,7 @@ struct _virNetworkDHCPHostDef { ...@@ -101,6 +125,7 @@ struct _virNetworkDHCPHostDef {
char *id; char *id;
char *name; char *name;
virSocketAddr ip; virSocketAddr ip;
virNetworkDHCPLeaseTimeDefPtr lease;
}; };
typedef struct _virNetworkDNSTxtDef virNetworkDNSTxtDef; typedef struct _virNetworkDNSTxtDef virNetworkDNSTxtDef;
...@@ -171,7 +196,7 @@ struct _virNetworkIPDef { ...@@ -171,7 +196,7 @@ struct _virNetworkIPDef {
int localPTR; /* virTristateBool */ int localPTR; /* virTristateBool */
size_t nranges; /* Zero or more dhcp ranges */ size_t nranges; /* Zero or more dhcp ranges */
virSocketAddrRangePtr ranges; virNetworkDHCPRangeDefPtr ranges;
size_t nhosts; /* Zero or more dhcp hosts */ size_t nhosts; /* Zero or more dhcp hosts */
virNetworkDHCPHostDefPtr hosts; virNetworkDHCPHostDefPtr hosts;
......
...@@ -772,6 +772,8 @@ virNetworkDefParseNode; ...@@ -772,6 +772,8 @@ virNetworkDefParseNode;
virNetworkDefParseString; virNetworkDefParseString;
virNetworkDefParseXML; virNetworkDefParseXML;
virNetworkDefUpdateSection; virNetworkDefUpdateSection;
virNetworkDHCPLeaseTimeUnitTypeFromString;
virNetworkDHCPLeaseTimeUnitTypeToString;
virNetworkForwardTypeToString; virNetworkForwardTypeToString;
virNetworkIPDefNetmask; virNetworkIPDefNetmask;
virNetworkIPDefPrefix; virNetworkIPDefPrefix;
...@@ -1950,6 +1952,7 @@ dnsmasqCapsRefresh; ...@@ -1950,6 +1952,7 @@ dnsmasqCapsRefresh;
dnsmasqContextFree; dnsmasqContextFree;
dnsmasqContextNew; dnsmasqContextNew;
dnsmasqDelete; dnsmasqDelete;
dnsmasqDhcpHostsToString;
dnsmasqReload; dnsmasqReload;
dnsmasqSave; dnsmasqSave;
......
...@@ -966,6 +966,30 @@ static int networkConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED) ...@@ -966,6 +966,30 @@ static int networkConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)
} }
static char *
networkBuildDnsmasqLeaseTime(virNetworkDHCPLeaseTimeDefPtr lease)
{
char *leasetime = NULL;
const char *unit;
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
if (!lease)
return NULL;
if (lease->expiry == 0) {
virBufferAddLit(&buf, "infinite");
} else {
unit = virNetworkDHCPLeaseTimeUnitTypeToString(lease->unit);
/* We get only first compatible char from string: 's', 'm' or 'h' */
virBufferAsprintf(&buf, "%lu%c", lease->expiry, unit[0]);
}
leasetime = virBufferContentAndReset(&buf);
return leasetime;
}
/* the following does not build a file, it builds a list /* the following does not build a file, it builds a list
* which is later saved into a file * which is later saved into a file
*/ */
...@@ -975,14 +999,18 @@ networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx, ...@@ -975,14 +999,18 @@ networkBuildDnsmasqDhcpHostsList(dnsmasqContext *dctx,
{ {
size_t i; size_t i;
bool ipv6 = false; bool ipv6 = false;
g_autofree char *leasetime = NULL;
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6))
ipv6 = true; ipv6 = true;
for (i = 0; i < ipdef->nhosts; i++) { for (i = 0; i < ipdef->nhosts; i++) {
virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]); virNetworkDHCPHostDefPtr host = &(ipdef->hosts[i]);
leasetime = networkBuildDnsmasqLeaseTime(host->lease);
if (VIR_SOCKET_ADDR_VALID(&host->ip)) if (VIR_SOCKET_ADDR_VALID(&host->ip))
if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip, if (dnsmasqAddDhcpHost(dctx, host->mac, &host->ip,
host->name, host->id, ipv6) < 0) host->name, host->id, leasetime,
ipv6) < 0)
return -1; return -1;
} }
...@@ -1052,6 +1080,7 @@ int ...@@ -1052,6 +1080,7 @@ int
networkDnsmasqConfContents(virNetworkObjPtr obj, networkDnsmasqConfContents(virNetworkObjPtr obj,
const char *pidfile, const char *pidfile,
char **configstr, char **configstr,
char **hostsfilestr,
dnsmasqContext *dctx, dnsmasqContext *dctx,
dnsmasqCapsPtr caps G_GNUC_UNUSED) dnsmasqCapsPtr caps G_GNUC_UNUSED)
{ {
...@@ -1381,13 +1410,15 @@ networkDnsmasqConfContents(virNetworkObjPtr obj, ...@@ -1381,13 +1410,15 @@ networkDnsmasqConfContents(virNetworkObjPtr obj,
} }
for (r = 0; r < ipdef->nranges; r++) { for (r = 0; r < ipdef->nranges; r++) {
int thisRange; int thisRange;
virNetworkDHCPRangeDef range = ipdef->ranges[r];
g_autofree char *leasetime = NULL;
if (!(saddr = virSocketAddrFormat(&ipdef->ranges[r].start)) || if (!(saddr = virSocketAddrFormat(&range.addr.start)) ||
!(eaddr = virSocketAddrFormat(&ipdef->ranges[r].end))) !(eaddr = virSocketAddrFormat(&range.addr.end)))
goto cleanup; goto cleanup;
if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) { if (VIR_SOCKET_ADDR_IS_FAMILY(&ipdef->address, AF_INET6)) {
virBufferAsprintf(&configbuf, "dhcp-range=%s,%s,%d\n", virBufferAsprintf(&configbuf, "dhcp-range=%s,%s,%d",
saddr, eaddr, prefix); saddr, eaddr, prefix);
} else { } else {
/* IPv4 - dnsmasq requires a netmask rather than prefix */ /* IPv4 - dnsmasq requires a netmask rather than prefix */
...@@ -1404,14 +1435,19 @@ networkDnsmasqConfContents(virNetworkObjPtr obj, ...@@ -1404,14 +1435,19 @@ networkDnsmasqConfContents(virNetworkObjPtr obj,
if (!(netmaskStr = virSocketAddrFormat(&netmask))) if (!(netmaskStr = virSocketAddrFormat(&netmask)))
goto cleanup; goto cleanup;
virBufferAsprintf(&configbuf, "dhcp-range=%s,%s,%s\n", virBufferAsprintf(&configbuf, "dhcp-range=%s,%s,%s",
saddr, eaddr, netmaskStr); saddr, eaddr, netmaskStr);
} }
if ((leasetime = networkBuildDnsmasqLeaseTime(range.lease)))
virBufferAsprintf(&configbuf, ",%s", leasetime);
virBufferAddLit(&configbuf, "\n");
VIR_FREE(saddr); VIR_FREE(saddr);
VIR_FREE(eaddr); VIR_FREE(eaddr);
thisRange = virSocketAddrGetRange(&ipdef->ranges[r].start, thisRange = virSocketAddrGetRange(&range.addr.start,
&ipdef->ranges[r].end, &range.addr.end,
&ipdef->address, &ipdef->address,
virNetworkIPDefPrefix(ipdef)); virNetworkIPDefPrefix(ipdef));
if (thisRange < 0) if (thisRange < 0)
...@@ -1525,6 +1561,9 @@ networkDnsmasqConfContents(virNetworkObjPtr obj, ...@@ -1525,6 +1561,9 @@ networkDnsmasqConfContents(virNetworkObjPtr obj,
if (!(*configstr = virBufferContentAndReset(&configbuf))) if (!(*configstr = virBufferContentAndReset(&configbuf)))
goto cleanup; goto cleanup;
*hostsfilestr = dnsmasqDhcpHostsToString(dctx->hostsfile->hosts,
dctx->hostsfile->nhosts);
ret = 0; ret = 0;
cleanup: cleanup:
...@@ -1549,11 +1588,12 @@ networkBuildDhcpDaemonCommandLine(virNetworkDriverStatePtr driver, ...@@ -1549,11 +1588,12 @@ networkBuildDhcpDaemonCommandLine(virNetworkDriverStatePtr driver,
int ret = -1; int ret = -1;
char *configfile = NULL; char *configfile = NULL;
char *configstr = NULL; char *configstr = NULL;
char *hostsfilestr = NULL;
char *leaseshelper_path = NULL; char *leaseshelper_path = NULL;
virNetworkObjSetDnsmasqPid(obj, -1); virNetworkObjSetDnsmasqPid(obj, -1);
if (networkDnsmasqConfContents(obj, pidfile, &configstr, if (networkDnsmasqConfContents(obj, pidfile, &configstr, &hostsfilestr,
dctx, dnsmasq_caps) < 0) dctx, dnsmasq_caps) < 0)
goto cleanup; goto cleanup;
if (!configstr) if (!configstr)
......
...@@ -46,5 +46,6 @@ int ...@@ -46,5 +46,6 @@ int
networkDnsmasqConfContents(virNetworkObjPtr obj, networkDnsmasqConfContents(virNetworkObjPtr obj,
const char *pidfile, const char *pidfile,
char **configstr, char **configstr,
char **hostsfilestr,
dnsmasqContext *dctx, dnsmasqContext *dctx,
dnsmasqCapsPtr caps); dnsmasqCapsPtr caps);
...@@ -5025,7 +5025,7 @@ testDomainInterfaceAddressFromNet(testDriverPtr driver, ...@@ -5025,7 +5025,7 @@ testDomainInterfaceAddressFromNet(testDriverPtr driver,
net_def->ips->prefix); net_def->ips->prefix);
if (net_def->ips->nranges > 0) if (net_def->ips->nranges > 0)
addr = net_def->ips->ranges[0].start; addr = net_def->ips->ranges[0].addr.start;
else else
addr = net_def->ips->address; addr = net_def->ips->address;
......
...@@ -296,11 +296,14 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile, ...@@ -296,11 +296,14 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile,
virSocketAddr *ip, virSocketAddr *ip,
const char *name, const char *name,
const char *id, const char *id,
const char *leasetime,
bool ipv6) bool ipv6)
{ {
char *ipstr = NULL; g_autofree char *ipstr = NULL;
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
if (VIR_REALLOC_N(hostsfile->hosts, hostsfile->nhosts + 1) < 0) if (VIR_REALLOC_N(hostsfile->hosts, hostsfile->nhosts + 1) < 0)
goto error; return -1;
if (!(ipstr = virSocketAddrFormat(ip))) if (!(ipstr = virSocketAddrFormat(ip)))
return -1; return -1;
...@@ -308,34 +311,30 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile, ...@@ -308,34 +311,30 @@ hostsfileAdd(dnsmasqHostsfile *hostsfile,
/* the first test determines if it is a dhcpv6 host */ /* the first test determines if it is a dhcpv6 host */
if (ipv6) { if (ipv6) {
if (name && id) { if (name && id) {
hostsfile->hosts[hostsfile->nhosts].host = g_strdup_printf("id:%s,%s,[%s]", virBufferAsprintf(&buf, "id:%s,%s", id, name);
id, name, ipstr);
} else if (name && !id) { } else if (name && !id) {
hostsfile->hosts[hostsfile->nhosts].host = g_strdup_printf("%s,[%s]", virBufferAsprintf(&buf, "%s", name);
name, ipstr);
} else if (!name && id) { } else if (!name && id) {
hostsfile->hosts[hostsfile->nhosts].host = g_strdup_printf("id:%s,[%s]", virBufferAsprintf(&buf, "id:%s", id);
id, ipstr);
} }
virBufferAsprintf(&buf, ",[%s]", ipstr);
} else if (name && mac) { } else if (name && mac) {
hostsfile->hosts[hostsfile->nhosts].host = g_strdup_printf("%s,%s,%s", virBufferAsprintf(&buf, "%s,%s,%s", mac, ipstr, name);
mac, ipstr, name);
} else if (name && !mac) { } else if (name && !mac) {
hostsfile->hosts[hostsfile->nhosts].host = g_strdup_printf("%s,%s", name, virBufferAsprintf(&buf, "%s,%s", name, ipstr);
ipstr);
} else { } else {
hostsfile->hosts[hostsfile->nhosts].host = g_strdup_printf("%s,%s", mac, virBufferAsprintf(&buf, "%s,%s", mac, ipstr);
ipstr);
} }
VIR_FREE(ipstr);
if (leasetime)
virBufferAsprintf(&buf, ",%s", leasetime);
if (!(hostsfile->hosts[hostsfile->nhosts].host = virBufferContentAndReset(&buf)))
return -1;
hostsfile->nhosts++; hostsfile->nhosts++;
return 0; return 0;
error:
VIR_FREE(ipstr);
return -1;
} }
static dnsmasqHostsfile * static dnsmasqHostsfile *
...@@ -501,9 +500,10 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx, ...@@ -501,9 +500,10 @@ dnsmasqAddDhcpHost(dnsmasqContext *ctx,
virSocketAddr *ip, virSocketAddr *ip,
const char *name, const char *name,
const char *id, const char *id,
const char *leasetime,
bool ipv6) bool ipv6)
{ {
return hostsfileAdd(ctx->hostsfile, mac, ip, name, id, ipv6); return hostsfileAdd(ctx->hostsfile, mac, ip, name, id, leasetime, ipv6);
} }
/* /*
...@@ -862,3 +862,23 @@ dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag) ...@@ -862,3 +862,23 @@ dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag)
{ {
return caps && virBitmapIsBitSet(caps->flags, flag); return caps && virBitmapIsBitSet(caps->flags, flag);
} }
/** dnsmasqDhcpHostsToString:
*
* Turns a vector of dnsmasqDhcpHost into the string that is ought to be
* stored in the hostsfile, this functionality is split to make hostsfiles
* testable. Returs NULL if nhosts is 0.
*/
char *
dnsmasqDhcpHostsToString(dnsmasqDhcpHost *hosts,
unsigned int nhosts)
{
size_t i;
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
for (i = 0; i < nhosts; i++)
virBufferAsprintf(&buf, "%s\n", hosts[i].host);
return virBufferContentAndReset(&buf);
}
...@@ -87,6 +87,7 @@ int dnsmasqAddDhcpHost(dnsmasqContext *ctx, ...@@ -87,6 +87,7 @@ int dnsmasqAddDhcpHost(dnsmasqContext *ctx,
virSocketAddr *ip, virSocketAddr *ip,
const char *name, const char *name,
const char *id, const char *id,
const char *leasetime,
bool ipv6); bool ipv6);
int dnsmasqAddHost(dnsmasqContext *ctx, int dnsmasqAddHost(dnsmasqContext *ctx,
virSocketAddr *ip, virSocketAddr *ip,
...@@ -104,6 +105,8 @@ int dnsmasqCapsRefresh(dnsmasqCapsPtr *caps, const char *binaryPath); ...@@ -104,6 +105,8 @@ int dnsmasqCapsRefresh(dnsmasqCapsPtr *caps, const char *binaryPath);
bool dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag); bool dnsmasqCapsGet(dnsmasqCapsPtr caps, dnsmasqCapsFlags flag);
const char *dnsmasqCapsGetBinaryPath(dnsmasqCapsPtr caps); const char *dnsmasqCapsGetBinaryPath(dnsmasqCapsPtr caps);
unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps); unsigned long dnsmasqCapsGetVersion(dnsmasqCapsPtr caps);
char *dnsmasqDhcpHostsToString(dnsmasqDhcpHost *hosts,
unsigned int nhosts);
#define DNSMASQ_DHCPv6_MAJOR_REQD 2 #define DNSMASQ_DHCPv6_MAJOR_REQD 2
#define DNSMASQ_DHCPv6_MINOR_REQD 64 #define DNSMASQ_DHCPv6_MINOR_REQD 64
......
...@@ -379,6 +379,7 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const char *xml, bool start) ...@@ -379,6 +379,7 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const char *xml, bool start)
virNetworkIPDefPtr ipdef = NULL; virNetworkIPDefPtr ipdef = NULL;
unsigned char uuid[VIR_UUID_BUFLEN]; unsigned char uuid[VIR_UUID_BUFLEN];
vboxIID vboxnetiid; vboxIID vboxnetiid;
virSocketAddrRange addr;
virSocketAddr netmask; virSocketAddr netmask;
IHost *host = NULL; IHost *host = NULL;
virNetworkPtr ret = NULL; virNetworkPtr ret = NULL;
...@@ -440,9 +441,10 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const char *xml, bool start) ...@@ -440,9 +441,10 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const char *xml, bool start)
/* Currently support only one dhcp server per network /* Currently support only one dhcp server per network
* with contigious address space from start to end * with contigious address space from start to end
*/ */
addr = ipdef->ranges[0].addr;
if ((ipdef->nranges >= 1) && if ((ipdef->nranges >= 1) &&
VIR_SOCKET_ADDR_VALID(&ipdef->ranges[0].start) && VIR_SOCKET_ADDR_VALID(&addr.start) &&
VIR_SOCKET_ADDR_VALID(&ipdef->ranges[0].end)) { VIR_SOCKET_ADDR_VALID(&addr.end)) {
IDHCPServer *dhcpServer = NULL; IDHCPServer *dhcpServer = NULL;
gVBoxAPI.UIVirtualBox.FindDHCPServerByNetworkName(data->vboxObj, gVBoxAPI.UIVirtualBox.FindDHCPServerByNetworkName(data->vboxObj,
...@@ -464,8 +466,8 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const char *xml, bool start) ...@@ -464,8 +466,8 @@ vboxNetworkDefineCreateXML(virConnectPtr conn, const char *xml, bool start)
ipAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->address); ipAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->address);
networkMaskUtf16 = vboxSocketFormatAddrUtf16(data, &netmask); networkMaskUtf16 = vboxSocketFormatAddrUtf16(data, &netmask);
fromIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->ranges[0].start); fromIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &addr.start);
toIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &ipdef->ranges[0].end); toIPAddressUtf16 = vboxSocketFormatAddrUtf16(data, &addr.end);
if (ipAddressUtf16 == NULL || networkMaskUtf16 == NULL || if (ipAddressUtf16 == NULL || networkMaskUtf16 == NULL ||
fromIPAddressUtf16 == NULL || toIPAddressUtf16 == NULL) { fromIPAddressUtf16 == NULL || toIPAddressUtf16 == NULL) {
...@@ -770,6 +772,7 @@ static char *vboxNetworkGetXMLDesc(virNetworkPtr network, unsigned int flags) ...@@ -770,6 +772,7 @@ static char *vboxNetworkGetXMLDesc(virNetworkPtr network, unsigned int flags)
vboxIID vboxnet0IID; vboxIID vboxnet0IID;
IHost *host = NULL; IHost *host = NULL;
char *ret = NULL; char *ret = NULL;
virSocketAddrRange addr;
nsresult rc; nsresult rc;
if (!data->vboxObj) if (!data->vboxObj)
...@@ -833,14 +836,15 @@ static char *vboxNetworkGetXMLDesc(virNetworkPtr network, unsigned int flags) ...@@ -833,14 +836,15 @@ static char *vboxNetworkGetXMLDesc(virNetworkPtr network, unsigned int flags)
/* Currently virtualbox supports only one dhcp server per network /* Currently virtualbox supports only one dhcp server per network
* with contigious address space from start to end * with contigious address space from start to end
*/ */
addr = ipdef->ranges[0].addr;
if (vboxSocketParseAddrUtf16(data, ipAddressUtf16, if (vboxSocketParseAddrUtf16(data, ipAddressUtf16,
&ipdef->address) < 0 || &ipdef->address) < 0 ||
vboxSocketParseAddrUtf16(data, networkMaskUtf16, vboxSocketParseAddrUtf16(data, networkMaskUtf16,
&ipdef->netmask) < 0 || &ipdef->netmask) < 0 ||
vboxSocketParseAddrUtf16(data, fromIPAddressUtf16, vboxSocketParseAddrUtf16(data, fromIPAddressUtf16,
&ipdef->ranges[0].start) < 0 || &addr.start) < 0 ||
vboxSocketParseAddrUtf16(data, toIPAddressUtf16, vboxSocketParseAddrUtf16(data, toIPAddressUtf16,
&ipdef->ranges[0].end) < 0) { &addr.end) < 0) {
errorOccurred = true; errorOccurred = true;
} }
......
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
static int static int
testCompareXMLToConfFiles(const char *inxml, const char *outconf, dnsmasqCapsPtr caps) testCompareXMLToConfFiles(const char *inxml, const char *outconf, dnsmasqCapsPtr caps)
{ {
char *actual = NULL; char *confactual = NULL;
char *hostsfileactual = NULL;
int ret = -1; int ret = -1;
virNetworkDefPtr def = NULL; virNetworkDefPtr def = NULL;
virNetworkObjPtr obj = NULL; virNetworkObjPtr obj = NULL;
...@@ -43,28 +44,30 @@ testCompareXMLToConfFiles(const char *inxml, const char *outconf, dnsmasqCapsPtr ...@@ -43,28 +44,30 @@ testCompareXMLToConfFiles(const char *inxml, const char *outconf, dnsmasqCapsPtr
if (dctx == NULL) if (dctx == NULL)
goto fail; goto fail;
if (networkDnsmasqConfContents(obj, pidfile, &actual, dctx, caps) < 0) if (networkDnsmasqConfContents(obj, pidfile, &confactual,
&hostsfileactual, dctx, caps) < 0)
goto fail; goto fail;
/* Any changes to this function ^^ should be reflected here too. */ /* Any changes to this function ^^ should be reflected here too. */
#ifndef __linux__ #ifndef __linux__
char * tmp; char * tmp;
if (!(tmp = virStringReplace(actual, if (!(tmp = virStringReplace(confactual,
"except-interface=lo0\n", "except-interface=lo0\n",
"except-interface=lo\n"))) "except-interface=lo\n")))
goto fail; goto fail;
VIR_FREE(actual); VIR_FREE(confactual);
actual = g_steal_pointer(&tmp); actual = g_steal_pointer(&tmp);
#endif #endif
if (virTestCompareToFile(actual, outconf) < 0) if (virTestCompareToFile(confactual, outconf) < 0)
goto fail; goto fail;
ret = 0; ret = 0;
fail: fail:
VIR_FREE(actual); VIR_FREE(confactual);
VIR_FREE(hostsfileactual);
VIR_FREE(pidfile); VIR_FREE(pidfile);
virCommandFree(cmd); virCommandFree(cmd);
virObjectUnref(xmlopt); virObjectUnref(xmlopt);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册