Cole Robinson wrote:
> The attached patch adds support for avahi polling
> to the virt-manager 'Open Connection' dialog.
> libvirtd advertises itself via avahi so we get the
> hard stuff for free :). To test this you will need
> to make sure Multicast DNS (mDNS, port 5353 udp) is
> open on your machine.
>
Second cut of this patch. Issues resolved:
- Removed the check box, unconditionally poll for
connections if the user selects a remote conn
option.
- Only use advertised 'name' as the list entry.
- Don't add duplicate list entries.
- If creating the initial avahi dbus interface
fails, just disable all polling, and never
activate the connection list.
- Sort list entries alphabetically by default,
and add ability to sort ascend/descend
Thanks,
Cole
diff -r 0c2ab6040585 src/virtManager/connect.py
--- a/src/virtManager/connect.py Fri Aug 22 13:41:17 2008 -0400
+++ b/src/virtManager/connect.py Fri Aug 22 14:51:15 2008 -0400
@@ -23,6 +23,7 @@
import os
import virtinst
import logging
+import dbus
HV_XEN = 0
HV_QEMU = 1
@@ -53,6 +54,9 @@
"on_vmm_open_connection_delete_event": self.cancel,
})
+ self.browser = None
+ self.can_browse = False
+
default = virtinst.util.default_connection()
if default is None:
self.window.get_widget("hypervisor").set_active(-1)
@@ -65,6 +69,29 @@
self.window.get_widget("connect").grab_default()
self.window.get_widget("autoconnect").set_active(True)
+ connListModel = gtk.ListStore(str, str, str)
+ self.window.get_widget("conn-list").set_model(connListModel)
+
+ nameCol = gtk.TreeViewColumn(_("Name"))
+ name_txt = gtk.CellRendererText()
+ nameCol.pack_start(name_txt, True)
+ nameCol.add_attribute(name_txt, "text", 2)
+ nameCol.set_sort_column_id(2)
+ self.window.get_widget("conn-list").append_column(nameCol)
+ connListModel.set_sort_column_id(2, gtk.SORT_ASCENDING)
+
+ self.window.get_widget("conn-list").get_selection().connect("changed",
self.conn_selected)
+
+ self.bus = dbus.SystemBus()
+ try:
+ self.server =
dbus.Interface(self.bus.get_object("org.freedesktop.Avahi", "/"),
"org.freedesktop.Avahi.Server")
+ self.can_browse = True
+ except Exception, e:
+ logging.debug("Couldn't contact avahi: %s" % str(e))
+ self.server = None
+ self.can_browse = False
+
+ self.reset_state()
def cancel(self,ignore1=None,ignore2=None):
@@ -74,21 +101,112 @@
def close(self):
self.window.get_widget("vmm-open-connection").hide()
+ self.stop_browse()
def show(self):
win = self.window.get_widget("vmm-open-connection")
win.show_all()
win.present()
+ self.reset_state()
+
+ def reset_state(self):
+ self.window.get_widget("hypervisor").set_active(0)
+ self.window.get_widget("autoconnect").set_sensitive(True)
+ self.window.get_widget("autoconnect").set_active(True)
+ self.window.get_widget("conn-list").set_sensitive(False)
+ self.window.get_widget("conn-list").get_model().clear()
+ self.window.get_widget("hostname").set_text("")
+ self.stop_browse()
def update_widget_states(self, src):
if src.get_active() > 0:
self.window.get_widget("hostname").set_sensitive(True)
self.window.get_widget("autoconnect").set_active(False)
- self.window.get_widget("autoconnect").set_sensitive(False)
+ self.window.get_widget("autoconnect").set_sensitive(True)
+ if self.can_browse:
+ self.window.get_widget("conn-list").set_sensitive(True)
+ self.start_browse()
else:
+ self.window.get_widget("conn-list").set_sensitive(False)
self.window.get_widget("hostname").set_sensitive(False)
+ self.window.get_widget("hostname").set_text("")
self.window.get_widget("autoconnect").set_sensitive(True)
self.window.get_widget("autoconnect").set_active(True)
+ self.stop_browse()
+
+ def add_service(self, interface, protocol, name, type, domain, flags):
+ try:
+ # Async service resolving
+ res = self.server.ServiceResolverNew(interface, protocol, name,
+ type, domain, -1, 0)
+ resint =
dbus.Interface(self.bus.get_object("org.freedesktop.Avahi",
+ res),
+ "org.freedesktop.Avahi.ServiceResolver")
+ resint.connect_to_signal("Found", self.add_conn_to_list)
+ # Synchronous service resolving
+ #self.server.ResolveService(interface, protocol, name, type,
+ # domain, -1, 0)
+ except Exception, e:
+ logging.exception(e)
+
+ def remove_service(self, interface, protocol, name, type, domain, flags):
+ try:
+ model = self.window.get_widget("conn-list").get_model()
+ name = str(name)
+ for row in model:
+ if row[0] == name:
+ model.remove(row.iter)
+ except Exception, e:
+ logging.exception(e)
+
+ def add_conn_to_list(self, interface, protocol, name, type, domain,
+ host, aprotocol, address, port, text, flags):
+ try:
+ model = self.window.get_widget("conn-list").get_model()
+ for row in model:
+ if row[2] == str(name):
+ return
+ model.append([str(address), self.sanitize_hostname(str(host)),
+ str(name)])
+ except Exception, e:
+ logging.exception(e)
+
+ def start_browse(self):
+ if self.browser or not self.can_browse:
+ return
+ # Call method to create new browser, and get back an object path for
it.
+ interface = -1 # physical interface to use? -1 is unspec
+ protocol = 0 # 0 = IPv4, 1 = IPv6, -1 = Unspecified
+ service = '_libvirt._tcp' # Service name to poll for
+ flags = 0 # Extra option flags
+ domain = "" # Domain to browse in. NULL uses default
+ bpath = self.server.ServiceBrowserNew(interface, protocol, service,
+ domain, flags)
+
+ # Create browser interface for the new object
+ self.browser =
dbus.Interface(self.bus.get_object("org.freedesktop.Avahi",
+ bpath),
+ "org.freedesktop.Avahi.ServiceBrowser")
+
+ self.browser.connect_to_signal("ItemNew", self.add_service)
+ self.browser.connect_to_signal("ItemRemove", self.remove_service)
+
+ def stop_browse(self):
+ if self.browser:
+ del(self.browser)
+ self.browser = None
+
+ def conn_selected(self, src):
+ active = src.get_selected()
+ if active[1] == None:
+ return
+ ip = active[0].get_value(active[1], 0)
+ host = active[0].get_value(active[1], 1)
+ host = self.sanitize_hostname(host)
+ entry = host
+ if not entry:
+ entry = ip
+ self.window.get_widget("hostname").set_text(entry)
def open_connection(self, src):
hv = self.window.get_widget("hypervisor").get_active()
@@ -125,4 +243,18 @@
self.close()
self.emit("completed", uri, readOnly, auto)
+ def sanitize_hostname(self, host):
+ if host.endswith(".local"):
+ host = host[:-6]
+ if host == "linux" or host == "localhost":
+ host = ""
+ if host.startswith("linux-"):
+ tmphost = host[6:]
+ try:
+ tmp = long(tmphost)
+ host = ""
+ except ValueError:
+ pass
+ return host
+
gobject.type_register(vmmConnect)
diff -r 0c2ab6040585 src/vmm-open-connection.glade
--- a/src/vmm-open-connection.glade Fri Aug 22 13:41:17 2008 -0400
+++ b/src/vmm-open-connection.glade Fri Aug 22 14:51:15 2008 -0400
@@ -146,35 +146,11 @@
<widget class="GtkTable" id="table1">
<property name="border_width">6</property>
<property name="visible">True</property>
- <property name="n_rows">4</property>
+ <property name="n_rows">5</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">3</property>
<property name="column_spacing">3</property>
-
- <child>
- <widget class="GtkEntry" id="hostname">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="editable">True</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>
- <accessibility>
- <atkproperty name="AtkObject::accessible_name"
translatable="yes">Hostname Field</atkproperty>
- </accessibility>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options"></property>
- </packing>
- </child>
<child>
<widget class="GtkComboBox" id="connection">
@@ -201,34 +177,6 @@
</child>
<child>
- <widget class="GtkLabel" id="label89">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Hostname:</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">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options">fill</property>
- <property name="y_options"></property>
- </packing>
- </child>
-
- <child>
<widget class="GtkLabel" id="label88">
<property name="visible">True</property>
<property name="label" translatable="yes">Connection:</property>
@@ -237,7 +185,7 @@
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
- <property name="xalign">1</property>
+ <property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
@@ -265,7 +213,7 @@
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
- <property name="xalign">1</property>
+ <property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
@@ -307,16 +255,49 @@
</child>
<child>
- <widget class="GtkLabel" id="label90">
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="border_width">3</property>
+ <property name="width_request">70</property>
+ <property name="height_request">220</property>
<property name="visible">True</property>
- <property name="label" translatable="yes">Autoconnect
- At Startup:</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="conn-list">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">True</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ <property name="fixed_height_mode">False</property>
+ <property name="hover_selection">False</property>
+ <property name="hover_expand">False</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label91">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Hostname:</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="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
@@ -330,6 +311,59 @@
<property name="right_attach">1</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>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="hostname">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</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>
+ <accessibility>
+ <atkproperty name="AtkObject::accessible_name"
translatable="yes">Hostname Field</atkproperty>
+ </accessibility>
+ </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="label90">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Autoconnect
+ at Startup:</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">0</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">4</property>
+ <property name="bottom_attach">5</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
@@ -350,8 +384,8 @@
<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="top_attach">4</property>
+ <property name="bottom_attach">5</property>
<property name="x_padding">7</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
_______________________________________________
et-mgmt-tools mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/et-mgmt-tools