[virt-tools-list] [PATCH 2/6] IPv6 support: update gui python processing

Gene Czarcinski gene at czarc.net
Tue Mar 26 11:05:57 UTC 2013


Update the gui processing programs.  Some of this is
also used by the Tui interface. With this patch, all needs for
IPy.py in the gui portion of virt-manager have been removed and
replaced with ipaddr from the prython-ipaddr package.  These updates
also implement network display.

Currently, createnet.py only handles IPv4 network
creation.
Signed-off-by: Gene Czarcinski <gene at czarc.net>
---
 virtManager/createnet.py |  67 +++++++++++----------
 virtManager/host.py      |  32 +++++++++-
 virtManager/network.py   | 151 +++++++++++++++++++++++++++++++++++++----------
 3 files changed, 184 insertions(+), 66 deletions(-)

diff --git a/virtManager/createnet.py b/virtManager/createnet.py
index 79dd249..846cfbf 100644
--- a/virtManager/createnet.py
+++ b/virtManager/createnet.py
@@ -21,7 +21,7 @@
 import logging
 import re
 
-from IPy import IP
+import ipaddr
 
 from gi.repository import Gtk
 from gi.repository import Gdk
@@ -153,7 +153,7 @@ class vmmCreateNetwork(vmmGObjectUI):
         src.modify_text(Gtk.StateType.NORMAL, black)
 
         # No IP specified or invalid IP
-        if ip is None or ip.version() != 4:
+        if ip is None or ip.version != 4:
             src.modify_base(Gtk.StateType.NORMAL, red)
             self.widget("net-info-netmask").set_text("")
             self.widget("net-info-broadcast").set_text("")
@@ -162,26 +162,25 @@ class vmmCreateNetwork(vmmGObjectUI):
             self.widget("net-info-type").set_text("")
             return
 
+        # FIXME: handle other networks and not just private?
         # We've got a valid IP
-        if ip.len() < 4 or ip.iptype() != "PRIVATE":
-            src.modify_base(Gtk.StateType.NORMAL, red)
+        if ip.numhosts < 16 or not ip.is_private:
+            src.modify_base(gtk.STATE_NORMAL, red)
         else:
             src.modify_base(Gtk.StateType.NORMAL, green)
-        self.widget("net-info-netmask").set_text(str(ip.netmask()))
-        self.widget("net-info-broadcast").set_text(str(ip.broadcast()))
+        self.widget("net-info-netmask").set_text(str(ip.netmask))
+        self.widget("net-info-broadcast").set_text(str(ip.broadcast))
 
-        if ip.len() <= 1:
+        if ip.prefixlen == 32:
             self.widget("net-info-gateway").set_text("")
         else:
-            self.widget("net-info-gateway").set_text(str(ip[1]))
+            self.widget("net-info-gateway").set_text(str(ip.network + 1))
         self.widget("net-info-size").set_text(_("%d addresses") %
-                                                         (ip.len()))
+                                                         (ip.numhosts))
 
-        if ip.iptype() == "PUBLIC":
-            self.widget("net-info-type").set_text(_("Public"))
-        elif ip.iptype() == "PRIVATE":
+        if ip.is_private:
             self.widget("net-info-type").set_text(_("Private"))
-        elif ip.iptype() == "RESERVED":
+        elif ip.is_reserved:
             self.widget("net-info-type").set_text(_("Reserved"))
         else:
             self.widget("net-info-type").set_text(_("Other"))
@@ -192,8 +191,8 @@ class vmmCreateNetwork(vmmGObjectUI):
         self.widget("net-dhcp-end").set_sensitive(val)
 
     def change_dhcp_start(self, src):
-        end = self.get_config_dhcp_start()
-        self.change_dhcp(src, end)
+        start = self.get_config_dhcp_start()
+        self.change_dhcp(src, start)
 
     def change_dhcp_end(self, src):
         end = self.get_config_dhcp_end()
@@ -222,18 +221,18 @@ class vmmCreateNetwork(vmmGObjectUI):
 
     def get_config_ip4(self):
         try:
-            return IP(self.widget("net-network").get_text())
+            return ipaddr.IPNetwork(self.widget("net-network").get_text())
         except:
             return None
 
     def get_config_dhcp_start(self):
         try:
-            return IP(self.widget("net-dhcp-start").get_text())
+            return ipaddr.IPNetwork(self.widget("net-dhcp-start").get_text())
         except:
             return None
     def get_config_dhcp_end(self):
         try:
-            return IP(self.widget("net-dhcp-end").get_text())
+            return ipaddr.IPNetwork(self.widget("net-dhcp-end").get_text())
         except:
             return None
 
