Hooked up stop/start/delete buttons for networking. Detect & signal start/stop events for network

This commit is contained in:
Daniel P. Berrange 2007-04-03 14:01:45 -04:00
parent 5896f50067
commit 17a1dac0ce
4 changed files with 167 additions and 106 deletions

View File

@ -42,6 +42,10 @@ class vmmConnection(gobject.GObject):
[str, str]),
"net-removed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
[str, str]),
"net-started": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
[str, str]),
"net-stopped": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
[str, str]),
"resources-sampled": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
[]),
"disconnected": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [str])
@ -213,6 +217,7 @@ class vmmConnection(gobject.GObject):
self.nets[uuid].start()
self.nets[uuid].set_autostart(True)
self.emit("net-added", self.uri, uuid)
self.emit("net-started", self.uri, uuid)
return self.nets[uuid]
def restore(self, frm):
@ -226,25 +231,45 @@ class vmmConnection(gobject.GObject):
return
oldNets = self.nets
startNets = {}
stopNets = {}
self.nets = {}
newNets = {}
for name in self.vmm.listNetworks():
newActiveNetNames = []
newInactiveNetNames = []
try:
newActiveNetNames = self.vmm.listNetworks()
except:
logging.warn("Unable to list active networks")
try:
newInactiveNetNames = self.vmm.listDefinedNetworks()
except:
logging.warn("Unable to list inactive networks")
for name in newActiveNetNames:
net = self.vmm.networkLookupByName(name)
uuid = self.uuidstr(net.UUID())
if not oldNets.has_key(uuid):
self.nets[uuid] = vmmNetwork(self.config, self, net, uuid)
self.nets[uuid] = vmmNetwork(self.config, self, net, uuid, True)
newNets[uuid] = self.nets[uuid]
startNets[uuid] = newNets[uuid]
else:
self.nets[uuid] = oldNets[uuid]
if not self.nets[uuid].is_active():
self.nets[uuid].set_active(True)
startNets[uuid] = self.nets[uuid]
del oldNets[uuid]
for name in self.vmm.listDefinedNetworks():
for name in newInactiveNetNames:
net = self.vmm.networkLookupByName(name)
uuid = self.uuidstr(net.UUID())
if not oldNets.has_key(uuid):
self.nets[uuid] = vmmNetwork(self.config, self, net, uuid)
self.nets[uuid] = vmmNetwork(self.config, self, net, uuid, False)
newNets[uuid] = self.nets[uuid]
else:
self.nets[uuid] = oldNets[uuid]
if self.nets[uuid].is_active():
self.nets[uuid].set_active(False)
stopNets[uuid] = self.nets[uuid]
del oldNets[uuid]
oldActiveIDs = {}
@ -369,6 +394,12 @@ class vmmConnection(gobject.GObject):
for uuid in newNets:
self.emit("net-added", self.uri, uuid)
for uuid in startNets:
self.emit("net-started", self.uri, uuid)
for uuid in stopNets:
self.emit("net-stopped", self.uri, uuid)
# Finally, we sample each domain
now = time()
self.hostinfo = self.vmm.getInfo()

View File

