virt-manager/src/virtManager/createinterface.py

1143 lines
40 KiB
Python
Raw Normal View History

2010-02-09 01:18:06 +03:00
#
# Copyright (C) 2008 Red Hat, Inc.
# Copyright (C) 2008 Cole Robinson <crobinso@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 gobject
import gtk
import logging
from virtinst import Interface
from virtManager import util
from virtManager import uihelpers
2010-12-09 01:26:19 +03:00
from virtManager.baseclass import vmmGObjectUI
2010-02-09 01:18:06 +03:00
from virtManager.asyncjob import vmmAsyncJob
from virtManager.createmeter import vmmCreateMeter
PAGE_TYPE = 0
PAGE_DETAILS = 1
DETAILS_BOND = 0
DETAILS_BRIDGE = 1
DETAILS_VLAN = 2
DETAILS_ETHERNET = 3
INTERFACE_ROW_KEY = 0
INTERFACE_ROW_SELECT = 1
INTERFACE_ROW_CANT_SELECT = 2
INTERFACE_ROW_NAME = 3
INTERFACE_ROW_TYPE = 4
INTERFACE_ROW_IS_DEFINED = 5
INTERFACE_ROW_IS_ACTIVE = 6
INTERFACE_ROW_IN_USE_BY = 7
INTERFACE_ROW_MAC = 8
BOND_PAGE_ARP = 0
BOND_PAGE_MII = 1
BOND_PAGE_DEFAULT = 2
IP_DHCP = 0
IP_STATIC = 1
IP_NONE = 2
2010-12-09 01:26:19 +03:00
class vmmCreateInterface(vmmGObjectUI):
2010-02-09 01:18:06 +03:00
__gsignals__ = {
"action-show-help": (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, [str]),
}
2010-12-09 01:26:19 +03:00
def __init__(self, conn):
vmmGObjectUI.__init__(self,
"vmm-create-interface.glade",
"vmm-create-interface")
2010-02-09 01:18:06 +03:00
self.conn = conn
self.interface = None
# Bridge configuration dialog
2010-12-09 01:26:19 +03:00
self.bridge_config_win = gtk.glade.XML(self.gladefile,
2010-02-09 01:18:06 +03:00
"bridge-config",
domain="virt-manager")
self.bridge_config = self.bridge_config_win.get_widget(
"bridge-config")
self.bridge_config_win.signal_autoconnect({
"on_bridge_config_delete_event": self.bridge_config_finish,
"on_bridge_ok_clicked" : self.bridge_config_finish,
})
# Bond configuration dialog
2010-12-09 01:26:19 +03:00
self.bond_config_win = gtk.glade.XML(self.gladefile,
2010-02-09 01:18:06 +03:00
"bond-config",
domain="virt-manager")
self.bond_config = self.bond_config_win.get_widget("bond-config")
self.bond_config_win.signal_autoconnect({
"on_bond_config_delete_event": self.bond_config_finish,
"on_bond_ok_clicked" : self.bond_config_finish,
"on_bond_monitor_mode_changed": self.bond_monitor_mode_changed,
})
2010-12-09 01:26:19 +03:00
self.ip_config_win = gtk.glade.XML(self.gladefile,
"ip-config",
domain="virt-manager")
self.ip_config = self.ip_config_win.get_widget("ip-config")
self.ip_config_win.signal_autoconnect({
"on_ip_config_delete_event": self.ip_config_finish,
"on_ip_ok_clicked": self.ip_config_finish,
"on_ip_copy_interface_toggled": self.ip_copy_interface_toggled,
"on_ipv4_mode_changed": self.ipv4_mode_changed,
"on_ipv6_mode_changed": self.ipv6_mode_changed,
"on_ipv6_address_add_clicked": self.ipv6_address_add,
"on_ipv6_address_remove_clicked": self.ipv6_address_remove,
})
self.ip_manually_changed = False
2010-02-09 01:18:06 +03:00
self.window.signal_autoconnect({
"on_vmm_create_interface_delete_event" : self.close,
"on_cancel_clicked": self.close,
"on_back_clicked" : self.back,
"on_forward_clicked" : self.forward,
"on_finish_clicked" : self.finish,
"on_help_clicked": self.show_help,
"on_pages_switch_page": self.page_changed,
"on_bridge_config_button_clicked": self.show_bridge_config,
"on_bond_config_button_clicked": self.show_bond_config,
"on_ip_config_button_clicked": self.show_ip_config,
2010-02-09 01:18:06 +03:00
"on_vlan_tag_changed": self.update_interface_name,
})
util.bind_escape_key_close(self)
self.set_initial_state()
def show(self):
self.reset_state()
self.topwin.present()
def show_bond_config(self, src):
self.bond_config.show_all()
def show_bridge_config(self, src):
self.bridge_config.show_all()
def show_ip_config(self, src):
self.ip_manually_changed = True
self.ip_config.show_all()
2010-02-09 01:18:06 +03:00
def close(self, ignore1=None, ignore2=None):
self.ip_config.hide()
self.bridge_config.hide()
self.bond_config.hide()
2010-02-09 01:18:06 +03:00
self.topwin.hide()
return 1
###########################
# Initialization routines #
###########################
def set_initial_state(self):
self.window.get_widget("pages").set_show_tabs(False)
self.bond_config_win.get_widget("bond-pages").set_show_tabs(False)
# FIXME: Unhide this when we make some documentation
self.window.get_widget("help").hide()
finish_img = gtk.image_new_from_stock(gtk.STOCK_QUIT,
gtk.ICON_SIZE_BUTTON)
self.window.get_widget("finish").set_image(finish_img)
blue = gtk.gdk.color_parse("#0072A8")
self.window.get_widget("header").modify_bg(gtk.STATE_NORMAL, blue)
box = self.window.get_widget("header-icon-box")
image = gtk.image_new_from_icon_name("network-idle",
gtk.ICON_SIZE_DIALOG)
image.show()
box.pack_end(image, False)
# Interface type
type_list = self.window.get_widget("interface-type")
type_model = gtk.ListStore(str, str)
type_list.set_model(type_model)
text = gtk.CellRendererText()
type_list.pack_start(text, True)
type_list.add_attribute(text, 'text', 1)
type_model.append([Interface.Interface.INTERFACE_TYPE_BRIDGE,
_("Bridge")])
type_model.append([Interface.Interface.INTERFACE_TYPE_BOND,
_("Bond")])
type_model.append([Interface.Interface.INTERFACE_TYPE_ETHERNET,
_("Ethernet")])
type_model.append([Interface.Interface.INTERFACE_TYPE_VLAN,
_("VLAN")])
# Start mode
uihelpers.build_startmode_combo(
self.window.get_widget("interface-startmode"))
# Parent/slave Interface list
slave_list = self.window.get_widget("interface-list")
# [ vmmInterface, selected, selectabel, name, type, is defined,
# is active, in use by str, mac]
slave_model = gtk.ListStore(object, bool, bool, str, str, bool, bool,
str, str)
slave_list.set_model(slave_model)
selectCol = gtk.TreeViewColumn()
nameCol = gtk.TreeViewColumn(_("Name"))
typeCol = gtk.TreeViewColumn(_("Type"))
useCol = gtk.TreeViewColumn(_("In use by"))
slave_list.append_column(selectCol)
slave_list.append_column(nameCol)
slave_list.append_column(typeCol)
slave_list.append_column(useCol)
chk = gtk.CellRendererToggle()
chk.connect("toggled", self.interface_item_toggled, slave_list)
selectCol.pack_start(chk, False)
selectCol.add_attribute(chk, "active", INTERFACE_ROW_SELECT)
selectCol.add_attribute(chk, "inconsistent", INTERFACE_ROW_CANT_SELECT)
selectCol.set_sort_column_id(INTERFACE_ROW_CANT_SELECT)
txt = gtk.CellRendererText()
nameCol.pack_start(txt, True)
nameCol.add_attribute(txt, "text", INTERFACE_ROW_NAME)
nameCol.set_sort_column_id(INTERFACE_ROW_NAME)
txt = gtk.CellRendererText()
typeCol.pack_start(txt, True)
typeCol.add_attribute(txt, "text", INTERFACE_ROW_TYPE)
typeCol.set_sort_column_id(INTERFACE_ROW_TYPE)
slave_model.set_sort_column_id(INTERFACE_ROW_CANT_SELECT,
gtk.SORT_ASCENDING)
txt = gtk.CellRendererText()
useCol.pack_start(txt, True)
useCol.add_attribute(txt, "text", INTERFACE_ROW_IN_USE_BY)
useCol.set_sort_column_id(INTERFACE_ROW_IN_USE_BY)
# Bond config
mode_list = self.bond_config_win.get_widget("bond-mode")
mode_model = gtk.ListStore(str, str)
mode_list.set_model(mode_model)
txt = gtk.CellRendererText()
mode_list.pack_start(txt, True)
mode_list.add_attribute(txt, "text", 0)
mode_model.append([_("System default"), None])
for m in Interface.InterfaceBond.INTERFACE_BOND_MODES:
mode_model.append([m, m])
mon_list = self.bond_config_win.get_widget("bond-monitor-mode")
mon_model = gtk.ListStore(str, str)
mon_list.set_model(mon_model)
txt = gtk.CellRendererText()
mon_list.pack_start(txt, True)
mon_list.add_attribute(txt, "text", 0)
mon_model.append([_("System default"), None])
for m in Interface.InterfaceBond.INTERFACE_BOND_MONITOR_MODES:
mon_model.append([m, m])
validate_list = self.bond_config_win.get_widget("arp-validate")
validate_model = gtk.ListStore(str)
validate_list.set_model(validate_model)
txt = gtk.CellRendererText()
validate_list.pack_start(txt, True)
validate_list.add_attribute(txt, "text", 0)
for m in Interface.InterfaceBond.INTERFACE_BOND_MONITOR_MODE_ARP_VALIDATE_MODES:
validate_model.append([m])
carrier_list = self.bond_config_win.get_widget("mii-carrier")
carrier_model = gtk.ListStore(str)
carrier_list.set_model(carrier_model)
txt = gtk.CellRendererText()
carrier_list.pack_start(txt, True)
carrier_list.add_attribute(txt, "text", 0)
for m in Interface.InterfaceBond.INTERFACE_BOND_MONITOR_MODE_MII_CARRIER_TYPES:
carrier_model.append([m])
# IP config
copy_iface = self.ip_config_win.get_widget("ip-copy-interface-combo")
copy_model = gtk.ListStore(str, object, bool)
copy_iface.set_model(copy_model)
txt = gtk.CellRendererText()
copy_iface.pack_start(txt, True)
copy_iface.add_attribute(txt, "text", 0)
copy_iface.add_attribute(txt, "sensitive", 2)
ip_mode = self.ip_config_win.get_widget("ipv4-mode")
ip_model = gtk.ListStore(str)
ip_mode.set_model(ip_model)
txt = gtk.CellRendererText()
ip_mode.pack_start(txt, True)
ip_mode.add_attribute(txt, "text", 0)
ip_model.insert(IP_DHCP, ["DHCP"])
ip_model.insert(IP_STATIC, ["Static"])
ip_model.insert(IP_NONE, ["No configuration"])
ip_mode = self.ip_config_win.get_widget("ipv6-mode")
ip_model = gtk.ListStore(str)
ip_mode.set_model(ip_model)
txt = gtk.CellRendererText()
ip_mode.pack_start(txt, True)
ip_mode.add_attribute(txt, "text", 0)
ip_model.insert(IP_DHCP, ["DHCP"])
ip_model.insert(IP_STATIC, ["Static"])
ip_model.insert(IP_NONE, ["No configuration"])
v6_addr = self.ip_config_win.get_widget("ipv6-address-list")
addr_model = gtk.ListStore(str)
v6_addr.set_model(addr_model)
txt_col = gtk.TreeViewColumn("")
v6_addr.append_column(txt_col)
txt = gtk.CellRendererText()
txt.set_property("editable", True)
txt.connect("edited", self.ipv6_address_editted)
txt_col.pack_start(txt, True)
txt_col.add_attribute(txt, "text", 0)
v6_addr.get_selection().connect("changed", self.ipv6_address_selected)
2010-02-09 01:18:06 +03:00
def reset_state(self):
self.window.get_widget("pages").set_current_page(PAGE_TYPE)
self.page_changed(None, None, PAGE_TYPE)
self.window.get_widget("interface-type").set_active(0)
# General details
self.window.get_widget("interface-name-entry").set_text("")
self.window.get_widget("interface-name-label").set_text("")
self.window.get_widget("interface-startmode").set_active(0)
self.window.get_widget("interface-activate").set_active(False)
# Bridge config
self.bridge_config_win.get_widget("bridge-delay").set_value(0)
self.bridge_config_win.get_widget("bridge-stp").set_active(True)
# Bond config
self.bond_config_win.get_widget("bond-mode").set_active(0)
self.bond_config_win.get_widget("bond-monitor-mode").set_active(0)
self.bond_config_win.get_widget("arp-interval").set_value(0)
self.bond_config_win.get_widget("arp-target").set_text("")
self.bond_config_win.get_widget("arp-validate").set_active(0)
self.bond_config_win.get_widget("mii-frequency").set_value(0)
self.bond_config_win.get_widget("mii-updelay").set_value(0)
self.bond_config_win.get_widget("mii-downdelay").set_value(0)
self.bond_config_win.get_widget("mii-carrier").set_active(0)
# IP config
self.ip_manually_changed = False
self.ip_config_win.get_widget("ip-do-manual").set_active(True)
self.ip_config_win.get_widget("ip-do-manual-box").set_current_page(0)
self.ip_config_win.get_widget("ipv4-mode").set_active(IP_DHCP)
self.ip_config_win.get_widget("ipv4-address").set_text("")
self.ip_config_win.get_widget("ipv4-gateway").set_text("")
self.ip_config_win.get_widget("ipv6-mode").set_active(IP_NONE)
self.ip_config_win.get_widget("ipv6-autoconf").set_active(False)
self.ipv6_address_selected()
2010-02-09 01:18:06 +03:00
def populate_details_page(self):
itype = self.get_config_interface_type()
# Set up default interface name
self.window.get_widget("interface-name-entry").hide()
self.window.get_widget("interface-name-label").hide()
if itype in [Interface.Interface.INTERFACE_TYPE_BRIDGE,
Interface.Interface.INTERFACE_TYPE_BOND]:
2010-02-09 01:18:06 +03:00
widget = "interface-name-entry"
else:
widget = "interface-name-label"
self.window.get_widget(widget).show()
default_name = self.get_default_name()
self.set_interface_name(default_name)
# Make sure interface type specific fields are shown
type_dict = {
Interface.Interface.INTERFACE_TYPE_BRIDGE : "bridge",
Interface.Interface.INTERFACE_TYPE_BOND : "bond",
Interface.Interface.INTERFACE_TYPE_VLAN : "vlan",
}
for key, value in type_dict.items():
do_show = (key == itype)
self.window.get_widget("%s-label" % value).set_property("visible",
do_show)
self.window.get_widget("%s-box" % value).set_property("visible",
do_show)
if itype == Interface.Interface.INTERFACE_TYPE_BRIDGE:
self.update_bridge_desc()
elif itype == Interface.Interface.INTERFACE_TYPE_BOND:
self.update_bond_desc()
# Populate device list
self.populate_interface_list(itype)
self.update_ip_config()
def update_ip_config(self):
(is_manual, current_name,
ignore, ignore, ignore) = self.get_config_ip_info()
2010-02-09 01:18:06 +03:00
itype = self.get_config_interface_type()
ifaces = self.get_config_selected_interfaces()
2010-02-09 01:18:06 +03:00
copy_radio = self.ip_config_win.get_widget("ip-copy-interface")
copy_combo = self.ip_config_win.get_widget("ip-copy-interface-combo")
copy_model = copy_combo.get_model()
2010-02-09 01:18:06 +03:00
# Only select 'copy from' option if using bridge/bond/vlan
enable_copy = (itype in [Interface.Interface.INTERFACE_TYPE_BRIDGE,
Interface.Interface.INTERFACE_TYPE_BOND,
Interface.Interface.INTERFACE_TYPE_VLAN])
2010-02-09 01:18:06 +03:00
# Set defaults if required
copy_model.clear()
active_rows = []
inactive_rows = []
for row in ifaces:
is_defined = row[INTERFACE_ROW_IS_DEFINED]
name = row[INTERFACE_ROW_NAME]
label = name
sensitive = False
iface_obj = None
if is_defined:
iface_obj = self.conn.get_interface(name)
# We only want configured (aka interface API) interfaces with
# actually present <protocol> info
if not is_defined or not iface_obj:
label += " (Not configured)"
elif not iface_obj.get_protocol_xml():
label += " (No IP configuration)"
else:
sensitive = True
row = [label, iface_obj, sensitive]
if sensitive:
active_rows.append(row)
else:
inactive_rows.append(row)
# Make sure inactive rows are listed after active rows
for row in active_rows + inactive_rows:
copy_model.append(row)
if len(copy_model) == 0:
copy_model.append(["No child interfaces selected.", None, False])
if not enable_copy:
copy_model.clear()
copy_model.append(["", None, False])
# Find default model selection
have_valid_copy = bool(active_rows)
# Re select previous selection, 0 otherwise
idx = 0
if not is_manual and current_name:
found_idx = 0
for row in copy_model:
if row[1] == current_name:
idx = found_idx
break
found_idx += 1
copy_combo.set_active(idx)
copy_radio.set_sensitive(enable_copy)
if not self.ip_manually_changed:
if (enable_copy and have_valid_copy):
copy_radio.set_active(True)
else:
self.ip_config_win.get_widget("ip-do-manual").set_active(True)
self.update_ip_desc()
2010-02-09 01:18:06 +03:00
def populate_interface_list(self, itype):
iface_list = self.window.get_widget("interface-list")
model = iface_list.get_model()
model.clear()
ifilter = [Interface.Interface.INTERFACE_TYPE_ETHERNET]
msg = None
if itype == Interface.Interface.INTERFACE_TYPE_BRIDGE:
ifilter.append(Interface.Interface.INTERFACE_TYPE_VLAN)
ifilter.append(Interface.Interface.INTERFACE_TYPE_BOND)
msg = _("Choose interface(s) to bridge:")
elif itype == Interface.Interface.INTERFACE_TYPE_VLAN:
msg = _("Choose parent interface:")
elif itype == Interface.Interface.INTERFACE_TYPE_BOND:
msg = _("Choose interfaces to bond:")
elif itype == Interface.Interface.INTERFACE_TYPE_ETHERNET:
msg = _("Choose an unconfigured interface:")
self.window.get_widget("interface-list-text").set_text(msg)
iface_list = []
row_dict = {}
for phys in self.conn.get_devices("net"):
row_dict[phys.interface] = [phys.interface,
False, False, phys.interface,
"ethernet", False, True, None,
phys.address]
for name in self.conn.list_interface_names():
iface = self.conn.get_interface(name)
key = iface.interface
iface_type = iface.get_type()
active = iface.is_active()
name = iface.get_name()
if iface_type not in ifilter:
continue
if itype == Interface.Interface.INTERFACE_TYPE_ETHERNET:
if name in row_dict:
2010-02-09 01:18:06 +03:00
del(row_dict[name])
# We only want 'unconfigured' interfaces here
continue
if name in row_dict:
2010-02-09 01:18:06 +03:00
# Interface was listed via nodedev APIs
row = row_dict[name]
row[INTERFACE_ROW_KEY] = key
row[INTERFACE_ROW_IS_DEFINED] = True
row[INTERFACE_ROW_IS_ACTIVE] = True
else:
# Brand new row
row = [key, False, False,
iface.get_name(), iface.get_type(), True,
active, None, iface.get_mac()]
row_dict[name] = row
for row in row_dict.values():
name = row[INTERFACE_ROW_NAME]
row[INTERFACE_ROW_IN_USE_BY] = util.iface_in_use_by(self.conn,
name)
for row in row_dict.values():
model.append(row)
def get_default_name(self):
itype = self.get_config_interface_type()
name = _("No interface selected")
if itype == Interface.Interface.INTERFACE_TYPE_BRIDGE:
name = Interface.Interface.find_free_name(self.conn.vmm, "br")
elif itype == Interface.Interface.INTERFACE_TYPE_BOND:
name = Interface.Interface.find_free_name(self.conn.vmm, "bond")
else:
ifaces = self.get_config_selected_interfaces()
if len(ifaces) > 0:
iface = ifaces[0][INTERFACE_ROW_NAME]
if itype == Interface.Interface.INTERFACE_TYPE_VLAN:
tag = self.window.get_widget("vlan-tag").get_value()
name = "%s.%s" % (iface, int(tag))
elif itype == Interface.Interface.INTERFACE_TYPE_ETHERNET:
name = iface
return name
#########################
# get_config_* routines #
#########################
def get_config_interface_type(self):
type_list = self.window.get_widget("interface-type")
return type_list.get_model()[type_list.get_active()][0]
def set_interface_name(self, name):
if self.window.get_widget("interface-name-entry").get_property("visible"):
widget = "interface-name-entry"
else:
widget = "interface-name-label"
self.window.get_widget(widget).set_text(name)
def get_config_interface_name(self):
if self.window.get_widget("interface-name-entry").get_property("visible"):
return self.window.get_widget("interface-name-entry").get_text()
else:
return self.window.get_widget("interface-name-label").get_text()
def get_config_interface_startmode(self):
start_list = self.window.get_widget("interface-startmode")
return start_list.get_model()[start_list.get_active()][0]
def get_config_selected_interfaces(self):
iface_list = self.window.get_widget("interface-list")
model = iface_list.get_model()
ret = []
for row in model:
active = row[INTERFACE_ROW_SELECT]
iobj = row[INTERFACE_ROW_KEY]
if active:
ret.append(row)
return ret
def get_config_bridge_params(self):
delay = self.bridge_config_win.get_widget("bridge-delay").get_value()
stp = self.bridge_config_win.get_widget("bridge-stp").get_active()
return [delay, stp]
def get_config_ipv6_address_selection(self):
src = self.ip_config_win.get_widget("ipv6-address-list")
selection = src.get_selection()
ignore, treepath = selection.get_selected()
return treepath
def get_config_ipv6_addresses(self):
src = self.ip_config_win.get_widget("ipv6-address-list")
model = src.get_model()
return map(lambda x: x[0], model)
2010-02-09 01:18:06 +03:00
################
# UI Listeners #
################
def interface_item_toggled(self, src, index, slave_list):
itype = self.get_config_interface_type()
active = src.get_active()
model = slave_list.get_model()
if itype in [Interface.Interface.INTERFACE_TYPE_ETHERNET,
Interface.Interface.INTERFACE_TYPE_VLAN]:
# Deselect any selected rows
for row in model:
if row == model[index]:
continue
row[INTERFACE_ROW_SELECT] = False
# Toggle the clicked row
model[index][INTERFACE_ROW_SELECT] = not active
self.update_interface_name()
self.update_ip_config()
2010-02-09 01:18:06 +03:00
def update_interface_name(self, ignore1=None, ignore2=None):
itype = self.get_config_interface_type()
if itype not in [Interface.Interface.INTERFACE_TYPE_VLAN,
Interface.Interface.INTERFACE_TYPE_ETHERNET]:
2010-02-09 01:18:06 +03:00
# The rest have editable name fields, so don't overwrite
return
name = self.get_default_name()
self.set_interface_name(name)
def bond_monitor_mode_changed(self, src):
model = src.get_model()
value = model[src.get_active()][1]
bond_pages = self.bond_config_win.get_widget("bond-pages")
if value == "arpmon":
page = BOND_PAGE_ARP
elif value == "miimon":
page = BOND_PAGE_MII
else:
page = BOND_PAGE_DEFAULT
bond_pages.set_current_page(page)
def ip_copy_interface_toggled(self, src):
active = src.get_active()
self.ip_config_win.get_widget("ip-copy-interface-box").set_sensitive(active)
self.ip_config_win.get_widget("ip-do-manual-box").set_sensitive(not active)
def ipv4_mode_changed(self, src):
static = (src.get_active() == IP_STATIC)
self.ip_config_win.get_widget("ipv4-static-box").set_sensitive(static)
def ipv6_mode_changed(self, src):
static = (src.get_active() == IP_STATIC)
self.ip_config_win.get_widget("ipv6-static-box").set_sensitive(static)
2010-02-09 01:18:06 +03:00
def update_bridge_desc(self):
delay, stp = self.get_config_bridge_params()
txt = "STP %s" % (stp and "on" or "off")
txt += ", delay %d sec" % int(delay)
self.window.get_widget("bridge-config-label").set_text(txt)
def update_bond_desc(self):
mode_list = self.bond_config_win.get_widget("bond-mode")
model = mode_list.get_model()
mode = model[mode_list.get_active()][0]
mon_list = self.bond_config_win.get_widget("bond-monitor-mode")
model = mon_list.get_model()
mon = model[mon_list.get_active()][1]
txt = mode
if mon:
txt += ", %s" % mon
self.window.get_widget("bond-config-label").set_text(txt)
def update_ip_desc(self):
is_manual, name, ipv4, ipv6, ignore = self.get_config_ip_info()
label = ""
if is_manual:
if ipv4:
label += "IPv4: %s" % (ipv4.dhcp and "DHCP" or "Static")
if ipv6:
if label:
label += ", "
label += "IPv6: "
mode_label = ""
if ipv6.autoconf and ipv6.dhcp:
mode_label += "Autoconf "
if ipv6.dhcp:
mode_label += "DHCP"
if not mode_label:
mode_label = "Static"
label += mode_label
else:
if name:
label = "Copy configuration from '%s'" % name
if not label:
label = "No configuration"
self.window.get_widget("ip-config-label").set_text(label)
def get_config_ip_info(self):
if not self.window.get_widget("ip-label").get_property("visible"):
return [True, None, None, None, None]
if not self.validate_ip_info():
return [True, None, None, None, None]
return self.build_ip_info()
def build_ip_info(self):
def get_row(widget):
combo = widget.get_model()
active = widget.get_active()
if active == -1:
return None
return combo[active]
def build_ip(addr_str):
if not addr_str:
return None
ret = addr_str.rsplit("/", 1)
ip = Interface.InterfaceProtocolIPAddress(ret[0])
if len(ret) > 1:
ip.prefix = ret[1]
return ip
is_manual = self.ip_config_win.get_widget("ip-do-manual").get_active()
copy_row = get_row(self.ip_config_win.get_widget("ip-copy-interface-combo"))
v4_mode = self.ip_config_win.get_widget("ipv4-mode").get_active()
v4_addr = self.ip_config_win.get_widget("ipv4-address").get_text()
v4_gate = self.ip_config_win.get_widget("ipv4-gateway").get_text()
v6_mode = self.ip_config_win.get_widget("ipv6-mode").get_active()
v6_auto = self.ip_config_win.get_widget("ipv6-autoconf").get_active()
v6_gate = self.ip_config_win.get_widget("ipv6-gateway").get_text()
v6_addrlist = self.get_config_ipv6_addresses()
copy_name = None
proto_xml = None
ipv4 = None
ipv6 = None
if not is_manual:
if copy_row[1] and copy_row[2]:
copy_name = copy_row[1].get_name()
proto_xml = copy_row[1].get_protocol_xml()
else:
# Build IPv4 Info
if v4_mode != IP_NONE:
ipv4 = Interface.InterfaceProtocolIPv4()
ipv4.dhcp = bool(v4_mode == IP_DHCP)
if not ipv4.dhcp:
if v4_addr:
ipv4.ips.append(build_ip(v4_addr))
if v4_gate:
ipv4.gateway = v4_gate
# Build IPv6 Info
if v6_mode != IP_NONE:
ipv6 = Interface.InterfaceProtocolIPv6()
ipv6.dhcp = bool(v6_mode == IP_DHCP)
ipv6.autoconf = bool(v6_auto)
if not ipv6.dhcp:
if v6_gate:
ipv6.gateway = v6_gate
if v6_addrlist:
ipv6.ips = map(build_ip, v6_addrlist)
return [is_manual, copy_name, ipv4, ipv6, proto_xml]
def ipv6_address_add(self, src):
src = self.ip_config_win.get_widget("ipv6-address-list")
model = src.get_model()
model.append(["Insert address/prefix"])
def ipv6_address_remove(self, src):
treepath = self.get_config_ipv6_address_selection()
src = self.ip_config_win.get_widget("ipv6-address-list")
model = src.get_model()
if treepath != None:
del(model[treepath])
def ipv6_address_editted(self, src, path, new_text):
src = self.ip_config_win.get_widget("ipv6-address-list")
model = src.get_model()
row = model[path]
row[0] = new_text
def ipv6_address_selected(self, src=None):
treepath = self.get_config_ipv6_address_selection()
has_selection = (treepath != None)
self.ip_config_win.get_widget("ipv6-address-remove").set_sensitive(
has_selection)
2010-02-09 01:18:06 +03:00
#######################
# Notebook navigation #
#######################
def back(self, src):
notebook = self.window.get_widget("pages")
curpage = notebook.get_current_page()
notebook.set_current_page(curpage - 1)
def forward(self, ignore):
notebook = self.window.get_widget("pages")
curpage = notebook.get_current_page()
if self.validate(notebook.get_current_page()) != True:
return
self.window.get_widget("forward").grab_focus()
notebook.set_current_page(curpage + 1)
def page_changed(self, ignore1, ignore2, pagenum):
next_page = pagenum + 1
# Update page number
page_lbl = ("<span color='#59B0E2'>%s</span>" %
_("Step %(current_page)d of %(max_page)d") %
{'current_page': next_page, 'max_page': PAGE_DETAILS + 1})
2010-02-09 01:18:06 +03:00
self.window.get_widget("header-pagenum").set_markup(page_lbl)
if pagenum == 0:
self.window.get_widget("back").set_sensitive(False)
else:
self.window.get_widget("back").set_sensitive(True)
if pagenum == PAGE_DETAILS:
self.populate_details_page()
self.window.get_widget("forward").hide()
self.window.get_widget("finish").show()
self.window.get_widget("finish").grab_focus()
else:
self.window.get_widget("forward").show()
self.window.get_widget("finish").hide()
def validate(self, pagenum):
try:
if pagenum == PAGE_TYPE:
# Nothing to validate
return True
elif pagenum == PAGE_DETAILS:
return self.validate_details_page()
except Exception, e:
self.err.show_err(_("Uncaught error validating install "
"parameters: %s") % str(e))
2010-02-09 01:18:06 +03:00
return
def validate_details_page(self):
itype = self.get_config_interface_type()
name = self.get_config_interface_name()
start = self.get_config_interface_startmode()
ifaces = self.get_config_selected_interfaces()
iclass = Interface.Interface.interface_class_for_type(itype)
if not name:
return self.err.val_err(_("An interface name is required."))
if (itype != Interface.Interface.INTERFACE_TYPE_BRIDGE and
len(ifaces) == 0):
return self.err.val_err(_("An interface must be selected"))
try:
iobj = iclass(name, self.conn.vmm)
iobj.start_mode = start
check_conflict = False
# Pull info from selected interfaces
if hasattr(iobj, "interfaces"):
iobj.interfaces = map(lambda x: x[INTERFACE_ROW_KEY], ifaces)
check_conflict = True
elif hasattr(iobj, "parent_interface"):
iobj.parent_interface = ifaces[0][INTERFACE_ROW_KEY]
elif itype == Interface.Interface.INTERFACE_TYPE_ETHERNET:
iobj.macaddr = ifaces[0][INTERFACE_ROW_MAC]
# Warn about defined interfaces
defined_ifaces = ""
if check_conflict:
for row in ifaces:
if not row[INTERFACE_ROW_IS_DEFINED]:
continue
if defined_ifaces:
defined_ifaces += ", "
defined_ifaces += row[INTERFACE_ROW_NAME]
if defined_ifaces:
ret = self.err.yes_no(
_("The following interface(s) are already "
"configured:\n\n%s\n\nUsing these may overwrite "
"their existing configuration. Are you sure you "
"want to use the selected interface(s)?") %
defined_ifaces)
if not ret:
return ret
# Validate IP info (get_config validates for us)
(is_manual, copy_name, ipv4,
ipv6, proto_xml) = self.get_config_ip_info()
if is_manual:
protos = []
if ipv4:
protos.append(ipv4)
if ipv6:
protos.append(ipv6)
iobj.protocols = protos
else:
iobj.protocol_xml = proto_xml
2010-02-09 01:18:06 +03:00
if itype == Interface.Interface.INTERFACE_TYPE_BRIDGE:
ret = self.validate_bridge(iobj, ifaces)
elif itype == Interface.Interface.INTERFACE_TYPE_BOND:
ret = self.validate_bond(iobj, ifaces)
elif itype == Interface.Interface.INTERFACE_TYPE_VLAN:
ret = self.validate_vlan(iobj, ifaces)
elif itype == Interface.Interface.INTERFACE_TYPE_ETHERNET:
ret = self.validate_ethernet(iobj, ifaces)
if not ret:
return ret
iobj.get_xml_config()
self.interface = iobj
except Exception, e:
return self.err.val_err(_("Error setting interface parameters."),
str(e))
return True
def validate_bridge(self, iobj, ifaces):
delay = self.bridge_config_win.get_widget("bridge-delay").get_value()
stp = self.bridge_config_win.get_widget("bridge-stp").get_active()
iobj.stp = stp
iobj.delay = int(delay)
return True
def validate_bond(self, iobj, ifaces):
mode_list = self.bond_config_win.get_widget("bond-mode")
model = mode_list.get_model()
mode = model[mode_list.get_active()][1]
mon_list = self.bond_config_win.get_widget("bond-monitor-mode")
model = mon_list.get_model()
mon = model[mon_list.get_active()][1]
val_list = self.bond_config_win.get_widget("arp-validate")
val_model = val_list.get_model()
arp_val = val_model[val_list.get_active()][0]
car_list = self.bond_config_win.get_widget("mii-carrier")
car_model = car_list.get_model()
mii_car = car_model[car_list.get_active()][0]
# ARP params
arp_int = self.bond_config_win.get_widget("arp-interval").get_value()
arp_tar = self.bond_config_win.get_widget("arp-target").get_text()
# MII params
mii_freq = self.bond_config_win.get_widget("mii-frequency").get_value()
mii_up = self.bond_config_win.get_widget("mii-updelay").get_value()
mii_down = self.bond_config_win.get_widget("mii-downdelay").get_value()
iobj.bond_mode = mode
iobj.monitor_mode = mon
if not mon:
# No monitor params, just return
return True
if mon == "arpmon":
iobj.arp_validate_mode = arp_val
iobj.arp_interval = int(arp_int)
iobj.arp_target = arp_tar or None
elif mon == "miimon":
iobj.mii_carrier_mode = mii_car
iobj.mii_frequency = int(mii_freq)
iobj.mii_updelay = int(mii_up)
iobj.mii_downdelay = int(mii_down)
return True
def validate_vlan(self, iobj, ifaces):
idx = self.window.get_widget("vlan-tag").get_value()
iobj.tag = int(idx)
return True
def validate_ethernet(self, iobj, ifaces):
return True
def validate_ip_info(self):
try:
self.build_ip_info()
except Exception, e:
self.err.show_err(_("Error validating IP configuration: %s") %
str(e))
return False
return True
2010-02-09 01:18:06 +03:00
####################
# Dialog callbacks #
####################
def bridge_config_finish(self, ignore1=None, ignore2=None):
self.update_bridge_desc()
self.bridge_config.hide()
return 1
def bond_config_finish(self, ignore1=None, ignore2=None):
self.update_bond_desc()
self.bond_config.hide()
return 1
def ip_config_finish(self, ignore1=None, ignore2=None):
if not self.validate_ip_info():
return
self.update_ip_desc()
self.ip_config.hide()
return 1
2010-02-09 01:18:06 +03:00
#####################
# Creation routines #
#####################
def finish(self, src):
# Validate the final page
page = self.window.get_widget("pages").get_current_page()
if self.validate(page) != True:
return False
activate = self.window.get_widget("interface-activate").get_active()
# Start the install
self.topwin.set_sensitive(False)
self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
progWin = vmmAsyncJob(self.do_install, [activate],
2010-02-09 01:18:06 +03:00
title=_("Creating virtual interface"),
text=_("The virtual interface is now being "
"created."))
2010-12-10 17:57:42 +03:00
error, details = progWin.run()
2010-02-09 01:18:06 +03:00
self.topwin.set_sensitive(True)
self.topwin.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_ARROW))
if error:
2010-12-10 17:57:42 +03:00
error = _("Error creating interface: '%s'") % error
self.err.show_err(error,
details=(error + "\n" + details))
2010-12-10 17:57:42 +03:00
else:
# FIXME: Hmm, shouldn't we emit a signal here rather than do this?
self.conn.tick(noStatsUpdate=True)
self.close()
2010-02-09 01:18:06 +03:00
2010-12-10 17:57:42 +03:00
def do_install(self, asyncjob, activate):
2010-02-09 01:18:06 +03:00
meter = vmmCreateMeter(asyncjob)
error = None
details = None
2010-12-10 17:57:42 +03:00
self.interface.conn = util.dup_conn(self.conn).vmm
2010-02-09 01:18:06 +03:00
2010-12-10 17:57:42 +03:00
self.interface.install(meter, create=activate)
logging.debug("Install completed")
2010-02-09 01:18:06 +03:00
def show_help(self, ignore):
# No help available yet.
pass
2010-12-09 01:26:19 +03:00
vmmGObjectUI.type_register(vmmCreateInterface)