@@ -260,16 +259,16 @@ class vmmCreateNetwork(vmmGObjectUI):
 
         ip = self.get_config_ip4()
         self.widget("summary-ip4-network").set_text(str(ip))
-        self.widget("summary-ip4-gateway").set_text(str(ip[1]))
-        self.widget("summary-ip4-netmask").set_text(str(ip.netmask()))
+        self.widget("summary-ip4-gateway").set_text(str(ip.network + 1))
+        self.widget("summary-ip4-netmask").set_text(str(ip.netmask))
 
         self.widget("label-dhcp-end").set_property("visible", dodhcp)
         self.widget("summary-dhcp-end").set_property("visible", dodhcp)
         if dodhcp:
             start = self.get_config_dhcp_start()
             end = self.get_config_dhcp_end()
-            self.widget("summary-dhcp-start").set_text(str(start))
-            self.widget("summary-dhcp-end").set_text(str(end))
+            self.widget("summary-dhcp-start").set_text(str(start.network))
+            self.widget("summary-dhcp-end").set_text(str(end.network))
             self.widget("label-dhcp-start").set_text(_("Start address:"))
             self.widget("label-dhcp-end").show()
             self.widget("summary-dhcp-end").show()
@@ -284,13 +283,13 @@ class vmmCreateNetwork(vmmGObjectUI):
 
     def populate_dhcp(self):
         ip = self.get_config_ip4()
-        start = int(ip.len() / 2)
-        end = ip.len() - 2
+        start = int(ip.numhosts / 2)
+        end   = int(ip.numhosts - 2)
 
         if self.widget("net-dhcp-start").get_text() == "":
-            self.widget("net-dhcp-start").set_text(str(ip[start]))
+            self.widget("net-dhcp-start").set_text(str(ip.network + start))
         if self.widget("net-dhcp-end").get_text() == "":
-            self.widget("net-dhcp-end").set_text(str(ip[end]))
+            self.widget("net-dhcp-end").set_text(str(ip.network + end))
 
     def page_changed(self, ignore1, ignore2, page_number):
         if page_number == PAGE_NAME:
@@ -331,13 +330,13 @@ class vmmCreateNetwork(vmmGObjectUI):
             else:
                 xml += "  <forward mode='%s'/>\n" % mode
 
-        xml += "  <ip address='%s' netmask='%s'>\n" % (str(ip[1]),
-                                                       str(ip.netmask()))
+        xml += "  <ip address='%s' netmask='%s'>\n" % (str(ip.network + 1),
+                                                       str(ip.netmask))
 
         if self.get_config_dhcp_enable():
             xml += "    <dhcp>\n"
-            xml += "      <range start='%s' end='%s'/>\n" % (str(start),
-                                                             str(end))
+            xml += "      <range start='%s' end='%s'/>\n" % (str(start.network),
+                                                             str(end.network))
             xml += "    </dhcp>\n"
 
         xml += "  </ip>\n"
@@ -372,15 +371,15 @@ class vmmCreateNetwork(vmmGObjectUI):
             return self.err.val_err(_("Invalid Network Address"),
                     _("The network address could not be understood"))
 
-        if ip.version() != 4:
+        if ip.version != 4:
             return self.err.val_err(_("Invalid Network Address"),
                     _("The network must be an IPv4 address"))
 
-        if ip.len() < 4:
+        if ip.numhosts < 16:
             return self.err.val_err(_("Invalid Network Address"),
-                    _("The network prefix must be at least /4 (16 addresses)"))
+                    _("The network prefix must be at least /28 (16 addresses)"))
 
-        if ip.iptype() != "PRIVATE":
+        if not ip.is_private:
             res = self.err.yes_no(_("Check Network Address"),
                     _("The network should normally use a private IPv4 "
                       "address. Use this non-private address anyway?"))
diff --git a/virtManager/host.py b/virtManager/host.py
index ff50f82..e4502b6 100644
--- a/virtManager/host.py
+++ b/virtManager/host.py
@@ -544,14 +544,37 @@ class vmmHost(vmmGObjectUI):
         self.widget("net-autostart").set_active(autostart)
         self.widget("net-autostart").set_label(autolabel)
 
-        network = net.get_ipv4_network()
+        result = net.get_ipv4_network()
+        network = result[0]
+        dhcp = result[1]
+        route = result[2]
         self.widget("net-ip4-network").set_text(str(network))
 
