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 et-mgmt-tools@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/et-mgmt-tools