diff --git a/src/virtManager/connection.py b/src/virtManager/connection.py index d662d2b06..1585b64c3 100644 --- a/src/virtManager/connection.py +++ b/src/virtManager/connection.py @@ -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() diff --git a/src/virtManager/host.py b/src/virtManager/host.py index 8a99958f9..00962e47e 100644 --- a/src/virtManager/host.py +++ b/src/virtManager/host.py @@ -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: diff --git a/src/virtManager/network.py b/src/virtManager/network.py index d0f917555..9172fc770 100644 --- a/src/virtManager/network.py +++ b/src/virtManager/network.py @@ -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() diff --git a/src/vmm-host.glade b/src/vmm-host.glade index 02382e4ec..94192ddf4 100644 --- a/src/vmm-host.glade +++ b/src/vmm-host.glade @@ -1143,7 +1143,7 @@ 6 True - 5 + 4 2 False 3 @@ -1152,7 +1152,7 @@ True - Address: + Network: False False GTK_JUSTIFY_LEFT @@ -1177,34 +1177,6 @@ - - - True - Netmask: - False - False - GTK_JUSTIFY_LEFT - False - False - 1 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - 1 - 1 - 2 - fill - - - - True @@ -1226,8 +1198,8 @@ 0 1 - 2 - 3 + 1 + 2 fill @@ -1254,15 +1226,15 @@ 0 1 - 3 - 4 + 2 + 3 fill - + True True False @@ -1283,7 +1255,7 @@ - + True True False @@ -1304,7 +1276,7 @@ - + True True False @@ -1324,27 +1296,6 @@ - - - True - True - False - True - 0 - - True - - False - - - 1 - 2 - 3 - 4 - - - - True @@ -1366,8 +1317,8 @@ 0 1 - 4 - 5 + 3 + 4 fill @@ -1422,8 +1373,8 @@ 1 2 - 4 - 5 + 3 + 4 fill fill @@ -1490,6 +1441,7 @@ True GTK_RELIEF_NORMAL True + @@ -1500,6 +1452,7 @@ True GTK_RELIEF_NORMAL True + @@ -1576,6 +1529,7 @@ True GTK_RELIEF_NORMAL True +