-        dhcp = net.get_ipv4_dhcp_range()
         start = dhcp and str(dhcp[0]) or _("Disabled")
         end = dhcp and str(dhcp[1]) or _("Disabled")
         self.widget("net-ip4-dhcp-start").set_text(start)
         self.widget("net-ip4-dhcp-end").set_text(end)
+        if route and route[0] and route[1]:
+            routeVia = str(route[0]) + " via " + str(route[1])
+        else:
+            routeVia = _("None")
+        self.widget("net-ip4-route-via").set_text(routeVia)
+
+        result = net.get_ipv6_network()
+        network = result[0]
+        dhcp = result[1]
+        route = result[2]
+        self.widget("net-ip6-network").set_text(str(network))
+
+        start = dhcp and str(dhcp[0]) or _("Disabled")
+        end = dhcp and str(dhcp[1]) or _("Disabled")
+        self.widget("net-ip6-dhcp-start").set_text(start)
+        self.widget("net-ip6-dhcp-end").set_text(end)
+        if route and route[0] and route[1]:
+            routeVia = str(route[0]) + " via " + str(route[1])
+        else:
+            routeVia = "None"
+        self.widget("net-ip6-route-via").set_text(routeVia)
 
         forward, ignore = net.get_ipv4_forward()
         iconsize = Gtk.IconSize.MENU
@@ -579,10 +602,15 @@ class vmmHost(vmmGObjectUI):
         self.widget("net-ip4-network").set_text("")
         self.widget("net-ip4-dhcp-start").set_text("")
         self.widget("net-ip4-dhcp-end").set_text("")
+        self.widget("net-ip4-route-via").set_text("")
         self.widget("net-ip4-forwarding-icon").set_from_stock(
                                     Gtk.STOCK_DISCONNECT, Gtk.IconSize.MENU)
         self.widget("net-ip4-forwarding").set_text(
                                     _("Isolated virtual network"))
+        self.widget("net-ip6-network").set_text("")
+        self.widget("net-ip6-dhcp-start").set_text("")
+        self.widget("net-ip6-dhcp-end").set_text("")
+        self.widget("net-ip6-route-via").set_text("")
         self.widget("net-apply").set_sensitive(False)
 
     def repopulate_networks(self, src_ignore, uuid_ignore):
diff --git a/virtManager/network.py b/virtManager/network.py
index 13a16e3..3d85799 100644
--- a/virtManager/network.py
+++ b/virtManager/network.py
@@ -18,9 +18,9 @@
 # MA 02110-1301 USA.
 #
 
-from IPy import IP
-
 from virtManager import util
+import ipaddr
+import libxml2
 from virtManager.libvirtobject import vmmLibvirtObject
 
 class vmmNetwork(vmmLibvirtObject):
@@ -97,27 +97,127 @@ class vmmNetwork(vmmLibvirtObject):
         return self.net.autostart()
 
     def get_ipv4_network(self):
+        doc = None
+        ret = None
+        goodNode = None
+        dhcpstart = None
+        dhcpend = None
+        routeAddr = None
+        routeVia = None
         xml = self.get_xml()
-        if util.xpath(xml, "/network/ip") is None:
-            return None
-        addrStr = util.xpath(xml, "/network/ip/@address")
-        netmaskStr = util.xpath(xml, "/network/ip/@netmask")
-        prefix = util.xpath(xml, "/network/ip/@prefix")
-
-        if prefix:
-            prefix = int(prefix)
-            binstr = ((prefix * "1") + ((32 - prefix) * "0"))
-            netmaskStr = str(IP(int(binstr, base=2)))
-
-        if netmaskStr:
-            netmask = IP(netmaskStr)
-            gateway = IP(addrStr)
-            network = IP(gateway.int() & netmask.int())
-            ret = IP(str(network) + "/" + netmaskStr)
+        doc = libxml2.parseDoc(xml)
+        nodes = doc.xpathEval('//ip')
+        for node in nodes:
+            family = node.xpathEval('string(./@family)')
+            if not family or family == 'ipv4':
+                dhcp = node.xpathEval('string(./dhcp)')
+                if dhcp:
+                    dhcpstart = node.xpathEval('string(./dhcp/range[1]/@start)')
+                    dhcpend = node.xpathEval('string(./dhcp/range[1]/@end)')
+                    goodNode = node
+                    break
+
+        for node in nodes:
+            family = node.xpathEval('string(./@family)')
+            if not family or family == 'ipv4':
+                routeVia = node.xpathEval('string(./@via)')
+                if routeVia:
+                    routeAddr = node.xpathEval('string(./@address)')
+                    break;
+
+        if goodNode == None:
+            for node in nodes:
+                family = node.xpathEval('string(./@family)')
+                if not family or family == 'ipv4':
+                    tmp = node.xpathEval('string(./@via)')
+                    if tmp:
+                        continue
+                    goodNode = node;
+                    break
+
+        if goodNode:
+            addrStr    = goodNode.xpathEval('string(./@address)')
+            netmaskStr = goodNode.xpathEval('string(./@netmask)')
+            prefix     = goodNode.xpathEval('string(./@prefix)')
+            if prefix:
+                prefix = int(prefix)
+                ret = str(ipaddr.IPNetwork(str(addrStr) + "/" + str(prefix)).masked())
+            elif netmaskStr:
+                netmask = ipaddr.IPAddress(netmaskStr)
+                network = ipaddr.IPAddress(addrStr)
+                ret = str(ipaddr.IPNetwork(str(network) + "/" + str(netmask)).masked())
+            else:
+                ret = str(ipaddr.IPNetwork(str(addrStr)))
+        if doc:
+            doc.freeDoc()
+        if dhcpstart and dhcpend:
+            dhcp = [str(ipaddr.IPAddress(dhcpstart)), str(ipaddr.IPAddress(dhcpend))]
         else:
