Commit 953ae2a7 authored by Natanael Copa's avatar Natanael Copa

main/libvirt: upgrade to 1.0.2 and update public ip NAT patches

parent 49e2d2c3
From 25ea8e47e74def560bf89cd94dd54b75ca5ff4d6 Mon Sep 17 00:00:00 2001
From: "Daniel P. Berrange" <berrange@redhat.com>
Date: Tue, 5 Feb 2013 12:55:09 +0000
Subject: [PATCH] Fix missing error constants in libvirt python module
The previous change to the generator, changed too much - only
the functions are in 'virerror.c', the constants remained in
'virerror.h' which could not be renamed for API compat reasons.
Add a test case to sanity check the generated python bindings
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
python/Makefile.am | 5 +++++
python/generator.py | 4 +++-
python/sanitytest.py | 31 +++++++++++++++++++++++++++++++
3 files changed, 39 insertions(+), 1 deletion(-)
create mode 100644 python/sanitytest.py
diff --git a/python/Makefile.am b/python/Makefile.am
index dd69600..ef3c3eb 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -119,6 +119,11 @@ $(libvirtmod_la_OBJECTS): $(GENERATED)
$(libvirtmod_qemu_la_OBJECTS): $(QEMU_GENERATED)
$(libvirtmod_lxc_la_OBJECTS): $(LXC_GENERATED)
+EXTRA_DIST += sanitytest.py
+
+check-local:
+ $(AM_V_GEN)PYTHONPATH=$(abs_topbuilddir):$(abs_topbuilddir)/.libs $(PYTHON) $(srcdir)/sanitytest.py
+
install-data-local:
$(mkinstalldirs) $(DESTDIR)$(pyexecdir)
$(INSTALL) -m 0644 libvirt.py $(DESTDIR)$(pyexecdir)
diff --git a/python/generator.py b/python/generator.py
index 71ca883..ceade6b 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -122,8 +122,9 @@ class docParser(xml.sax.handler.ContentHandler):
if attrs.has_key('field'):
self.function_return_field = attrs['field']
elif tag == 'enum':
+ # enums come from header files, hence virterror.h
if (attrs['file'] == "libvirt" or
- attrs['file'] == "virerror"):
+ attrs['file'] == "virterror"):
enum(attrs['type'],attrs['name'],attrs['value'])
elif attrs['file'] == "libvirt-lxc":
lxc_enum(attrs['type'],attrs['name'],attrs['value'])
@@ -134,6 +135,7 @@ class docParser(xml.sax.handler.ContentHandler):
if debug:
print "end %s" % tag
if tag == 'function':
+ # fuctions come from source files, hence 'virerror.c'
if self.function != None:
if (self.function_module == "libvirt" or
self.function_module == "virevent" or
diff --git a/python/sanitytest.py b/python/sanitytest.py
new file mode 100644
index 0000000..047450b
--- /dev/null
+++ b/python/sanitytest.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+
+import libvirt
+
+globals = dir(libvirt)
+
+# Sanity test that the generator hasn't gone wrong
+
+# Look for core classes
+assert("virConnect" in globals)
+assert("virDomain" in globals)
+assert("virDomainSnapshot" in globals)
+assert("virInterface" in globals)
+assert("virNWFilter" in globals)
+assert("virNodeDevice" in globals)
+assert("virNetwork" in globals)
+assert("virSecret" in globals)
+assert("virStoragePool" in globals)
+assert("virStorageVol" in globals)
+assert("virStream" in globals)
+assert("VIR_CONNECT_RO" in globals)
+
+# Error related bits
+assert("libvirtError" in globals)
+assert("VIR_ERR_AUTH_FAILED" in globals)
+assert("virGetLastError" in globals)
+
+# Some misc methods
+assert("virInitialize" in globals)
+assert("virEventAddHandle" in globals)
+assert("virEventRegisterDefaultImpl" in globals)
--
1.7.11.7
From a6b8bae5a6a4752926eba409202ec061d81c6c8a Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn@canonical.com>
Date: Wed, 30 Jan 2013 21:05:45 -0600
Subject: [PATCH] complete virterror->virerror name change
Without these two string changes in generator.py, the
virGetLastError wrapper does not get created in
/usr/share/pyshared/libvirt.py. Noticed when running
tests with virt-install.
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
---
python/generator.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/python/generator.py b/python/generator.py
index 5d27f66..71ca883 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -123,7 +123,7 @@ class docParser(xml.sax.handler.ContentHandler):
self.function_return_field = attrs['field']
elif tag == 'enum':
if (attrs['file'] == "libvirt" or
- attrs['file'] == "virterror"):
+ attrs['file'] == "virerror"):
enum(attrs['type'],attrs['name'],attrs['value'])
elif attrs['file'] == "libvirt-lxc":
lxc_enum(attrs['type'],attrs['name'],attrs['value'])
@@ -137,7 +137,7 @@ class docParser(xml.sax.handler.ContentHandler):
if self.function != None:
if (self.function_module == "libvirt" or
self.function_module == "virevent" or
- self.function_module == "virterror"):
+ self.function_module == "virerror"):
function(self.function, self.function_descr,
self.function_return, self.function_args,
self.function_file, self.function_module,
--
1.8.1
From da1e7fe01acdaf13b3fb9e3cda53627063014da9 Mon Sep 17 00:00:00 2001
From: Natanael Copa <ncopa@alpinelinux.org>
Date: Tue, 4 Dec 2012 17:03:51 +0100
Subject: [PATCH] net: support set public ip for forward mode nat
Support setting which public ip to use for NAT via attribute
publicaddr. This will construct an iptables line using '-j SNAT
--to-source <publicaddr>' instead of '-j MASQUERADE'.
Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
---
docs/formatnetwork.html.in | 4 +++-
src/conf/network_conf.c | 33 +++++++++++++++++++++++++++++++++
src/conf/network_conf.h | 1 +
src/network/bridge_driver.c | 24 ++++++++++++++++--------
src/util/iptables.c | 31 ++++++++++++++++++++++++-------
src/util/iptables.h | 6 ++++--
6 files changed, 81 insertions(+), 18 deletions(-)
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index 49206dd..07f9783 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -125,7 +125,9 @@
other network device whether ethernet, wireless, dialup,
or VPN. If the <code>dev</code> attribute is set, the
firewall rules will restrict forwarding to the named
- device only. Inbound connections from other networks are
+ device only. If the <code>publicaddr</code> attribute is set,
+ the given source address will be used with iptables' SNAT
+ target. Inbound connections from other networks are
all prohibited; all connections between guests on the same
network, and to/from the host to the guests, are
unrestricted and not NATed.<span class="since">Since
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 6ce2e63..36128ac 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -174,6 +174,7 @@ void virNetworkDefFree(virNetworkDefPtr def)
VIR_FREE(def->name);
VIR_FREE(def->bridge);
VIR_FREE(def->domain);
+ VIR_FREE(def->publicaddr);
for (ii = 0 ; ii < def->nForwardPfs && def->forwardPfs ; ii++) {
virNetworkForwardPfDefClear(&def->forwardPfs[ii]);
@@ -1211,6 +1212,22 @@ error:
return result;
}
+static int
+virValidPublicaddr(const char *publicaddr)
+{
+ /* only check for max len and valid chars for now */
+ const int maxlen = sizeof("123.123.123.123-123.123.123.123:65535-65534")-1;
+ int len = strlen(publicaddr);
+
+ if (len > maxlen)
+ return 0;
+
+ if (strspn(publicaddr, "0123456789.-:") < len)
+ return 0;
+
+ return 1;
+}
+
static virNetworkDefPtr
virNetworkDefParseXML(xmlXPathContextPtr ctxt)
{
@@ -1387,6 +1404,21 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
def->managed = 1;
}
+ def->publicaddr = virXPathString("string(./@publicaddr)", ctxt);
+ if (def->publicaddr != NULL) {
+ char *errstr = NULL;
+ if (def->forwardType != VIR_NETWORK_FORWARD_NAT) {
+ errstr = "Attribute 'publicaddr' is only valid with mode='nat'";
+ } else if (!virValidPublicaddr(def->publicaddr)) {
+ errstr = "Attribute 'publicaddr' must be in the format: ipaddr[-ipaddr][:port[-port]]";
+ }
+
+ if (errstr != NULL) {
+ virReportError(VIR_ERR_XML_ERROR, "%s", _(errstr));
+ goto error;
+ }
+ }
+
/* all of these modes can use a pool of physical interfaces */
nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes);
nForwardPfs = virXPathNodeSet("./pf", ctxt, &forwardPfNodes);
@@ -1861,6 +1893,7 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
}
virBufferAddLit(&buf, "<forward");
virBufferEscapeString(&buf, " dev='%s'", dev);
+ virBufferEscapeString(&buf, " publicaddr='%s'", def->publicaddr);
virBufferAsprintf(&buf, " mode='%s'", mode);
if (def->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) {
if (def->managed == 1)
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 3e46304..76fb591 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -206,6 +206,7 @@ struct _virNetworkDef {
virPortGroupDefPtr portGroups;
virNetDevBandwidthPtr bandwidth;
virNetDevVlan vlan;
+ char *publicaddr;
};
typedef struct _virNetworkObj virNetworkObj;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 75f3c3a..04f178b 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -1438,7 +1438,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
&ipdef->address,
prefix,
forwardIf,
- NULL) < 0) {
+ NULL,
+ network->def->publicaddr) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
forwardIf ?
_("failed to add iptables rule to enable masquerading to %s") :
@@ -1452,7 +1453,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
&ipdef->address,
prefix,
forwardIf,
- "udp") < 0) {
+ "udp",
+ network->def->publicaddr) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
forwardIf ?
_("failed to add iptables rule to enable UDP masquerading to %s") :
@@ -1466,7 +1468,8 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
&ipdef->address,
prefix,
forwardIf,
- "tcp") < 0) {
+ "tcp",
+ network->def->publicaddr) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
forwardIf ?
_("failed to add iptables rule to enable TCP masquerading to %s") :
@@ -1482,13 +1485,15 @@ networkAddMasqueradingIptablesRules(struct network_driver *driver,
&ipdef->address,
prefix,
forwardIf,
- "udp");
+ "udp",
+ network->def->publicaddr);
masqerr4:
iptablesRemoveForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
forwardIf,
- NULL);
+ NULL,
+ network->def->publicaddr);
masqerr3:
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
&ipdef->address,
@@ -1518,17 +1523,20 @@ networkRemoveMasqueradingIptablesRules(struct network_driver *driver,
&ipdef->address,
prefix,
forwardIf,
- "tcp");
+ "tcp",
+ network->def->publicaddr);
iptablesRemoveForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
forwardIf,
- "udp");
+ "udp",
+ network->def->publicaddr);
iptablesRemoveForwardMasquerade(driver->iptables,
&ipdef->address,
prefix,
forwardIf,
- NULL);
+ NULL,
+ network->def->publicaddr);
iptablesRemoveForwardAllowRelatedIn(driver->iptables,
&ipdef->address,
diff --git a/src/util/iptables.c b/src/util/iptables.c
index 407ca3a..4a89673 100644
--- a/src/util/iptables.c
+++ b/src/util/iptables.c
@@ -804,6 +804,7 @@ iptablesForwardMasquerade(iptablesContext *ctx,
unsigned int prefix,
const char *physdev,
const char *protocol,
+ const char *publicaddr,
int action)
{
int ret;
@@ -833,10 +834,24 @@ iptablesForwardMasquerade(iptablesContext *ctx,
if (physdev && physdev[0])
virCommandAddArgList(cmd, "--out-interface", physdev, NULL);
- virCommandAddArgList(cmd, "--jump", "MASQUERADE", NULL);
+ /* Use --jump SNAT if public addr is specified */
+ if (publicaddr && publicaddr[0]) {
+ char tmpstr[sizeof("123.123.123.123-123.123.123.123:65535-65535")];
+ const char *portstr = "";
- if (protocol && protocol[0])
- virCommandAddArgList(cmd, "--to-ports", "1024-65535", NULL);
+ memset(tmpstr, 0, sizeof(tmpstr));
+ if (protocol && protocol[0] && (strchr(publicaddr, ':') == NULL))
+ portstr = ":1024-65535";
+ snprintf(tmpstr, sizeof(tmpstr), "%s%s", publicaddr, portstr);
+
+ virCommandAddArgList(cmd, "--jump", "SNAT",
+ "--to-source", tmpstr, NULL);
+ } else {
+ virCommandAddArgList(cmd, "--jump", "MASQUERADE", NULL);
+
+ if (protocol && protocol[0])
+ virCommandAddArgList(cmd, "--to-ports", "1024-65535", NULL);
+ }
ret = iptablesCommandRunAndFree(cmd);
VIR_FREE(networkstr);
@@ -861,9 +876,10 @@ iptablesAddForwardMasquerade(iptablesContext *ctx,
virSocketAddr *netaddr,
unsigned int prefix,
const char *physdev,
- const char *protocol)
+ const char *protocol,
+ const char *publicaddr)
{
- return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, protocol, ADD);
+ return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, protocol, publicaddr, ADD);
}
/**
@@ -884,9 +900,10 @@ iptablesRemoveForwardMasquerade(iptablesContext *ctx,
virSocketAddr *netaddr,
unsigned int prefix,
const char *physdev,
- const char *protocol)
+ const char *protocol,
+ const char *publicaddr)
{
- return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, protocol, REMOVE);
+ return iptablesForwardMasquerade(ctx, netaddr, prefix, physdev, protocol, publicaddr, REMOVE);
}
diff --git a/src/util/iptables.h b/src/util/iptables.h
index e54f8b1..a9d2772 100644
--- a/src/util/iptables.h
+++ b/src/util/iptables.h
@@ -105,12 +105,14 @@ int iptablesAddForwardMasquerade (iptablesContext *ctx,
virSocketAddr *netaddr,
unsigned int prefix,
const char *physdev,
- const char *protocol);
+ const char *protocol,
+ const char *publicaddr);
int iptablesRemoveForwardMasquerade (iptablesContext *ctx,
virSocketAddr *netaddr,
unsigned int prefix,
const char *physdev,
- const char *protocol);
+ const char *protocol,
+ const char *publicaddr);
int iptablesAddOutputFixUdpChecksum (iptablesContext *ctx,
const char *iface,
int port);
--
1.8.0.1
From 18d50f3bc920d70a65e2c3b1f08826db91d8ae2e Mon Sep 17 00:00:00 2001
From: Natanael Copa <ncopa@alpinelinux.org>
Date: Sun, 3 Feb 2013 12:18:36 +0100
Subject: [PATCH 1/2] net: support set public ip range for forward mode nat
Support setting which public ip to use for NAT via attribute
address in subelement <nat> in <forward>:
...
<forward mode='nat'>
<address start='1.2.3.4' end='1.2.3.10'/>
</forward>
...
This will construct an iptables line using:
'-j SNAT --to-source <start>-<end>'
instead of:
'-j MASQUERADE'
Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
---
docs/formatnetwork.html.in | 18 ++++++
src/conf/network_conf.c | 152 ++++++++++++++++++++++++++++++++++++++++++--
src/conf/network_conf.h | 3 +
src/network/bridge_driver.c | 16 +++++
src/util/viriptables.c | 56 +++++++++++++---
src/util/viriptables.h | 4 ++
6 files changed, 235 insertions(+), 14 deletions(-)
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index 7b42529..5fbd0a9 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -136,6 +136,24 @@
network, and to/from the host to the guests, are
unrestricted and not NATed.<span class="since">Since
0.4.2</span>
+
+ <p><span class="since">Since 1.0.3</span> it is possible to
+ specify a public IPv4 address range to be used for the NAT by
+ using the <code>&lt;nat&gt;</code> and
+ <code>&lt;address&gt;</code> subelements.
+ <pre>
+...
+ &lt;forward mode='nat'&gt;
+ &lt;nat&gt;
+ &lt;address start='1.2.3.4' end='1.2.3.10'/&gt;
+ &lt;/nat&gt;
+ &lt;/forward&gt;
+...
+ </pre>
+ An singe IPv4 address can be set by setting
+ <code>start</code> and <code>end</code> attributes to
+ the same value.
+ </p>
</dd>
<dt><code>route</code></dt>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 3604ff7..61d086a 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -1325,6 +1325,80 @@ cleanup:
}
static int
+virNetworkForwardNatDefParseXML(const char *networkName,
+ xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
+ virNetworkForwardDefPtr def)
+{
+ int ret = -1;
+ xmlNodePtr *natAddrNodes = NULL;
+ int nNatAddrs;
+ char *addr_start = NULL;
+ char *addr_end = NULL;
+ xmlNodePtr save = ctxt->node;
+
+ ctxt->node = node;
+
+ if (def->type != VIR_NETWORK_FORWARD_NAT) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("The <nat> element can only be used when <forward> 'mode' is 'nat' in network %s"),
+ networkName);
+ goto cleanup;
+ }
+
+ /* addresses for SNAT */
+ nNatAddrs = virXPathNodeSet("./address", ctxt, &natAddrNodes);
+ if (nNatAddrs < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("invalid <address> element found in <forward> of "
+ "network %s"), networkName);
+ goto cleanup;
+ } else if (nNatAddrs > 1) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Only one <address> element is allowed in <nat> in "
+ "<forward> in network %s"), networkName);
+ goto cleanup;
+ } else if (nNatAddrs == 1) {
+ addr_start = virXMLPropString(*natAddrNodes, "start");
+ if (addr_start == NULL) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("missing 'start' attribute in <address> element in <nat> in "
+ "<forward> in network %s"), networkName);
+ goto cleanup;
+ }
+ addr_end = virXMLPropString(*natAddrNodes, "end");
+ if (addr_end == NULL) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("missing 'end' attribute in <address> element in <nat> in "
+ "<forward> in network %s"), networkName);
+ goto cleanup;
+ }
+ }
+
+ if (addr_start && virSocketAddrParse(&def->addr_start, addr_start, AF_INET) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Bad ipv4 start address '%s' in <nat> in <forward> in "
+ "network '%s'"), addr_start, networkName);
+ goto cleanup;
+ }
+
+ if (addr_end && virSocketAddrParse(&def->addr_end, addr_end, AF_INET) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Bad ipv4 end address '%s' in <nat> in <forward> in "
+ "network '%s'"), addr_end, networkName);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(addr_start);
+ VIR_FREE(addr_end);
+ ctxt->node = save;
+ return ret;
+}
+
+static int
virNetworkForwardDefParseXML(const char *networkName,
xmlNodePtr node,
xmlXPathContextPtr ctxt,
@@ -1334,7 +1408,8 @@ virNetworkForwardDefParseXML(const char *networkName,
xmlNodePtr *forwardIfNodes = NULL;
xmlNodePtr *forwardPfNodes = NULL;
xmlNodePtr *forwardAddrNodes = NULL;
- int nForwardIfs, nForwardAddrs, nForwardPfs;
+ xmlNodePtr *forwardNatNodes = NULL;
+ int nForwardIfs, nForwardAddrs, nForwardPfs, nForwardNats;
char *forwardDev = NULL;
char *forwardManaged = NULL;
char *type = NULL;
@@ -1384,6 +1459,24 @@ virNetworkForwardDefParseXML(const char *networkName,
goto cleanup;
}
+ nForwardNats = virXPathNodeSet("./nat", ctxt, &forwardNatNodes);
+ if (nForwardNats < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("invalid <nat> element found in <forward> of network %s"),
+ networkName);
+ goto cleanup;
+ } else if (nForwardNats > 1) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Only one <nat> element is allowed in <forward> of network %s"),
+ networkName);
+ goto cleanup;
+ } else if (nForwardNats == 1) {
+ if (virNetworkForwardNatDefParseXML(networkName,
+ *forwardNatNodes,
+ ctxt, def) < 0)
+ goto cleanup;
+ }
+
if (((nForwardIfs > 0) + (nForwardAddrs > 0) + (nForwardPfs > 0)) > 1) {
virReportError(VIR_ERR_XML_ERROR,
_("<address>, <interface>, and <pf> elements in <forward> "
@@ -1525,6 +1618,7 @@ cleanup:
VIR_FREE(forwardPfNodes);
VIR_FREE(forwardIfNodes);
VIR_FREE(forwardAddrNodes);
+ VIR_FREE(forwardNatNodes);
ctxt->node = save;
return ret;
}
@@ -2079,13 +2173,54 @@ virPortGroupDefFormat(virBufferPtr buf,