From 41c782a37e2ea982cf80823a4227565f80f7af3d Mon Sep 17 00:00:00 2001 From: Gene Czarcinski Date: Tue, 14 May 2013 12:15:02 -0400 Subject: [PATCH] static route support The syntax for static route support is defined by the new subelement which has the form: This patch builds on the previous patches for adding IPv6 support and extending the virtual network support. The static route support code has been recently added to libvirt and will be included in libvirt 1.0.6. . Signed-off-by: Gene Czarcinski --- ui/vmm-create-net.ui | 883 ++++++++++++++++++++++++++++++--------- ui/vmm-host.ui | 4 +- virtManager/createnet.py | 597 +++++++++++++++++++++----- virtManager/host.py | 8 +- virtManager/network.py | 108 +++-- 5 files changed, 1260 insertions(+), 340 deletions(-) diff --git a/ui/vmm-create-net.ui b/ui/vmm-create-net.ui index ef9fcaa3..8d07c6c4 100644 --- a/ui/vmm-create-net.ui +++ b/ui/vmm-create-net.ui @@ -89,7 +89,7 @@ False 0 6 - <small>●</small> A <b>name</b> for the new virtual network + <small>●</small> A <b>name</b> for the new virtual network interface True @@ -105,7 +105,7 @@ 0 0.47999998927116394 6 - <small>●</small> An <b>IPv4</b> and/or <b>IPv6</b> network address and prefix (netmask) to assign + <small>●</small> An <b>IPv4</b> and/or <b>IPv6</b> network address and prefix (netmask) to assign to this network interface True True @@ -121,7 +121,7 @@ False 0 6 - <small>●</small> The network address range which the <b>DHCPv4</b> and/or <b>DHCPv6</b> server will assign addresses to virtual machines + <small>●</small> The network address range which the <b>DHCPv4</b> and/or <b>DHCPv6</b> server will use to assign addresses to virtual machines True True @@ -152,7 +152,7 @@ False 0 6 - <small>●</small> Optionally to specify an <b>IPv4</b> and/or <b>IPv6</b> network address. If neither is specified, this will be a valid definition for an isolated network with <b>no</b> DHCP or DNS support. + <small>●</small> Optionally, to not specify any <b>IPv4</b> or <b>IPv6</b> network address. If neither is specified, this will be a valid definition for an isolated network with <b>no</b> DHCP or DNS support. True True @@ -162,6 +162,38 @@ 4 + + + True + False + 0 + 6 + <small>●</small> By default, the <b>Domain</b> name will be the same as the network/interface name. + True + True + + + False + True + 5 + + + + + True + False + 0 + 6 + <small>●</small> Optionally, a <b>static route</b> to a different network can be specified. This network traffic is routed to the specified <b>gateway</b> on the primary network. + True + True + + + False + True + 6 + + @@ -384,6 +416,130 @@ 3 + + + True + False + + + True + False + 0 + 6 + The following information may help you with defining your networks. + True + True + + + False + True + 0 + + + + + True + False + 25 + + + True + False + + + True + False + 0 + 6 + <small>●</small> A<b> network</b> must be specified as the network <b>address</b> and the <b>prefix</b> for that network. + True + True + + + True + True + 0 + + + + + True + False + 0 + 6 + <small>●</small> A network mask cannot be used for the network specification. Instead, the prefix must be used. + True + True + + + True + True + 1 + + + + + True + False + 0 + <small>●</small> A <b>host address</b> such as that used for the dhcp start, dhcp end, and the static route gateway address should not include a prefix. If included, this prefix must be the maximum. That is, for IPv4 prefix=32 and for IPv6 prefix=128. + True + True + + + True + True + 2 + + + + + True + False + 0 + 6 + <small>●</small> If IPv6 is to be routed, some form of routing must be specified for the interface. + True + True + + + True + True + 3 + + + + + True + False + 0 + 6 + <small>●</small> For the <b>primary network</b>, the prefix must be <b>64</b>. However, for the <b>static route network</b>, the prefix can be <b>64 or less</b>. + True + True + + + True + True + 4 + + + + + + + False + True + 1 + + + + + True + True + 4 + + True @@ -793,7 +949,7 @@ True False - 3 + 6 5 4 3 @@ -893,6 +1049,104 @@ + + + True + False + 27 + + + Enable Static Route Definition + True + True + False + True + + + + + + 5 + 3 + 4 + GTK_FILL + + + + + + True + False + 1 + 15 + <b>to</b> Network: + True + + + 4 + 5 + GTK_FILL + + + + + + True + False + 1 + 15 + <b>via</b> Gateway: + True + + + 5 + 6 + GTK_FILL + + + + + + True + True + 20 + + False + False + True + True + + + + 1 + 5 + 4 + 5 + GTK_FILL + + + + + + True + True + 15 + + False + False + True + True + + + + 1 + 5 + 5 + 6 + GTK_FILL + + + True @@ -1317,7 +1571,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False - 3 + 6 5 4 3 @@ -1355,7 +1609,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True True - 45 + 40 True False @@ -1377,7 +1631,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True True - 45 + 40 True False @@ -1417,6 +1671,104 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 + + + True + False + 27 + + + Enable Static Route Definition + True + True + False + True + + + + + + 5 + 3 + 4 + GTK_FILL + + + + + + True + False + 1 + 15 + <b>to</b> Network: + True + + + 4 + 5 + GTK_FILL + + + + + + True + False + 1 + 15 + <b>via</b> Gateway: + True + + + 5 + 6 + GTK_FILL + + + + + + True + True + 45 + + False + False + True + True + + + + 1 + 5 + 4 + 5 + GTK_FILL + + + + + + True + True + 40 + + False + False + True + True + + + + 1 + 5 + 5 + 6 + GTK_FILL + + + True @@ -1994,10 +2346,25 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False 6 - 14 + 18 3 3 3 + + + + + + + + + + + + + + + True @@ -2018,7 +2385,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 False 0 5 - <b>IPv4 network</b> + <b>IPv4 Network</b> True @@ -2050,7 +2417,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False 1 - Domain Name: + <b>Domain</b> Name: True @@ -2067,6 +2434,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False 0 + 2 192.168.10.254 middle @@ -2084,6 +2452,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False 0 + 2 192.168.10.1 middle @@ -2101,6 +2470,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False 0 + 2 192.168.10.0/24 @@ -2117,6 +2487,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False 0 + 2 demonet @@ -2133,6 +2504,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False 0 + 2 192.168.10.128 True @@ -2145,130 +2517,12 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 - - - True - False - 0 - 5 - <b>IPv6 network</b> - True - - - 8 - 9 - GTK_FILL - - - - - - True - False - 0 - FD00:100::/64 - True - - - 2 - 3 - 9 - 10 - GTK_FILL - - - - - - True - False - 0 - FD00:100::1 - middle - - - 2 - 3 - 10 - 11 - GTK_FILL - - - - - - True - False - 1 - DHCPv6 End Address: - True - - - 1 - 2 - 13 - 14 - GTK_FILL - - - - - - True - False - 1 - DHCPv6 Start Address: - True - - - 1 - 2 - 12 - 13 - GTK_FILL - - - - - - True - False - 0 - FD00:100::100 - True - - - 2 - 3 - 12 - 13 - GTK_FILL - - - - - - True - False - 0 - FD00:100::1FF - True - - - 2 - 3 - 13 - 14 - GTK_EXPAND | GTK_SHRINK | GTK_FILL - - - True False 1 - Network: + Network Address / prefix: 1 @@ -2313,38 +2567,6 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 - - - True - False - 1 - Network: - - - 1 - 2 - 9 - 10 - GTK_FILL - - - - - - True - False - 1 - Gateway: - - - 1 - 2 - 10 - 11 - GTK_FILL - - - True @@ -2364,7 +2586,8 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False 1 - Network Name: + <b>Network</b> Name: + True 1 @@ -2378,6 +2601,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False 0 + 2 demo @@ -2408,6 +2632,7 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False 0 + 2 NAT @@ -2419,38 +2644,6 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 - - - True - False - 1 - Forwarding/Connectivity: - - - 1 - 2 - 11 - 12 - GTK_FILL - - - - - - True - False - 0 - Routed - - - 2 - 3 - 11 - 12 - GTK_FILL - - - True @@ -2546,7 +2739,14 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 True False - + + True + False + 0 + 5 + <b>IPv6 Network</b> + True + @@ -2614,6 +2814,175 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 GTK_FILL + + + True + False + 1 + DHCPv6 End Address: + True + + + 1 + 2 + 15 + 16 + GTK_FILL + + + + + + True + False + 1 + DHCPv6 Start Address: + True + + + 1 + 2 + 14 + 15 + GTK_FILL + + + + + + True + False + 1 + Forwarding/Connectivity: + + + 1 + 2 + 13 + 14 + GTK_FILL + + + + + + True + False + 1 + Gateway: + + + 1 + 2 + 12 + 13 + GTK_FILL + + + + + + True + False + 1 + Network Address / prefix: + + + 1 + 2 + 11 + 12 + GTK_FILL + + + + + + True + False + 0 + 2 + FD00:100::100 + True + + + 2 + 3 + 14 + 15 + GTK_EXPAND | GTK_SHRINK | GTK_FILL + + + + + + True + False + 0 + 2 + FD00:100::1FF + True + + + 2 + 3 + 15 + 16 + GTK_EXPAND | GTK_SHRINK | GTK_FILL + + + + + + True + False + 0 + 2 + Routed + + + 2 + 3 + 13 + 14 + GTK_FILL + + + + + + True + False + 0 + 2 + FD00:100::/64 + + + 2 + 3 + 11 + 12 + GTK_FILL + + + + + + True + False + 0 + 2 + FD00:100::1 + + + 2 + 3 + 12 + 13 + GTK_FILL + + + True @@ -2622,9 +2991,131 @@ A typical IPv6 network address will look something like: fd00:dead:beef:55::/64 1 3 + 10 + 11 + GTK_FILL + + + + + True + False + 1 + Static Route <b>to</b> network: + True + + + 1 + 2 + 8 + 9 + + + + + True + False + 1 + <b>via</b> Gateway: + True + + + 1 + 2 + 9 + 10 + + + + + True + False + 1 + Static Route <b>to</b> network: + True + + + 1 + 2 + 16 + 17 + + + + + True + False + 1 + <b>via</b> Gateway: + True + + + 1 + 2 + 17 + 18 + + + + + True + False + 0 + 3 + + + 2 + 3 8 9 GTK_FILL + + + + + + True + False + 0 + 3 + + + 2 + 3 + 9 + 10 + GTK_FILL + + + + + + True + False + 0 + 3 + + + 2 + 3 + 16 + 17 + GTK_FILL + + + + + + True + False + 0 + 3 + + + 2 + 3 + 17 + 18 diff --git a/ui/vmm-host.ui b/ui/vmm-host.ui index aca4cb73..bd315fee 100644 --- a/ui/vmm-host.ui +++ b/ui/vmm-host.ui @@ -945,7 +945,7 @@ True False 0 - Route-Via: + Static Route: 3 @@ -1050,7 +1050,7 @@ True False 0 - Route-Via: + Static Route: 3 diff --git a/virtManager/createnet.py b/virtManager/createnet.py index 7f61448a..69510870 100644 --- a/virtManager/createnet.py +++ b/virtManager/createnet.py @@ -54,16 +54,26 @@ class vmmCreateNetwork(vmmGObjectUI): "on_net_name_activate": self.forward, "on_net_forward_toggled" : self.change_forward_type, - "on_net-ipv4-enable_toggled" : self.change_ipv4_enable, - "on_net-ipv4-network_changed": self.change_network, + + "on_net-ipv4-enable_toggled" : self.change_ipv4_enable, + "on_net-ipv4-network_changed": self.change_ipv4_network, "on_net-dhcpv4-enable_toggled": self.change_dhcpv4_enable, - "on_net-dhcpv4-start_changed": self.change_dhcpv4_start, - "on_net-dhcpv4-end_changed": self.change_dhcpv4_end, - "on_net-ipv6-enable_toggled" : self.change_ipv6_enable, - "on_net-ipv6-network_changed": self.change_ipv6_network, + "on_net-dhcpv4-start_changed": self.change_dhcpv4_start, + "on_net-dhcpv4-end_changed": self.change_dhcpv4_end, + + "on_net-ipv6-enable_toggled" : self.change_ipv6_enable, + "on_net-ipv6-network_changed": self.change_ipv6_network, "on_net-dhcpv6-enable_toggled": self.change_dhcpv6_enable, - "on_net-dhcpv6-start_changed": self.change_dhcpv6_start, - "on_net-dhcpv6-end_changed": self.change_dhcpv6_end, + "on_net-dhcpv6-start_changed": self.change_dhcpv6_start, + "on_net-dhcpv6-end_changed": self.change_dhcpv6_end, + + "on_net-routev4-enable_toggled": self.change_routev4_enable, + "on_net-routev4-network_changed": self.change_routev4_network, + "on_net-routev4-gateway_changed": self.change_routev4_gateway, + + "on_net-routev6-enable_toggled": self.change_routev6_enable, + "on_net-routev6-network_changed": self.change_routev6_network, + "on_net-routev6-gateway_changed": self.change_routev6_gateway, }) self.bind_escape_key_close() @@ -171,53 +181,77 @@ class vmmCreateNetwork(vmmGObjectUI): ignore = src white = Gdk.Color.parse("#f0f0f0")[1] - net4 = self.widget("net-ipv4-network") - start4 = self.widget("net-dhcpv4-start") - end4 = self.widget("net-dhcpv4-end") + net = self.widget("net-ipv4-network") + start = self.widget("net-dhcpv4-start") + end = self.widget("net-dhcpv4-end") + network = self.widget("net-routev4-network") + gateway = self.widget("net-routev4-gateway") if self.get_config_ipv4_enable(): - net4.set_sensitive(True) - net4.set_text("") - net4.modify_bg(Gtk.StateType.NORMAL, white) + net.set_sensitive(True) + net.set_text("") + net.modify_bg(Gtk.StateType.NORMAL, white) if self.get_config_dhcpv4_enable(): - start4.set_sensitive(True) - end4.set_sensitive(True) + start.set_sensitive(True) + end.set_sensitive(True) + if self.get_config_routev4_enable(): + network.set_sensitive(True) + gateway.set_sensitive(True) else: - net4.set_text("") - start4.set_text("") - end4.set_text("") - net4.set_sensitive(False) - start4.set_sensitive(False) - end4.set_sensitive(False) - net4.modify_bg(Gtk.StateType.NORMAL, white) - start4.modify_bg(Gtk.StateType.NORMAL, white) - end4.modify_bg(Gtk.StateType.NORMAL, white) + net.set_text("") + start.set_text("") + end.set_text("") + network.set_text("") + gateway.set_text("") + net.set_sensitive(False) + start.set_sensitive(False) + end.set_sensitive(False) + network.set_sensitive(False) + gateway.set_sensitive(False) + net.modify_bg(Gtk.StateType.NORMAL, white) + start.modify_bg(Gtk.StateType.NORMAL, white) + end.modify_bg(Gtk.StateType.NORMAL, white) + network.modify_bg(Gtk.StateType.NORMAL, white) + gateway.modify_bg(Gtk.StateType.NORMAL, white) def change_ipv6_enable(self, src): ignore = src white = Gdk.Color.parse("#f0f0f0")[1] - net6 = self.widget("net-ipv6-network") - start6 = self.widget("net-dhcpv6-start") - end6 = self.widget("net-dhcpv6-end") + net = self.widget("net-ipv6-network") + start = self.widget("net-dhcpv6-start") + end = self.widget("net-dhcpv6-end") + network = self.widget("net-routev6-network") + gateway = self.widget("net-routev6-gateway") if self.get_config_ipv6_enable(): - net6.set_sensitive(True) - net6.set_text("") - net6.modify_bg(Gtk.StateType.NORMAL, white) + net.set_sensitive(True) + net.set_text("") + net.modify_bg(Gtk.StateType.NORMAL, white) if self.get_config_dhcpv6_enable(): - start6.set_sensitive(True) - end6.set_sensitive(True) + start.set_sensitive(True) + end.set_sensitive(True) + if self.get_config_routev6_enable(): + network.set_sensitive(True) + gateway.set_sensitive(True) else: - net6.set_text("") - start6.set_text("") - end6.set_text("") - net6.set_sensitive(False) - start6.set_sensitive(False) - end6.set_sensitive(False) - net6.modify_bg(Gtk.StateType.NORMAL, white) - start6.modify_bg(Gtk.StateType.NORMAL, white) - end6.modify_bg(Gtk.StateType.NORMAL, white) + net.set_text("") + start.set_text("") + end.set_text("") + network.set_text("") + gateway.set_text("") + net.set_sensitive(False) + start.set_sensitive(False) + end.set_sensitive(False) + network.set_sensitive(False) + gateway.set_sensitive(False) + net.modify_bg(Gtk.StateType.NORMAL, white) + start.modify_bg(Gtk.StateType.NORMAL, white) + end.modify_bg(Gtk.StateType.NORMAL, white) + network.modify_bg(Gtk.StateType.NORMAL, white) + gateway.modify_bg(Gtk.StateType.NORMAL, white) + + def change_ipv4_network(self, src): + ignore = src - def change_network(self, src): ip = self.get_config_ip4() green = Gdk.Color.parse("#c0ffc0")[1] red = Gdk.Color.parse("#ffc0c0")[1] @@ -231,6 +265,8 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("net-info-type").set_text("") self.widget("net-dhcpv4-start").set_text("") self.widget("net-dhcpv4-end").set_text("") + self.widget("net-routev4-network").set_text("") + self.widget("net-routev4-gateway").set_text("") return # We've got a valid IP @@ -260,7 +296,16 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("net-dhcpv4-start").set_sensitive(False) self.widget("net-dhcpv4-end").set_sensitive(False) + if self.get_config_routev4_enable(): + self.widget("net-routev4-network").set_sensitive(True) + self.widget("net-routev4-gateway").set_sensitive(True) + else: + self.widget("net-routev4-network").set_sensitive(False) + self.widget("net-routev4-gateway").set_sensitive(False) + def change_ipv6_network(self, src): + ignore = src + ip = self.get_config_ip6() green = Gdk.Color.parse("#c0ffc0")[1] red = Gdk.Color.parse("#ffc0c0")[1] @@ -274,12 +319,16 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("net-info-type-ip6").set_text("") self.widget("net-dhcpv6-start").set_text("") self.widget("net-dhcpv6-end").set_text("") + self.widget("net-routev6-network").set_text("") + self.widget("net-routev6-gateway").set_text("") return - if ip.prefixlen != 64 or not ip.is_private: - src.modify_bg(Gtk.StateType.NORMAL, red) - else: - src.modify_bg(Gtk.StateType.NORMAL, green) + color = green + if not ip.is_private: + color = red + if ip.prefixlen != 64: + color = red + src.modify_bg(Gtk.StateType.NORMAL, color) if ip.prefixlen != 64: self.widget("net-info-gateway-ip6").set_text("") @@ -306,37 +355,135 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("net-dhcpv6-start").set_sensitive(False) self.widget("net-dhcpv6-end").set_sensitive(False) + if self.get_config_routev6_enable(): + self.widget("net-routev6-network").set_sensitive(True) + self.widget("net-routev6-gateway").set_sensitive(True) + else: + self.widget("net-routev6-network").set_sensitive(False) + self.widget("net-routev6-gateway").set_sensitive(False) + + + def change_routev4_enable(self, src): + ignore = src + + white = Gdk.Color.parse("#f0f0f0")[1] + ntwk = self.widget("net-routev4-network") + gway = self.widget("net-routev4-gateway") + ntwk.modify_bg(Gtk.StateType.NORMAL, white) + gway.modify_bg(Gtk.StateType.NORMAL, white) + ntwk.set_text("") + gway.set_text("") + + if self.get_config_routev4_enable(): + ntwk.set_sensitive(True) + gway.set_sensitive(True) + else: + ntwk.set_sensitive(False) + gway.set_sensitive(False) + + def get_config_routev4_network(self): + if not self.get_config_routev4_enable(): + return None + return self.widget("net-routev4-network").get_text() + + def get_config_routev4_gateway(self): + if not self.get_config_routev4_enable(): + return None + return self.widget("net-routev4-gateway").get_text() + + def get_route_addr(self, addrStr): + if addrStr is None: + return None + try: + addr = ipaddr.IPNetwork(addrStr) + except: + addr = None + return addr + + def change_routev4_network(self, src): + ignore = src + + ntwk = self.get_config_routev4_network() + ipAddr = self.get_config_ip4() + black = Gdk.Color.parse("#000000")[1] + src.modify_text(Gtk.StateType.NORMAL, black) + + if ipAddr is None or ntwk is None: + white = Gdk.Color.parse("#f0f0f0")[1] + src.modify_bg(Gtk.StateType.NORMAL, white) + return + addr = self.get_route_addr(ntwk) + red = Gdk.Color.parse("#ffc0c0")[1] + green = Gdk.Color.parse("#c0ffc0")[1] + color = green + if addr is None: + color = red + else: + if addr.version != 4: + color = red + if addr.prefixlen > 28: + color = red + src.modify_bg(Gtk.StateType.NORMAL, color) + + def change_routev4_gateway(self, src): + ignore = src + + gway = self.get_config_routev4_gateway() + ipAddr = self.get_config_ip4() + black = Gdk.Color.parse("#000000")[1] + src.modify_text(Gtk.StateType.NORMAL, black) + + if ipAddr is None or gway is None: + white = Gdk.Color.parse("#f0f0f0")[1] + src.modify_bg(Gtk.StateType.NORMAL, white) + return + addr = self.get_route_addr(gway) + red = Gdk.Color.parse("#ffc0c0")[1] + green = Gdk.Color.parse("#c0ffc0")[1] + color = green + if addr is None: + color = red + else: + if addr.version != 4: + color = red + if not ipAddr.overlaps(addr): + color = red + if addr.prefixlen != 32: + color = red + src.modify_bg(Gtk.StateType.NORMAL, color) def change_dhcpv4_enable(self, src): ignore = src white = Gdk.Color.parse("#f0f0f0")[1] - start4 = self.widget("net-dhcpv4-start") - end4 = self.widget("net-dhcpv4-end") - start4.modify_bg(Gtk.StateType.NORMAL, white) - end4.modify_bg(Gtk.StateType.NORMAL, white) - start4.set_text("") - end4.set_text("") + start = self.widget("net-dhcpv4-start") + end = self.widget("net-dhcpv4-end") + start.modify_bg(Gtk.StateType.NORMAL, white) + end.modify_bg(Gtk.StateType.NORMAL, white) + start.set_text("") + end.set_text("") if not self.get_config_dhcpv4_enable(): - start4.set_sensitive(False) - end4.set_sensitive(False) + start.set_sensitive(False) + end.set_sensitive(False) else: - start4.set_sensitive(True) - end4.set_sensitive(True) + start.set_sensitive(True) + end.set_sensitive(True) ip = self.get_config_ip4() if ip: - start = int(ip.numhosts / 2) - end = int(ip.numhosts - 2) - start4.set_text(str(ip.network + start)) - end4.set_text(str(ip.network + end)) + start.set_text(str(ip.network + int(ip.numhosts / 2))) + end.set_text(str(ip.network + int(ip.numhosts - 2))) def change_dhcpv4_start(self, src): + ignore = src + start = self.get_config_dhcpv4_start() self.change_dhcpv4(src, start) def change_dhcpv4_end(self, src): + ignore = src + end = self.get_config_dhcpv4_end() self.change_dhcpv4(src, end) @@ -344,43 +491,112 @@ class vmmCreateNetwork(vmmGObjectUI): ip = self.get_config_ip4() black = Gdk.Color.parse("#000000")[1] src.modify_text(Gtk.StateType.NORMAL, black) - if not ip: - return - if addr is None: + if ip is None or addr is None: white = Gdk.Color.parse("#f0f0f0")[1] src.modify_bg(Gtk.StateType.NORMAL, white) - elif not ip.overlaps(addr): + return + if addr.version != 4 or not ip.overlaps(addr): red = Gdk.Color.parse("#ffc0c0")[1] src.modify_bg(Gtk.StateType.NORMAL, red) else: green = Gdk.Color.parse("#c0ffc0")[1] src.modify_bg(Gtk.StateType.NORMAL, green) - def change_dhcpv6_enable(self, src): - ignore = src - + def change_routev6_enable(self, src): white = Gdk.Color.parse("#f0f0f0")[1] - start6 = self.widget("net-dhcpv6-start") - end6 = self.widget("net-dhcpv6-end") - start6.modify_bg(Gtk.StateType.NORMAL, white) - end6.modify_bg(Gtk.StateType.NORMAL, white) - start6.set_text("") - end6.set_text("") + ntwk = self.widget("net-routev6-network") + gway = self.widget("net-routev6-gateway") + ntwk.modify_bg(Gtk.StateType.NORMAL, white) + gway.modify_bg(Gtk.StateType.NORMAL, white) + ntwk.set_text("") + gway.set_text("") + + if self.get_config_routev6_enable(): + ntwk.set_sensitive(True) + gway.set_sensitive(True) + else: + ntwk.set_sensitive(False) + gway.set_sensitive(False) + + def get_config_routev6_network(self): + if not self.get_config_routev6_enable(): + return None + return self.widget("net-routev6-network").get_text() + + def get_config_routev6_gateway(self): + if not self.get_config_routev6_enable(): + return None + return self.widget("net-routev6-gateway").get_text() + + def change_routev6_network(self, src): + ntwk = self.get_config_routev6_network() + ip = self.get_config_ip6() + black = Gdk.Color.parse("#000000")[1] + src.modify_text(Gtk.StateType.NORMAL, black) + + if ip is None or ntwk is None: + white = Gdk.Color.parse("#f0f0f0")[1] + src.modify_bg(Gtk.StateType.NORMAL, white) + return + addr = self.get_route_addr(ntwk) + red = Gdk.Color.parse("#ffc0c0")[1] + green = Gdk.Color.parse("#c0ffc0")[1] + color = green + if addr is None: + color = red + else: + if addr.version != 6: + color = red + if addr.prefixlen > 64: + color = red + src.modify_bg(Gtk.StateType.NORMAL, color) + + def change_routev6_gateway(self, src): + gway = self.get_config_routev6_gateway() + ip = self.get_config_ip6() + black = Gdk.Color.parse("#000000")[1] + src.modify_text(Gtk.StateType.NORMAL, black) + + if ip is None or gway is None: + white = Gdk.Color.parse("#f0f0f0")[1] + src.modify_bg(Gtk.StateType.NORMAL, white) + return + addr = self.get_route_addr(gway) + red = Gdk.Color.parse("#ffc0c0")[1] + green = Gdk.Color.parse("#c0ffc0")[1] + color = green + if addr is None: + color = red + else: + if addr.version != 6: + color = red + if not ip.overlaps(addr): + color = red + if addr.prefixlen != 128: + color = red + src.modify_bg(Gtk.StateType.NORMAL, color) + + def change_dhcpv6_enable(self, src): + white = Gdk.Color.parse("#f0f0f0")[1] + start = self.widget("net-dhcpv6-start") + end = self.widget("net-dhcpv6-end") + start.modify_bg(Gtk.StateType.NORMAL, white) + end.modify_bg(Gtk.StateType.NORMAL, white) + start.set_text("") + end.set_text("") if not self.get_config_dhcpv6_enable(): - start6.set_sensitive(False) - end6.set_sensitive(False) + start.set_sensitive(False) + end.set_sensitive(False) else: - start6.set_sensitive(True) - end6.set_sensitive(True) + start.set_sensitive(True) + end.set_sensitive(True) ip = self.get_config_ip6() if ip: - start = 256 - end = 512 - 1 - start6.set_text(str(ip.network + start)) - end6.set_text(str(ip.network + end)) + start.set_text(str(ip.network + 256)) + end.set_text(str(ip.network + 511)) def change_dhcpv6_start(self, src): start = self.get_config_dhcpv6_start() @@ -394,13 +610,12 @@ class vmmCreateNetwork(vmmGObjectUI): ip = self.get_config_ip6() black = Gdk.Color.parse("#000000")[1] src.modify_text(Gtk.StateType.NORMAL, black) - if not ip: - return - if addr is None: + if ip is None or addr is None: white = Gdk.Color.parse("#f0f0f0")[1] src.modify_bg(Gtk.StateType.NORMAL, white) - elif not ip.overlaps(addr): + return + if addr.version != 6 or not ip.overlaps(addr): red = Gdk.Color.parse("#ffc0c0")[1] src.modify_bg(Gtk.StateType.NORMAL, red) else: @@ -451,13 +666,13 @@ class vmmCreateNetwork(vmmGObjectUI): return ipaddr.IPNetwork(self.widget("net-dhcpv6-start").get_text()) except: return None + def get_config_dhcpv6_end(self): try: return ipaddr.IPNetwork(self.widget("net-dhcpv6-end").get_text()) except: return None - def get_config_forwarding(self): if self.widget("net-forward-none").get_active(): return [None, None] @@ -483,6 +698,12 @@ class vmmCreateNetwork(vmmGObjectUI): def get_config_dhcpv6_enable(self): return self.widget("net-dhcpv6-enable").get_active() + def get_config_routev4_enable(self): + return self.widget("net-routev4-enable").get_active() + + def get_config_routev6_enable(self): + return self.widget("net-routev6-enable").get_active() + def populate_summary(self): self.widget("summary-name").set_text(self.get_config_name()) self.widget("summary-domain").set_text(self.get_config_domain_name()) @@ -495,7 +716,7 @@ class vmmCreateNetwork(vmmGObjectUI): if ip: self.widget("label-ip4-gateway").show() self.widget("summary-ip4-gateway").show() - self.widget("label-ip4-network").set_text(_("Network:")) + self.widget("label-ip4-network").set_text(_("Network Address / prefix:")) self.widget("summary-ip4-network").set_text(str(ip)) self.widget("summary-ip4-gateway").set_text(str(ip.network + 1)) else: @@ -509,7 +730,7 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("summary-dhcp-end").show() start = self.get_config_dhcpv4_start() end = self.get_config_dhcpv4_end() - self.widget("label-dhcp-start").set_text("Start Address:") + self.widget("label-dhcp-start").set_text("DHCPv4 Start Address:") if start and end: self.widget("summary-dhcp-start").set_text(str(start.network)) self.widget("summary-dhcp-end").set_text(str(end.network)) @@ -522,6 +743,32 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("label-dhcp-start").set_text(_("DHCPv4 Status:")) self.widget("summary-dhcp-start").set_text(_("Disabled")) + if ip and self.get_config_routev4_enable(): + self.widget("label-routev4-network").show() + self.widget("label-routev4-gateway").show() + self.widget("summary-routev4-network").show() + self.widget("summary-routev4-gateway").show() + self.widget("summary-routev4-network").set_text("") + self.widget("summary-routev4-gateway").set_text("") + ntwk = self.get_config_routev4_network() + try: + naddr = ipaddr.IPNetwork(ntwk) + except: + naddr = None + gway = self.get_config_routev4_gateway() + try: + gaddr = ipaddr.IPNetwork(gway) + except: + gaddr = None + if naddr and gaddr: + self.widget("summary-routev4-network").set_text(str(naddr)) + self.widget("summary-routev4-gateway").set_text(str(gaddr.network)) + else: + self.widget("label-routev4-network").hide() + self.widget("label-routev4-gateway").hide() + self.widget("summary-routev4-network").hide() + self.widget("summary-routev4-gateway").hide() + forward_txt = "" dev, mode = self.get_config_forwarding() forward_txt = vmmNetwork.pretty_desc(mode, dev) @@ -531,7 +778,7 @@ class vmmCreateNetwork(vmmGObjectUI): if ip: self.widget("label-ip6-gateway").show() self.widget("summary-ip6-gateway").show() - self.widget("label-ip6-network").set_text(_("Network:")) + self.widget("label-ip6-network").set_text(_("Network Address / prefix:")) self.widget("summary-ip6-network").set_text(str(ip)) self.widget("summary-ip6-gateway").set_text(str(ip.network + 1)) else: @@ -546,7 +793,7 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("summary-dhcpv6-end").show() start = self.get_config_dhcpv6_start() end = self.get_config_dhcpv6_end() - self.widget("label-dhcpv6-start").set_text("Start Address:") + self.widget("label-dhcpv6-start").set_text("DHCPv6 Start Address:") if start and end: self.widget("summary-dhcpv6-start").set_text(str(start.network)) self.widget("summary-dhcpv6-end").set_text(str(end.network)) @@ -558,6 +805,34 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("summary-dhcpv6-end").hide() self.widget("label-dhcpv6-start").set_text(_("DHCPv6 Status:")) self.widget("summary-dhcpv6-start").set_text(_("Disabled")) + + if ip and self.get_config_routev6_enable(): + self.widget("label-routev6-network").show() + self.widget("label-routev6-gateway").show() + self.widget("summary-routev6-network").show() + self.widget("summary-routev6-gateway").show() + self.widget("summary-routev6-network").set_text("") + self.widget("summary-routev6-gateway").set_text("") + ntwk = self.get_config_routev6_network() + try: + naddr = ipaddr.IPNetwork(ntwk) + except: + naddr = None + gway = self.get_config_routev6_gateway() + try: + gaddr = ipaddr.IPNetwork(gway) + except: + gaddr = None + if naddr and gaddr: + self.widget("summary-routev6-network").set_text(str(naddr)) + self.widget("summary-routev6-gateway").set_text(str(gaddr.network)) + else: + self.widget("label-routev6-network").hide() + self.widget("label-routev6-gateway").hide() + self.widget("summary-routev6-network").hide() + self.widget("summary-routev6-gateway").hide() + + if ip: self.widget("summary-ipv6-forwarding").set_text("Routed network") else: @@ -574,15 +849,14 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("net-ipv4-network").set_sensitive(False) self.widget("net-dhcpv4-start").set_sensitive(False) self.widget("net-dhcpv4-end").set_sensitive(False) - return - self.widget("net-ipv4-network").set_sensitive(True) + else: + self.widget("net-ipv4-network").set_sensitive(True) if not self.get_config_dhcpv4_enable(): self.widget("net-dhcpv4-end").set_text("") self.widget("net-dhcpv4-start").set_text("") self.widget("net-dhcpv4-start").set_sensitive(False) self.widget("net-dhcpv4-end").set_sensitive(False) - return else: ip = self.get_config_ip4() if ip: @@ -603,15 +877,16 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("net-ipv6-network").set_sensitive(False) self.widget("net-dhcpv6-start").set_sensitive(False) self.widget("net-dhcpv6-end").set_sensitive(False) - return - self.widget("net-ipv6-network").set_sensitive(True) + self.widget("net-routev6-network").set_sensitive(False) + self.widget("net-routev6-gateway").set_sensitive(False) + else: + self.widget("net-ipv6-network").set_sensitive(True) if not self.get_config_dhcpv6_enable(): self.widget("net-dhcpv6-end").set_text("") self.widget("net-dhcpv6-start").set_text("") self.widget("net-dhcpv6-start").set_sensitive(False) self.widget("net-dhcpv6-end").set_sensitive(False) - return else: ip = self.get_config_ip6() if ip: @@ -622,6 +897,21 @@ class vmmCreateNetwork(vmmGObjectUI): self.widget("net-dhcpv6-end").set_text(str(ip.network + end)) self.widget("net-dhcpv6-start").set_sensitive(True) self.widget("net-dhcpv6-end").set_sensitive(True) + if not self.get_config_routev6_enable(): + self.widget("net-routev6-network").set_text("") + self.widget("net-routev6-gateway").set_text("") + self.widget("net-routev6-network").set_sensitive(False) + self.widget("net-routev6-gateway").set_sensitive(False) + else: + self.widget("net-routev6-network").set_text("") + self.widget("net-routev6-gateway").set_text("") + self.widget("net-routev6-network").set_sensitive(True) + self.widget("net-routev6-gateway").set_sensitive(True) + + def populate_misc(self): + name = self.widget("net-name").get_text() + if self.widget("net-domain-name").get_text() == "": + self.widget("net-domain-name").set_text(name) def page_changed(self, ignore1, ignore2, page_number): if page_number == PAGE_NAME: @@ -632,6 +922,8 @@ class vmmCreateNetwork(vmmGObjectUI): self.populate_ipv4() elif page_number == PAGE_IPV6: self.populate_ipv6() + elif page_number == PAGE_MISC: + self.populate_misc() elif page_number == PAGE_SUMMARY: self.populate_summary() @@ -698,6 +990,39 @@ class vmmCreateNetwork(vmmGObjectUI): xml += " \n" xml += " \n" + ntwk = self.get_config_routev4_network() + try: + netaddr = ipaddr.IPNetwork(ntwk) + except: + netaddr = None + gway = self.get_config_routev4_gateway() + try: + gwaddr = ipaddr.IPNetwork(gway) + except: + gwaddr = None + if netaddr and gwaddr: + xml += " 28: + ntwkbad = True + gaddr = self.get_route_addr(gway) + if gaddr is None: + gwaybad = True + else: + if gaddr.version != 4: + gwaybad = True + if gaddr.prefixlen != 32: + gwaybad = True + if not ip.overlaps(gaddr): + gwaybad = True + if ntwkbad: + return self.err.val_err(_("Invalid static route"), + _("The network address is incorrect.")) + if gwaybad: + return self.err.val_err(_("Invalid static route"), + _("The gateway address is incorrect.")) + return True def validate_ipv6(self): @@ -812,6 +1172,41 @@ class vmmCreateNetwork(vmmGObjectUI): (_("The DHCPv6 end address is not with the network %s") % (str(ip)))) + enabled = self.get_config_routev6_enable() + if enabled: + ntwk = self.get_config_routev6_network() + ntwkbad = False + gway = self.get_config_routev6_gateway() + gwaybad = False + if ntwk is None or gway is None: + return True + if ntwk == "" and gway == "": + return True + naddr = self.get_route_addr(ntwk) + if naddr is None: + ntwkbad = True + else: + if naddr.version != 6: + ntwkbad = True + if naddr.prefixlen > 64: + ntwkbad = True + gaddr = self.get_route_addr(gway) + if gaddr is None: + gwaybad = True + else: + if gaddr.version != 6: + gwaybad = True + if gaddr.prefixlen != 128: + gwaybad = True + if not ip.overlaps(gaddr): + gwaybad = True + if ntwkbad: + return self.err.val_err(_("Invalid static route"), + _("The network address is incorrect.")) + if gwaybad: + return self.err.val_err(_("Invalid static route"), + _("The gateway address is incorrect.")) + return True def validate_miscellaneous(self): diff --git a/virtManager/host.py b/virtManager/host.py index 100ac8da..6d3ca88e 100644 --- a/virtManager/host.py +++ b/virtManager/host.py @@ -575,7 +575,7 @@ class vmmHost(vmmGObjectUI): 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]) + routeVia = str(route[0]) + ", gateway=" + str(route[1]) self.widget("net-ip4-route-label").show() else: routeVia = _("") @@ -605,7 +605,7 @@ class vmmHost(vmmGObjectUI): iconsize = Gtk.IconSize.MENU icon = Gtk.STOCK_DISCONNECT self.widget("net-ip6-forwarding-icon").set_from_stock(icon, iconsize) - ipv6 = net.get_ipv6_route() + ipv6 = net.get_ipv6_routing() if ipv6: self.widget("net-ip6-forwarding").set_text( _("Isolated network, internal and host routing only")) @@ -622,7 +622,7 @@ class vmmHost(vmmGObjectUI): 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]) + routeVia = str(route[0]) + ", gateway=" + str(route[1]) self.widget("net-ip6-route-label").show() else: routeVia = "" @@ -1081,7 +1081,7 @@ class vmmHost(vmmGObjectUI): str(e)) return - # This will require an interface restart + # XXX: This will require an interface restart self.widget("interface-apply").set_sensitive(False) def interface_startmode_changed(self, src_ignore): diff --git a/virtManager/network.py b/virtManager/network.py index d76e0be6..60ddcb85 100644 --- a/virtManager/network.py +++ b/virtManager/network.py @@ -17,6 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA. # +import logging from virtManager import util import ipaddr @@ -97,14 +98,47 @@ class vmmNetwork(vmmLibvirtObject): def get_autostart(self): return self.net.autostart() + def get_ipv4_static_route(self): + doc = None + ret = None + routeAddr = None + routeVia = None + xml = self.get_xml() + doc = libxml2.parseDoc(xml) + nodes = doc.xpathEval('//route') + for node in nodes: + family = node.xpathEval('string(./@family)') + if not family or family == 'ipv4': + addrStr = node.xpathEval('string(./@address)') + netmaskStr = node.xpathEval('string(./@netmask)') + gatewayStr = node.xpathEval('string(./@gateway)') + prefix = node.xpathEval('string(./@prefix)') + if prefix: + prefix = int(prefix) + routeAddr = str(ipaddr.IPNetwork(str(addrStr) + "/" + str(prefix)).masked()) + elif netmaskStr: + netmask = ipaddr.IPAddress(netmaskStr) + network = ipaddr.IPAddress(addrStr) + routeAddr = str(ipaddr.IPNetwork(str(network) + "/" + str(netmask)).masked()) + else: + routeAddr = str(ipaddr.IPNetwork(str(addrStr))) + routeVia = str(ipaddr.IPAddress(str(gatewayStr))) + break + + if doc: + doc.freeDoc() + if routeAddr and routeVia: + ret = [routeAddr, routeVia] + else: + ret = None + return ret + def get_ipv4_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') @@ -118,21 +152,10 @@ class vmmNetwork(vmmLibvirtObject): 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 is 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 @@ -155,20 +178,45 @@ class vmmNetwork(vmmLibvirtObject): 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 + route = self.get_ipv4_static_route() return [ret, dhcp, route] + def get_ipv6_static_route(self): + doc = None + ret = None + routeAddr = None + routeVia = None + xml = self.get_xml() + doc = libxml2.parseDoc(xml) + nodes = doc.xpathEval('//route') + for node in nodes: + family = node.xpathEval('string(./@family)') + if family and family == 'ipv6': + addrStr = node.xpathEval('string(./@address)') + prefix = node.xpathEval('string(./@prefix)') + gatewayStr = node.xpathEval('string(./@gateway)') + if prefix: + prefix = int(prefix) + routeAddr = str(ipaddr.IPNetwork(str(addrStr) + "/" + str(prefix)).masked()) + else: + routeAddr = str(ipaddr.IPNetwork(str(addrStr))) + routeVia = str(ipaddr.IPAddress(str(gatewayStr))) + break + + if doc: + doc.freeDoc() + if routeAddr and routeVia: + ret = [routeAddr, routeVia] + else: + ret = None + return ret + 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') @@ -182,21 +230,10 @@ class vmmNetwork(vmmLibvirtObject): 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 is 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 @@ -214,10 +251,7 @@ class vmmNetwork(vmmLibvirtObject): 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 + route = self.get_ipv6_static_route() return [ret, dhcp, route] def get_name_domain(self): @@ -225,10 +259,10 @@ class vmmNetwork(vmmLibvirtObject): name_domain = util.xpath(xml, "/network/domain/@name") return name_domain - def get_ipv6_route(self): + def get_ipv6_routing(self): xml = self.get_xml() - ipv6_route = util.xpath(xml, "/network/@ipv6") - return ipv6_route + ipv6_routing = util.xpath(xml, "/network/@ipv6") + return ipv6_routing def get_ipv4_forward(self): xml = self.get_xml()