-            ret = IP(str(addrStr))
-
-        return ret
+            dhcp = None
+        if routeAddr and routeVia:
+            route = [str(ipaddr.IPAddress(routeAddr)), str(ipaddr.IPAddress(routeVia))]
+        else:
+            route = None
+        return [ret, dhcp, route]
+
+    def get_ipv6_network(self):
+        doc = None
+        ret = None
+        goodNode = None
+        dhcpstart = None
+        dhcpend = None
+        routeAddr = None
+        routeVia = None
+        xml = self.get_xml()
+        doc = libxml2.parseDoc(xml)
+        nodes = doc.xpathEval('//ip')
+        for node in nodes:
+            family = node.xpathEval('string(./@family)')
+            if family and family == 'ipv6':
+                dhcp = node.xpathEval('string(./dhcp)')
+                if dhcp:
+                    dhcpstart = node.xpathEval('string(./dhcp/range[1]/@start)')
+                    dhcpend = node.xpathEval('string(./dhcp/range[1]/@end)')
+                    goodNode = node
+                    break
+
+        for node in nodes:
+            family = node.xpathEval('string(./@family)')
+            if family and family == 'ipv6':
+                routeVia = node.xpathEval('string(./@via)')
+                if routeVia:
+                    routeAddr = node.xpathEval('string(./@address)')
+                    break;
+
+        if goodNode == None:
+            for node in nodes:
+                family = node.xpathEval('string(./@family)')
+                if family and family == 'ipv6':
+                    tmp = node.xpathEval('string(./@via)')
+                    if tmp:
+                        continue
+                    goodNode = node;
+                    break
+
+        if goodNode:
+            addrStr    = goodNode.xpathEval('string(./@address)')
+            prefix     = goodNode.xpathEval('string(./@prefix)')
+            if prefix:
+                prefix = int(prefix)
+                ret = str(ipaddr.IPNetwork(str(addrStr) + "/" + str(prefix)).masked())
+            else:
+                ret = str(ipaddr.IPNetwork(str(addrStr)))
+        if doc:
+            doc.freeDoc()
+        if dhcpstart and dhcpend:
+            dhcp = [str(ipaddr.IPAddress(dhcpstart)), str(ipaddr.IPAddress(dhcpend))]
+        else:
+            dhcp = None
+        if routeAddr and routeVia:
+            route = [str(ipaddr.IPAddress(routeAddr)), str(ipaddr.IPAddress(routeVia))]
+        else:
+            route = None
+        return [ret, dhcp, route]
 
     def get_ipv4_forward(self):
         xml = self.get_xml()
@@ -125,15 +225,6 @@ class vmmNetwork(vmmLibvirtObject):
         forwardDev = util.xpath(xml, "/network/forward/@dev")
         return [fw, forwardDev]
 
-    def get_ipv4_dhcp_range(self):
-        xml = self.get_xml()
-        dhcpstart = util.xpath(xml, "/network/ip/dhcp/range[1]/@start")
-        dhcpend = util.xpath(xml, "/network/ip/dhcp/range[1]/@end")
-        if not dhcpstart or not dhcpend:
-            return None
-
-        return [IP(dhcpstart), IP(dhcpend)]
-
     def pretty_forward_mode(self):
         forward, forwardDev = self.get_ipv4_forward()
         return vmmNetwork.pretty_desc(forward, forwardDev)
-- 
1.8.1.4




More information about the virt-tools-list mailing list