mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
With this patch, basic IPv6 support has been added to the network creation wizard. It includes changes to both the glade-3 ui and the related python code. There have been some significant changes made to both files for IPv6 support and some additional capabilities. This update includes the fix so color will work in the network creation wizard. Besides basic IPv6 support, this includes optionally specifying a DNS domain name and enabling IPv6 internal routing if no IPv6 address is specified. . Signed-off-by: Gene Czarcinski <gene@czarc.net>
837 lines
32 KiB
Python
837 lines
32 KiB
Python
#
|
|
# Copyright (C) 2006-2007 Red Hat, Inc.
|
|
# Copyright (C) 2006 Hugh O. Brock <hbrock@redhat.com>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
# MA 02110-1301 USA.
|
|
#
|
|
|
|
import logging
|
|
import re
|
|
|
|
import ipaddr
|
|
|
|
from gi.repository import Gtk
|
|
from gi.repository import Gdk
|
|
|
|
from virtManager.network import vmmNetwork
|
|
from virtManager.baseclass import vmmGObjectUI
|
|
|
|
PAGE_INTRO = 0
|
|
PAGE_NAME = 1
|
|
PAGE_IPV4 = 2
|
|
PAGE_IPV6 = 3
|
|
PAGE_MISC = 4
|
|
PAGE_SUMMARY = 5
|
|
|
|
|
|
class vmmCreateNetwork(vmmGObjectUI):
|
|
def __init__(self, conn):
|
|
vmmGObjectUI.__init__(self, "vmm-create-net.ui", "vmm-create-net")
|
|
self.conn = conn
|
|
|
|
self.builder.connect_signals({
|
|
"on_create_pages_switch_page" : self.page_changed,
|
|
"on_create_cancel_clicked" : self.close,
|
|
"on_vmm_create_delete_event" : self.close,
|
|
"on_create_forward_clicked" : self.forward,
|
|
"on_create_back_clicked" : self.back,
|
|
"on_create_finish_clicked" : self.finish,
|
|
|
|
"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-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-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,
|
|
})
|
|
self.bind_escape_key_close()
|
|
|
|
finish_img = Gtk.Image.new_from_stock(Gtk.STOCK_QUIT,
|
|
Gtk.IconSize.BUTTON)
|
|
self.widget("create-finish").set_image(finish_img)
|
|
|
|
self.set_initial_state()
|
|
|
|
def show(self, parent):
|
|
logging.debug("Showing new network wizard")
|
|
self.reset_state()
|
|
self.topwin.set_transient_for(parent)
|
|
self.topwin.present()
|
|
|
|
def is_visible(self):
|
|
return self.topwin.get_visible()
|
|
|
|
def close(self, ignore1=None, ignore2=None):
|
|
logging.debug("Closing new network wizard")
|
|
self.topwin.hide()
|
|
return 1
|
|
|
|
def _cleanup(self):
|
|
self.conn = None
|
|
|
|
def set_initial_state(self):
|
|
notebook = self.widget("create-pages")
|
|
notebook.set_show_tabs(False)
|
|
|
|
black = Gdk.Color.parse("#000")[1]
|
|
for num in range(PAGE_SUMMARY + 1):
|
|
name = "page" + str(num) + "-title"
|
|
self.widget(name).modify_bg(Gtk.StateType.NORMAL, black)
|
|
|
|
fw_list = self.widget("net-forward")
|
|
# [ label, dev name ]
|
|
fw_model = Gtk.ListStore(str, str)
|
|
fw_list.set_model(fw_model)
|
|
text = Gtk.CellRendererText()
|
|
fw_list.pack_start(text, True)
|
|
fw_list.add_attribute(text, 'text', 0)
|
|
|
|
fw_model.append([_("Any physical device"), None])
|
|
for path in self.conn.list_net_device_paths():
|
|
net = self.conn.get_net_device(path)
|
|
fw_model.append([_("Physical device %s") % (net.get_name()),
|
|
net.get_name()])
|
|
|
|
mode_list = self.widget("net-forward-mode")
|
|
# [ label, mode ]
|
|
mode_model = Gtk.ListStore(str, str)
|
|
mode_list.set_model(mode_model)
|
|
text = Gtk.CellRendererText()
|
|
mode_list.pack_start(text, True)
|
|
mode_list.add_attribute(text, 'text', 0)
|
|
|
|
mode_model.append([_("NAT"), "nat"])
|
|
mode_model.append([_("Routed"), "route"])
|
|
|
|
def reset_state(self):
|
|
notebook = self.widget("create-pages")
|
|
notebook.set_current_page(0)
|
|
|
|
self.page_changed(None, None, 0)
|
|
|
|
self.widget("net-name").set_text("")
|
|
self.widget("net-name").set_sensitive(True)
|
|
self.widget("net-domain-name").set_text("")
|
|
self.widget("net-domain-name").set_sensitive(True)
|
|
self.widget("net-ipv4-enable").set_active(True)
|
|
self.widget("net-ipv4-network").set_text("192.168.100.0/24")
|
|
self.widget("net-ipv4-network").set_sensitive(True)
|
|
self.widget("net-dhcpv4-enable").set_active(True)
|
|
self.widget("net-dhcpv4-start").set_text("192.168.100.128")
|
|
self.widget("net-dhcpv4-end").set_text("192.168.100.254")
|
|
self.widget("net-dhcpv4-start").set_sensitive(True)
|
|
self.widget("net-dhcpv4-end").set_sensitive(True)
|
|
self.widget("net-ipv6-enable").set_active(False)
|
|
self.widget("net-ipv6-network").set_text("")
|
|
self.widget("net-ipv6-network").set_sensitive(True)
|
|
self.widget("net-dhcpv6-enable").set_active(False)
|
|
self.widget("net-dhcpv6-start").set_text("")
|
|
self.widget("net-dhcpv6-end").set_text("")
|
|
self.widget("net-forward-none").set_active(True)
|
|
|
|
self.widget("net-forward").set_active(0)
|
|
self.widget("net-forward-mode").set_active(0)
|
|
self.widget("net-enable-ipv6-networking").set_active(False)
|
|
|
|
|
|
def forward(self, ignore=None):
|
|
notebook = self.widget("create-pages")
|
|
if self.validate(notebook.get_current_page()) is not True:
|
|
return
|
|
|
|
self.widget("create-forward").grab_focus()
|
|
notebook.next_page()
|
|
|
|
def back(self, ignore=None):
|
|
notebook = self.widget("create-pages")
|
|
notebook.prev_page()
|
|
|
|
def change_ipv4_enable(self, 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")
|
|
if self.get_config_ipv4_enable():
|
|
net4.set_sensitive(True)
|
|
net4.set_text("")
|
|
net4.modify_bg(Gtk.StateType.NORMAL, white)
|
|
if self.get_config_dhcpv4_enable():
|
|
start4.set_sensitive(True)
|
|
end4.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)
|
|
|
|
def change_ipv6_enable(self, 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")
|
|
if self.get_config_ipv6_enable():
|
|
net6.set_sensitive(True)
|
|
net6.set_text("")
|
|
net6.modify_bg(Gtk.StateType.NORMAL, white)
|
|
if self.get_config_dhcpv6_enable():
|
|
start6.set_sensitive(True)
|
|
end6.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)
|
|
|
|
def change_network(self, src):
|
|
ip = self.get_config_ip4()
|
|
green = Gdk.Color.parse("#c0ffc0")[1]
|
|
red = Gdk.Color.parse("#ffc0c0")[1]
|
|
black = Gdk.Color.parse("#000000")[1]
|
|
src.modify_text(Gtk.StateType.NORMAL, black)
|
|
|
|
# No IP specified or invalid IP
|
|
if ip is None or ip.version != 4:
|
|
src.modify_bg(Gtk.StateType.NORMAL, red)
|
|
self.widget("net-info-gateway").set_text("")
|
|
self.widget("net-info-type").set_text("")
|
|
self.widget("net-dhcpv4-start").set_text("")
|
|
self.widget("net-dhcpv4-end").set_text("")
|
|
return
|
|
|
|
# We've got a valid IP
|
|
if ip.numhosts < 16 or not ip.is_private:
|
|
src.modify_bg(Gtk.StateType.NORMAL, red)
|
|
else:
|
|
src.modify_bg(Gtk.StateType.NORMAL, green)
|
|
|
|
if ip.prefixlen == 32:
|
|
self.widget("net-info-gateway").set_text("")
|
|
else:
|
|
self.widget("net-info-gateway").set_text(str(ip.network + 1))
|
|
|
|
if ip.is_private:
|
|
self.widget("net-info-type").set_text(_("Private"))
|
|
else:
|
|
self.widget("net-info-type").set_text(_("Other/Public"))
|
|
|
|
if self.get_config_dhcpv4_enable():
|
|
self.widget("net-dhcpv4-start").set_sensitive(True)
|
|
self.widget("net-dhcpv4-end").set_sensitive(True)
|
|
start = int(ip.numhosts / 2)
|
|
end = int(ip.numhosts - 2)
|
|
self.widget("net-dhcpv4-start").set_text(str(ip.network + start))
|
|
self.widget("net-dhcpv4-end").set_text(str(ip.network + end))
|
|
else:
|
|
self.widget("net-dhcpv4-start").set_sensitive(False)
|
|
self.widget("net-dhcpv4-end").set_sensitive(False)
|
|
|
|
def change_ipv6_network(self, src):
|
|
ip = self.get_config_ip6()
|
|
green = Gdk.Color.parse("#c0ffc0")[1]
|
|
red = Gdk.Color.parse("#ffc0c0")[1]
|
|
black = Gdk.Color.parse("#000000")[1]
|
|
src.modify_text(Gtk.StateType.NORMAL, black)
|
|
|
|
# No IP specified or invalid IP
|
|
if ip is None or ip.version != 6:
|
|
src.modify_bg(Gtk.StateType.NORMAL, red)
|
|
self.widget("net-info-gateway-ip6").set_text("")
|
|
self.widget("net-info-type-ip6").set_text("")
|
|
self.widget("net-dhcpv6-start").set_text("")
|
|
self.widget("net-dhcpv6-end").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)
|
|
|
|
if ip.prefixlen != 64:
|
|
self.widget("net-info-gateway-ip6").set_text("")
|
|
else:
|
|
self.widget("net-info-gateway-ip6").set_text(str(ip.network + 1))
|
|
|
|
if ip.is_private:
|
|
self.widget("net-info-type-ip6").set_text(_("Private"))
|
|
elif ip.is_reserved:
|
|
self.widget("net-info-type-ip6").set_text(_("Reserved"))
|
|
elif ip.is_unspecified:
|
|
self.widget("net-info-type-ip6").set_text(_("Unspecified"))
|
|
else:
|
|
self.widget("net-info-type-ip6").set_text(_("Other/Public"))
|
|
|
|
if self.get_config_dhcpv6_enable():
|
|
self.widget("net-dhcpv6-start").set_sensitive(True)
|
|
self.widget("net-dhcpv6-end").set_sensitive(True)
|
|
start = 256
|
|
end = 512 - 1
|
|
self.widget("net-dhcpv6-start").set_text(str(ip.network + start))
|
|
self.widget("net-dhcpv6-end").set_text(str(ip.network + end))
|
|
else:
|
|
self.widget("net-dhcpv6-start").set_sensitive(False)
|
|
self.widget("net-dhcpv6-end").set_sensitive(False)
|
|
|
|
|
|
def change_dhcpv4_enable(self, 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("")
|
|
|
|
if not self.get_config_dhcpv4_enable():
|
|
start4.set_sensitive(False)
|
|
end4.set_sensitive(False)
|
|
else:
|
|
start4.set_sensitive(True)
|
|
end4.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))
|
|
|
|
def change_dhcpv4_start(self, src):
|
|
start = self.get_config_dhcpv4_start()
|
|
self.change_dhcpv4(src, start)
|
|
|
|
def change_dhcpv4_end(self, src):
|
|
end = self.get_config_dhcpv4_end()
|
|
self.change_dhcpv4(src, end)
|
|
|
|
def change_dhcpv4(self, src, addr):
|
|
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:
|
|
white = Gdk.Color.parse("#f0f0f0")[1]
|
|
src.modify_bg(Gtk.StateType.NORMAL, white)
|
|
elif 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):
|
|
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("")
|
|
if not self.get_config_dhcpv6_enable():
|
|
start6.set_sensitive(False)
|
|
end6.set_sensitive(False)
|
|
|
|
else:
|
|
start6.set_sensitive(True)
|
|
end6.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))
|
|
|
|
def change_dhcpv6_start(self, src):
|
|
start = self.get_config_dhcpv6_start()
|
|
self.change_dhcpv6(src, start)
|
|
|
|
def change_dhcpv6_end(self, src):
|
|
end = self.get_config_dhcpv6_end()
|
|
self.change_dhcpv6(src, end)
|
|
|
|
def change_dhcpv6(self,src,addr):
|
|
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:
|
|
white = Gdk.Color.parse("#f0f0f0")[1]
|
|
src.modify_bg(Gtk.StateType.NORMAL, white)
|
|
elif 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_forward_type(self, src_ignore):
|
|
skip_fwd = self.widget("net-forward-none").get_active()
|
|
|
|
self.widget("net-forward-mode").set_sensitive(not skip_fwd)
|
|
self.widget("net-forward").set_sensitive(not skip_fwd)
|
|
|
|
def get_config_name(self):
|
|
return self.widget("net-name").get_text()
|
|
|
|
def get_config_domain_name(self):
|
|
return self.widget("net-domain-name").get_text()
|
|
|
|
def get_config_ip4(self):
|
|
if not self.get_config_ipv4_enable():
|
|
return None
|
|
try:
|
|
return ipaddr.IPNetwork(self.widget("net-ipv4-network").get_text())
|
|
except:
|
|
return None
|
|
|
|
def get_config_dhcpv4_start(self):
|
|
try:
|
|
return ipaddr.IPNetwork(self.widget("net-dhcpv4-start").get_text())
|
|
except:
|
|
return None
|
|
def get_config_dhcpv4_end(self):
|
|
try:
|
|
return ipaddr.IPNetwork(self.widget("net-dhcpv4-end").get_text())
|
|
except:
|
|
return None
|
|
|
|
def get_config_ip6(self):
|
|
if not self.get_config_ipv6_enable():
|
|
return None
|
|
try:
|
|
return ipaddr.IPNetwork(self.widget("net-ipv6-network").get_text())
|
|
except:
|
|
return None
|
|
|
|
def get_config_dhcpv6_start(self):
|
|
try:
|
|
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]
|
|
else:
|
|
dev = self.widget("net-forward")
|
|
model = dev.get_model()
|
|
active = dev.get_active()
|
|
name = model[active][1]
|
|
|
|
mode_w = self.widget("net-forward-mode")
|
|
mode = mode_w.get_model()[mode_w.get_active()][1]
|
|
return [name, mode]
|
|
|
|
def get_config_ipv4_enable(self):
|
|
return self.widget("net-ipv4-enable").get_active()
|
|
|
|
def get_config_ipv6_enable(self):
|
|
return self.widget("net-ipv6-enable").get_active()
|
|
|
|
def get_config_dhcpv4_enable(self):
|
|
return self.widget("net-dhcpv4-enable").get_active()
|
|
|
|
def get_config_dhcpv6_enable(self):
|
|
return self.widget("net-dhcpv6-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())
|
|
self.widget("summary-ip4-network").set_text("");
|
|
self.widget("summary-ip4-gateway").set_text("");
|
|
self.widget("summary-ip6-network").set_text("");
|
|
self.widget("summary-ip6-gateway").set_text("");
|
|
|
|
ip = self.get_config_ip4()
|
|
if ip:
|
|
self.widget("label-ip4-gateway").show()
|
|
self.widget("summary-ip4-gateway").show()
|
|
self.widget("label-ip4-network").set_text(_("Network:"))
|
|
self.widget("summary-ip4-network").set_text(str(ip))
|
|
self.widget("summary-ip4-gateway").set_text(str(ip.network + 1))
|
|
else:
|
|
self.widget("label-ip4-gateway").hide()
|
|
self.widget("summary-ip4-gateway").hide()
|
|
self.widget("label-ip4-network").set_text("IPv4 Network:")
|
|
self.widget("summary-ip4-network").set_text("Not Defined")
|
|
|
|
if ip and self.get_config_dhcpv4_enable():
|
|
self.widget("label-dhcp-end").show()
|
|
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:")
|
|
if start and end:
|
|
self.widget("summary-dhcp-start").set_text(str(start.network))
|
|
self.widget("summary-dhcp-end").set_text(str(end.network))
|
|
else:
|
|
self.widget("summary-dhcp-start").set_text("?")
|
|
self.widget("summary-dhcp-end").set_text("?")
|
|
else:
|
|
self.widget("label-dhcp-end").hide()
|
|
self.widget("summary-dhcp-end").hide()
|
|
self.widget("label-dhcp-start").set_text(_("DHCPv4 Status:"))
|
|
self.widget("summary-dhcp-start").set_text(_("Disabled"))
|
|
|
|
forward_txt = ""
|
|
dev, mode = self.get_config_forwarding()
|
|
forward_txt = vmmNetwork.pretty_desc(mode, dev)
|
|
self.widget("summary-ipv4-forwarding").set_text(forward_txt)
|
|
|
|
ip = self.get_config_ip6()
|
|
if ip:
|
|
self.widget("label-ip6-gateway").show()
|
|
self.widget("summary-ip6-gateway").show()
|
|
self.widget("label-ip6-network").set_text(_("Network:"))
|
|
self.widget("summary-ip6-network").set_text(str(ip))
|
|
self.widget("summary-ip6-gateway").set_text(str(ip.network + 1))
|
|
else:
|
|
self.widget("label-ip6-gateway").hide()
|
|
self.widget("summary-ip6-gateway").hide()
|
|
self.widget("label-ip6-network").set_text(_("IPV6 Network:"))
|
|
self.widget("summary-ip6-network").set_text(_("Not Defined"))
|
|
|
|
|
|
if ip and self.get_config_dhcpv6_enable():
|
|
self.widget("label-dhcpv6-end").show()
|
|
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:")
|
|
if start and end:
|
|
self.widget("summary-dhcpv6-start").set_text(str(start.network))
|
|
self.widget("summary-dhcpv6-end").set_text(str(end.network))
|
|
else:
|
|
self.widget("summary-dhcpv6-start").set_text("?")
|
|
self.widget("summary-dhcpv6-end").set_text("?")
|
|
else:
|
|
self.widget("label-dhcpv6-end").hide()
|
|
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:
|
|
self.widget("summary-ipv6-forwarding").set_text("Routed network")
|
|
else:
|
|
if self.widget("net-enable-ipv6-networking").get_active():
|
|
self.widget("summary-ipv6-forwarding").set_text("Isolated network, internal routing only")
|
|
else:
|
|
self.widget("summary-ipv6-forwarding").set_text("Isolated network")
|
|
|
|
def populate_ipv4(self):
|
|
if not self.get_config_ipv4_enable():
|
|
self.widget("net-ipv4-network").set_text("")
|
|
self.widget("net-dhcpv4-end").set_text("")
|
|
self.widget("net-dhcpv4-start").set_text("")
|
|
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)
|
|
|
|
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:
|
|
start = int(ip.numhosts / 2)
|
|
end = int(ip.numhosts - 2)
|
|
if self.widget("net-dhcpv4-start").get_text() == "":
|
|
self.widget("net-dhcpv4-start").set_text(str(ip.network + start))
|
|
self.widget("net-dhcpv4-end").set_text(str(ip.network + end))
|
|
self.widget("net-dhcpv4-start").set_sensitive(True)
|
|
self.widget("net-dhcpv4-end").set_sensitive(True)
|
|
|
|
|
|
def populate_ipv6(self):
|
|
if not self.get_config_ipv6_enable():
|
|
self.widget("net-ipv6-network").set_text("")
|
|
self.widget("net-dhcpv6-end").set_text("")
|
|
self.widget("net-dhcpv6-start").set_text("")
|
|
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)
|
|
|
|
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:
|
|
start = 256
|
|
end = 512 - 1
|
|
if self.widget("net-dhcpv6-start").get_text() == "":
|
|
self.widget("net-dhcpv6-start").set_text(str(ip.network + start))
|
|
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)
|
|
|
|
def page_changed(self, ignore1, ignore2, page_number):
|
|
if page_number == PAGE_NAME:
|
|
name_widget = self.widget("net-name")
|
|
name_widget.set_sensitive(True)
|
|
name_widget.grab_focus()
|
|
elif page_number == PAGE_IPV4:
|
|
self.populate_ipv4()
|
|
elif page_number == PAGE_IPV6:
|
|
self.populate_ipv6()
|
|
elif page_number == PAGE_SUMMARY:
|
|
self.populate_summary()
|
|
|
|
if page_number == PAGE_INTRO:
|
|
self.widget("create-back").set_sensitive(False)
|
|
else:
|
|
self.widget("create-back").set_sensitive(True)
|
|
|
|
if page_number == PAGE_SUMMARY:
|
|
self.widget("create-forward").hide()
|
|
self.widget("create-finish").show()
|
|
self.widget("create-finish").grab_focus()
|
|
else:
|
|
self.widget("create-forward").show()
|
|
self.widget("create-finish").hide()
|
|
|
|
|
|
def finish(self, ignore=None):
|
|
name = self.get_config_name()
|
|
dev, mode = self.get_config_forwarding()
|
|
|
|
if self.widget("net-enable-ipv6-networking").get_active():
|
|
xml = "<network ipv6='yes'>\n"
|
|
else:
|
|
xml = "<network>\n"
|
|
|
|
xml += " <name>%s</name>\n" % name
|
|
|
|
domain_name = self.get_config_domain_name()
|
|
if len(domain_name) != 0:
|
|
xml += " <domain name='%s' />\n" % domain_name
|
|
|
|
if mode:
|
|
if dev is not None:
|
|
xml += " <forward mode='%s' dev='%s'/>\n" % (mode, dev)
|
|
else:
|
|
xml += " <forward mode='%s'/>\n" % mode
|
|
|
|
if self.get_config_ipv4_enable():
|
|
ip = self.get_config_ip4()
|
|
xml += " <ip address='%s' netmask='%s'>\n" % (str(ip.network + 1),
|
|
str(ip.netmask))
|
|
|
|
if self.get_config_dhcpv4_enable():
|
|
start = self.get_config_dhcpv4_start()
|
|
end = self.get_config_dhcpv4_end()
|
|
xml += " <dhcp>\n"
|
|
xml += " <range start='%s' end='%s'/>\n" % (str(start.network),
|
|
str(end.network))
|
|
xml += " </dhcp>\n"
|
|
xml += " </ip>\n"
|
|
|
|
if self.get_config_ipv6_enable():
|
|
ip = self.get_config_ip6()
|
|
xml += " <ip family='ipv6' address='%s' prefix='%s'>\n" % (str(ip.network + 1),
|
|
str(ip.prefixlen))
|
|
|
|
if self.get_config_dhcpv6_enable():
|
|
start = self.get_config_dhcpv6_start()
|
|
end = self.get_config_dhcpv6_end()
|
|
xml += " <dhcp>\n"
|
|
xml += " <range start='%s' end='%s'/>\n" % (str(start.network),
|
|
str(end.network))
|
|
xml += " </dhcp>\n"
|
|
xml += " </ip>\n"
|
|
|
|
xml += "</network>\n"
|
|
|
|
logging.debug("Generated network XML:\n" + xml)
|
|
|
|
try:
|
|
self.conn.create_network(xml)
|
|
except Exception, e:
|
|
self.err.show_err(_("Error creating virtual network: %s" % str(e)))
|
|
return
|
|
|
|
self.conn.tick(noStatsUpdate=True)
|
|
self.close()
|
|
|
|
def validate_name(self):
|
|
name_widget = self.widget("net-name")
|
|
name = name_widget.get_text()
|
|
if len(name) > 50 or len(name) == 0:
|
|
retcode = self.err.val_err(_("Invalid Network Name"),
|
|
_("Network name must be non-blank and less than "
|
|
"50 characters"))
|
|
name_widget.grab_focus()
|
|
return retcode
|
|
if re.match("^[a-zA-Z0-9_]*$", name) is None:
|
|
return self.err.val_err(_("Invalid Network Name"),
|
|
_("Network name may contain alphanumeric and '_' "
|
|
"characters only"))
|
|
return True
|
|
|
|
def validate_ipv4(self):
|
|
if not self.get_config_ipv4_enable():
|
|
return True
|
|
ip = self.get_config_ip4()
|
|
if ip is None:
|
|
return self.err.val_err(_("Invalid Network Address"),
|
|
_("The network address could not be understood"))
|
|
|
|
if ip.version != 4:
|
|
return self.err.val_err(_("Invalid Network Address"),
|
|
_("The network must be an IPv4 address"))
|
|
|
|
if ip.numhosts < 16:
|
|
return self.err.val_err(_("Invalid Network Address"),
|
|
_("The network prefix must be at least /28 (16 addresses)"))
|
|
|
|
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?"))
|
|
if not res:
|
|
return False
|
|
|
|
enabled = self.get_config_dhcpv4_enable()
|
|
if enabled:
|
|
start = self.get_config_dhcpv4_start()
|
|
end = self.get_config_dhcpv4_end()
|
|
if enabled and start is None:
|
|
return self.err.val_err(_("Invalid DHCP Address"),
|
|
_("The DHCP start address could not be understood"))
|
|
if enabled and end is None:
|
|
return self.err.val_err(_("Invalid DHCP Address"),
|
|
_("The DHCP end address could not be understood"))
|
|
if enabled and not ip.overlaps(start):
|
|
return self.err.val_err(_("Invalid DHCP Address"),
|
|
(_("The DHCP start address is not with the network %s") %
|
|
(str(ip))))
|
|
if enabled and not ip.overlaps(end):
|
|
return self.err.val_err(_("Invalid DHCP Address"),
|
|
(_("The DHCP end address is not with the network %s") %
|
|
(str(ip))))
|
|
|
|
return True
|
|
|
|
def validate_ipv6(self):
|
|
if not self.get_config_ipv6_enable():
|
|
return True
|
|
ip = self.get_config_ip6()
|
|
if ip is None:
|
|
return self.err.val_err(_("Invalid Network Address"),
|
|
_("The network address could not be understood"))
|
|
|
|
if ip.version != 6:
|
|
return self.err.val_err(_("Invalid Network Address"),
|
|
_("The network must be an IPv6 address"))
|
|
|
|
if ip.prefixlen != 64:
|
|
return self.err.val_err(_("Invalid Network Address"),
|
|
_("For libvirt, the IPv6 network prefix must be 64"))
|
|
|
|
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?"))
|
|
if not res:
|
|
return False
|
|
|
|
enabled = self.get_config_dhcpv6_enable()
|
|
if enabled:
|
|
start = self.get_config_dhcpv6_start()
|
|
end = self.get_config_dhcpv6_end()
|
|
if start is None:
|
|
return self.err.val_err(_("Invalid DHCPv6 Address"),
|
|
_("The DHCPv6 start address could not be understood"))
|
|
if end is None:
|
|
return self.err.val_err(_("Invalid DHCPv6 Address"),
|
|
_("The DHCPv6 end address could not be understood"))
|
|
if not ip.overlaps(start):
|
|
return self.err.val_err(_("Invalid DHCPv6 Address"),
|
|
(_("The DHCPv6 start address is not with the network %s") %
|
|
(str(ip))))
|
|
if not ip.overlaps(end):
|
|
return self.err.val_err(_("Invalid DHCPv6 Address"),
|
|
(_("The DHCPv6 end address is not with the network %s") %
|
|
(str(ip))))
|
|
|
|
return True
|
|
|
|
def validate_miscellaneous(self):
|
|
domain_name = self.widget("net-domain-name").get_text()
|
|
if len(domain_name) > 0:
|
|
if len(domain_name) > 16:
|
|
return self.err.val_err(_("Invalid Domain Name"),
|
|
_("Domain name must be less than 17 characters"))
|
|
if re.match("^[a-zA-Z0-9_]*$", domain_name) is None:
|
|
return self.err.val_err(_("Invalid Domain Name"),
|
|
_("Domain name may contain alphanumeric and '_' "
|
|
"characters only"))
|
|
|
|
if not self.widget("net-forward-dev").get_active():
|
|
return True
|
|
|
|
dev = self.widget("net-forward")
|
|
if dev.get_active() == -1:
|
|
return self.err.val_err(_("Invalid forwarding mode"),
|
|
_("Please select where the traffic should be forwarded"))
|
|
return True
|
|
|
|
def validate(self, page_num):
|
|
if page_num == PAGE_NAME:
|
|
return self.validate_name()
|
|
elif page_num == PAGE_IPV4:
|
|
return self.validate_ipv4()
|
|
elif page_num == PAGE_IPV6:
|
|
return self.validate_ipv6()
|
|
elif page_num == PAGE_MISC:
|
|
return self.validate_miscellaneous()
|
|
return True
|