@ -82,9 +82,14 @@ class vmmHost(gobject.GObject):
"on_vmm_host_delete_event": self.close,
"on_menu_help_about_activate": self.show_help,
"on_net_add_clicked": self.add_network,
"on_net_delete_clicked": self.delete_network,
"on_net_stop_clicked": self.stop_network,
"on_net_start_clicked": self.start_network,
})
self.conn.connect("resources-sampled", self.refresh_resources)
self.conn.connect("net-started", self.refresh_network)
self.conn.connect("net-stopped", self.refresh_network)
def show(self):
dialog = self.window.get_widget("vmm-host")
@ -95,6 +100,21 @@ class vmmHost(gobject.GObject):
return 1
return 0
def delete_network(self, src):
net = self.current_network()
if net is not None:
net.delete()
def start_network(self, src):
net = self.current_network()
if net is not None:
net.start()
def stop_network(self, src):
net = self.current_network()
if net is not None:
net.stop()
def add_network(self, src):
if self.add is None:
self.add = vmmCreateNetwork(self.config, self.conn)
@ -122,6 +142,21 @@ class vmmHost(gobject.GObject):
memory_vector.reverse()
self.memory_usage_graph.set_property("data_array", memory_vector)
def current_network(self):
sel = self.window.get_widget("net-list").get_selection()
active = sel.get_selected()
if active[1] != None:
curruuid = active[0].get_value(active[1], 0)
return self.conn.get_net(curruuid)
return None
def refresh_network(self, src, uri, uuid):
sel = self.window.get_widget("net-list").get_selection()
active = sel.get_selected()
if active[1] != None:
curruuid = active[0].get_value(active[1], 0)
if curruuid == uuid:
self.net_selected(sel)
def net_selected(self, src):
active = src.get_selected()
@ -135,34 +170,48 @@ class vmmHost(gobject.GObject):
self.window.get_widget("net-name").set_text(net.get_name())
self.window.get_widget("net-uuid").set_text(net.get_uuid())
if net.get_bridge_device() == None or net.get_bridge_device() == "":
self.window.get_widget("net-device").set_text("")
self.window.get_widget("net-device").set_sensitive(False)
self.window.get_widget("net-state").set_text(_("Inactive"))
self.window.get_widget("net-state-icon").set_from_pixbuf(gtk.gdk.pixbuf_new_from_file_at_size(self.config.get_icon_dir() + "/state_shutoff.png", 18, 18))
else:
if net.is_active():
self.window.get_widget("net-device").set_text(net.get_bridge_device())
self.window.get_widget("net-device").set_sensitive(True)
self.window.get_widget("net-state").set_text(_("Active"))
self.window.get_widget("net-state-icon").set_from_pixbuf(gtk.gdk.pixbuf_new_from_file_at_size(self.config.get_icon_dir() + "/state_running.png", 18, 18))
self.window.get_widget("net-start").set_sensitive(False)
self.window.get_widget("net-stop").set_sensitive(True)
self.window.get_widget("net-delete").set_sensitive(False)
else:
self.window.get_widget("net-device").set_text("")
self.window.get_widget("net-device").set_sensitive(False)
self.window.get_widget("net-state").set_text(_("Inactive"))
self.window.get_widget("net-state-icon").set_from_pixbuf(gtk.gdk.pixbuf_new_from_file_at_size(self.config.get_icon_dir() + "/state_shutoff.png", 18, 18))
self.window.get_widget("net-start").set_sensitive(True)
self.window.get_widget("net-stop").set_sensitive(False)
self.window.get_widget("net-delete").set_sensitive(True)
if 1: # XXX net.get_autostart():
autostart = True
try:
autostart = net.get_autostart()
except:
# Hack, libvirt 0.2.1 is missing python binding for the autostart method
pass
if autostart:
self.window.get_widget("net-autostart").set_text(_("On boot"))
self.window.get_widget("net-autostart-icon").set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_MENU)
else:
self.window.get_widget("net-autostart").set_text(_("Never"))
self.window.get_widget("net-autostart-icon").set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_MENU)
ip4 = net.get_ip4_config()
self.window.get_widget("net-ip4-address").set_text(ip4[0])
self.window.get_widget("net-ip4-netmask").set_text(ip4[1])
self.window.get_widget("net-ip4-dhcp-start").set_text(ip4[2])
self.window.get_widget("net-ip4-dhcp-end").set_text(ip4[3])
network = net.get_ipv4_network()
self.window.get_widget("net-ip4-network").set_text(str(network))
if ip4[4]:
dhcp = net.get_ipv4_dhcp_range()
self.window.get_widget("net-ip4-dhcp-start").set_text(str(dhcp[0]))
self.window.get_widget("net-ip4-dhcp-end").set_text(str(dhcp[1]))
(forward, forwardDev) = net.get_ipv4_forward()
if forward:
self.window.get_widget("net-ip4-forwarding-icon").set_from_stock(gtk.STOCK_CONNECT, gtk.ICON_SIZE_MENU)
if ip4[5] != None and ip4[5] != "":
self.window.get_widget("net-ip4-forwarding").set_text(_("NAT to physical device %s") % (ip4[5]))
if forwardDev != None and forwardDev != "":
self.window.get_widget("net-ip4-forwarding").set_text(_("NAT to physical device %s") % (forwardDev))
else:
self.window.get_widget("net-ip4-forwarding").set_text(_("Masquerade via default route"))
else:

View File

