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()