@ -23,38 +23,31 @@ import libxml2
import os
import sys
import logging
from virtManager.IPy import IP
class vmmNetwork(gobject.GObject):
__gsignals__ = { }
def __init__(self, config, connection, net, uuid):
def __init__(self, config, connection, net, uuid, active):
self.__gobject_init__()
self.config = config
self.connection = connection
self.net = net
self.uuid = uuid
self.active = active
def set_handle(self, net):
self.net = net
def set_active(self, state):
self.active = state
def is_active(self):
if self.net.ID() == -1:
return False
else:
return True
return self.active
def get_connection(self):
return self.connection
def get_id(self):
return self.net.ID()
def get_id_pretty(self):
id = self.get_id()
if id < 0:
return "-"
return str(id)
def get_name(self):
return self.net.name()
@ -70,28 +63,62 @@ class vmmNetwork(gobject.GObject):
def start(self):
self.net.create()
def stop(self):
name = self.get_name()
self.net.destroy()
# XXX nasty nasty hack - destroy() kills the virNetworkPtr object
# so we have to grab a new one
self.net = self.connection.vmm.networkLookupByName(name)
def delete(self):
self.net.undefine()
# The virNetworkPtr is dead after this point, so nullify it
self.net = None
def set_autostart(self, value):
self.net.setAutostart(value)
def get_autostart(self):
return self.net.autostart()
def get_ip4_config(self):
def get_ipv4_network(self):
try:
xml = self.net.XMLDesc(0)
doc = libxml2.parseDoc(xml)
addrStr = self._get_xml_path(doc, "/network/ip/@address")
netmaskStr = self._get_xml_path(doc, "/network/ip/@netmask")
netmask = IP(netmaskStr)
gateway = IP(addrStr)
network = IP(gateway.int() & netmask.int())
return IP(str(network)+ "/" + netmaskStr)
finally:
if doc is not None:
doc.freeDoc()
def get_ipv4_forward(self):
try:
xml = self.net.XMLDesc(0)
doc = libxml2.parseDoc(xml)
fw = self._get_xml_path(doc, "string(count(/network/forward))")
if fw != None and int(fw) != 0:
forwardDev = self._get_xml_path(doc, "string(/network/forward/@dev)")
return [True, forwardDev]
else:
return [False, None]
finally:
if doc is not None:
doc.freeDoc()
def get_ipv4_dhcp_range(self):
try:
xml = self.net.XMLDesc(0)
doc = libxml2.parseDoc(xml)
addr = self._get_xml_path(doc, "/network/ip/@address")
netmask = self._get_xml_path(doc, "/network/ip/@netmask")
dhcpstart = self._get_xml_path(doc, "/network/ip/dhcp/range[1]/@start")
dhcpend = self._get_xml_path(doc, "/network/ip/dhcp/range[1]/@end")
fw = self._get_xml_path(doc, "string(count(/network/forward))")
forward = False
forwardDev = None
if fw != None and int(fw) != 0:
forward = True
forwardDev = self._get_xml_path(doc, "string(/network/forward/@dev)")
return [addr, netmask,dhcpstart,dhcpend,forward, forwardDev]
return [IP(dhcpstart), IP(dhcpend)]
finally:
if doc is not None:
doc.freeDoc()

View File

@ -1143,7 +1143,7 @@
<widget class="GtkTable" id="table3">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="n_rows">5</property>
<property name="n_rows">4</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">3</property>
@ -1152,7 +1152,7 @@
<child>
<widget class="GtkLabel" id="label52">
<property name="visible">True</property>
<property name="label" translatable="yes">Address:</property>
<property name="label" translatable="yes">Network:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@ -1177,34 +1177,6 @@
</packing>
</child>
<child>
<widget class="GtkLabel" id="label53">
<property name="visible">True</property>
<property name="label" translatable="yes">Netmask:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">1</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label54">
<property name="visible">True</property>
@ -1226,8 +1198,8 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
@ -1254,15 +1226,15 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="net-ip4-address">
<widget class="GtkEntry" id="net-ip4-network">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
@ -1283,7 +1255,7 @@
</child>
<child>
<widget class="GtkEntry" id="net-ip4-netmask">
<widget class="GtkEntry" id="net-ip4-dhcp-start">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
@ -1304,7 +1276,7 @@
</child>
<child>
<widget class="GtkEntry" id="net-ip4-dhcp-start">
<widget class="GtkEntry" id="net-ip4-dhcp-end">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
@ -1324,27 +1296,6 @@
</packing>
</child>
<child>
<widget class="GtkEntry" id="net-ip4-dhcp-end">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char">•</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label26">
<property name="visible">True</property>
@ -1366,8 +1317,8 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
@ -1422,8 +1373,8 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
</packing>
@ -1490,6 +1441,7 @@
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_net_delete_clicked" last_modification_time="Tue, 03 Apr 2007 17:05:22 GMT"/>
</widget>
</child>
@ -1500,6 +1452,7 @@
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_net_start_clicked" last_modification_time="Tue, 03 Apr 2007 17:05:17 GMT"/>
<child>
<widget class="GtkAlignment" id="alignment7">
@ -1576,6 +1529,7 @@
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_net_stop_clicked" last_modification_time="Tue, 03 Apr 2007 17:05:12 GMT"/>
</widget>
</child>
</widget>