FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Fedora/Linux Management Tools

 
 
LinkBack Thread Tools
 
Old 07-28-2008, 03:51 PM
Cole Robinson
 
Default virt-manager: show serial/parallel devices

The attached patch teaches virt-manager how to parse VM
character devices, showing them in the details section.
This patch also implements removing these devices.

There are a couple quirks though:

1) All the possible character device xml properties
aren't accounted for. This only parses target port,
device type, and source path. I figure this covers
the common cases, and is easily expandable.

2) Explicit entries are only set for serial and parallel
devices, not console devices. Since by default, console
is really just a duplicate of the first serial device,
we try to detect this and label said serial device as
appropriately (seen in the second screen shot).
This simplifies things a good deal, and makes deleting
easier, since in order to remove the console or
first serial device, both xml blocks need to be removed
simultaneously (not sure if this is a libvirt bug or not).

I've posted a couple screenshots to give a better idea:

Parallel device:
http://crobinso.fedorapeople.org/virt-manager/vmm-parallel.png

Serial device that is also the console device:
http://crobinso.fedorapeople.org/virt-manager/vmm-serial.png

Thanks,
Cole
# HG changeset patch
# User "Cole Robinson <crobinso@redhat.com>"
# Date 1216924902 14400
# Node ID 2bbb1937e47b24db7257288117f0a9c5e50ee694
# Parent 8ff3fe2b729ea60b9393dfb778067007a03e2e4b
Populate serial and parallel devices in details section. Allow deleting them as well.

diff -r 8ff3fe2b729e -r 2bbb1937e47b src/virtManager/details.py
--- a/src/virtManager/details.py Fri Jul 18 21:34:13 2008 -0400
+++ b/src/virtManager/details.py Thu Jul 24 14:41:42 2008 -0400
@@ -56,6 +56,7 @@
HW_LIST_TYPE_INPUT = 5
HW_LIST_TYPE_GRAPHICS = 6
HW_LIST_TYPE_SOUND = 7
+HW_LIST_TYPE_CHAR = 8

# Console pages
PAGE_UNAVAILABLE = 0
@@ -254,6 +255,7 @@
"on_config_input_remove_clicked": self.remove_input,
"on_config_graphics_remove_clicked": self.remove_graphics,
"on_config_sound_remove_clicked": self.remove_sound,
+ "on_config_char_remove_clicked": self.remove_char,
"on_add_hardware_button_clicked": self.add_hardware,

"on_details_menu_view_fullscreen_activate": self.toggle_fullscreen,
@@ -541,6 +543,8 @@
self.refresh_graphics_page()
elif pagetype == HW_LIST_TYPE_SOUND:
self.refresh_sound_page()
+ elif pagetype == HW_LIST_TYPE_CHAR:
+ self.refresh_char_page()
elif pagetype == HW_LIST_TYPE_BOOT:
self.refresh_boot_page()
self.window.get_widget("config-boot-options-apply").set_sensitive(False)
@@ -727,6 +731,8 @@
self.refresh_graphics_page()
elif pagetype == HW_LIST_TYPE_SOUND:
self.refresh_sound_page()
+ elif pagetype == HW_LIST_TYPE_CHAR:
+ self.refresh_char_page()

def refresh_summary(self):
self.window.get_widget("overview-cpu-usage-text").set_text("%d %%" % self.vm.cpu_time_percentage())
@@ -911,6 +917,26 @@
self.window.get_widget("config-sound-remove").set_sensitive(False)
else:
self.window.get_widget("config-sound-remove").set_sensitive(True)
+
+ def refresh_char_page(self):
+ vmlist = self.window.get_widget("hw-list")
+ selection = vmlist.get_selection()
+ active = selection.get_selected()
+ if active[1] is None:
+ return
+ char = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
+ typelabel = "<b>%s Device %s</b>" % (char[0].capitalize(),
+ char[5] and _("(Primary Console)") or "")
+ self.window.get_widget("char-type").set_markup(typelabel)
+ self.window.get_widget("char-dev-type").set_text(char[1] or "-")
+ self.window.get_widget("char-target-port").set_text(char[2])
+ self.window.get_widget("char-source-path").set_text(char[4] or "-")
+
+ # Can't remove char dev from live guest
+ if self.vm.is_active():
+ self.window.get_widget("config-char-remove").set_sensitive(False)
+ else:
+ self.window.get_widget("config-char-remove").set_sensitive(True)

def refresh_boot_page(self):
# Refresh autostart
@@ -1330,6 +1356,20 @@
self.remove_device(xml)
self.refresh_resources()

+ def remove_char(self, src):
+ vmlist = self.window.get_widget("hw-list")
+ selection = vmlist.get_selection()
+ active = selection.get_selected()
+ if active[1] is None:
+ return
+ char = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
+
+ xml = "<%s>
" % char[0] +
+ " <target port='%s'/>
" % char[2] +
+ "</%s>" % char[0]
+ self.remove_device(xml)
+ self.refresh_resources()
+
def prepare_hw_list(self):
hw_list_model = gtk.ListStore(str, str, int, gtk.gdk.Pixbuf, int, gobject.TYPE_PYOBJECT)
self.window.get_widget("hw-list").set_model(hw_list_model)
@@ -1479,6 +1519,27 @@
if missing:
hw_list_model.insert(insertAt, [_("Sound: %s" % sound[3]), gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_SOUND, sound])

+
+ # Populate list of char devices
+ currentChars = {}
+ for char in self.vm.get_char_devices():
+ missing = True
+ insertAt = 0
+ currentChars[char[3]] = 1
+ for row in hw_list_model:
+ if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_CHAR and
+ row[HW_LIST_COL_DEVICE][3] == char[3]:
+ # Update metadata
+ row[HW_LIST_COL_DEVICE] = char
+ missing = False
+
+ if row[HW_LIST_COL_TYPE] <= HW_LIST_TYPE_CHAR:
+ insertAt = insertAt + 1
+ # Add in row
+ if missing:
+ hw_list_model.insert(insertAt, ["%s %s" % (char[0].capitalize(), char[2]), gtk.STOCK_CONNECT, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_CHAR, char])
+
+
# Now remove any no longer current devs
devs = range(len(hw_list_model))
devs.reverse()
@@ -1497,6 +1558,9 @@
removeIt = True
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_SOUND and not
currentSounds.has_key(row[HW_LIST_COL_DEVICE][3]):
+ removeIt = True
+ elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_CHAR and not
+ currentChars.has_key(row[HW_LIST_COL_DEVICE][3]):
removeIt = True

if removeIt:
diff -r 8ff3fe2b729e -r 2bbb1937e47b src/virtManager/domain.py
--- a/src/virtManager/domain.py Fri Jul 18 21:34:13 2008 -0400
+++ b/src/virtManager/domain.py Thu Jul 24 14:41:42 2008 -0400
@@ -702,6 +702,46 @@

return self._parse_device_xml(_parse_sound_devs)

+ def get_char_devices(self):
+ def _parse_char_devs(ctx):
+ chars = []
+ devs = []
+ cons = ctx.xpathEval("/domain/devices/console")
+ devs.extend(ctx.xpathEval("/domain/devices/parallel"))
+ devs.extend(ctx.xpathEval("/domain/devices/serial"))
+
+ # Since there is only one 'console' device ever in the xml
+ # find its port (if present)
+ cons_port = None
+ for node in cons:
+ for child in node.children:
+ if child.name == "target":
+ cons_port = child.prop("port")
+
+ for node in devs:
+ char_type = node.name
+ dev_type = node.prop("type")
+ target_port = None
+ source_path = None
+ console_dev = False
+
+ for child in node.children:
+ if child.name == "target":
+ target_port = child.prop("port")
+ if child.name == "source":
+ source_path = child.prop("path")
+
+ if node.name == "serial" and target_port == cons_port:
+ # Console is just a dupe of this serial device
+ console_dev = True
+
+ chars.append([char_type, dev_type, target_port,
+ "%s:%s" % (char_type, target_port),
+ source_path, console_dev])
+ return chars
+
+ return self._parse_device_xml(_parse_char_devs)
+
def _parse_device_xml(self, parse_function):
doc = None
ctx = None
@@ -803,6 +843,30 @@
if len(model) > 0 and model[0].content != None:
logging.debug("Looking for type %s" % model[0].content)
ret = ctx.xpathEval("/domain/devices/sound[@model='%s']" % model[0].content)
+
+ elif dev_type == "parallel" or dev_type == "console" or
+ dev_type == "serial":
+ port = dev_ctx.xpathEval("/%s/target/@port" % dev_type)
+ if port and len(port) > 0 and port[0].content != None:
+ logging.debug("Looking for %s w/ port %s" % (dev_type,
+ port))
+ ret = ctx.xpathEval("/domain/devices/%s[target/@port='%s']" % (dev_type, port[0].content))
+
+ # If serial and console are both present, console is
+ # probably (always?) just a dup of the 'primary' serial
+ # device. Try and find an associated console device with
+ # the same port and remove that as well, otherwise the
+ # removal doesn't go through
+ if dev_type == "serial":
+ cons_ret = ctx.xpathEval("/domain/devices/console[target/@port='%s']" % port[0].content)
+ if cons_ret and len(cons_ret) > 0:
+ logging.debug("Also removing console device "
+ "associated with serial dev.")
+ cons_ret[0].unlinkNode()
+ cons_ret[0].freeNode()
+ else:
+ logging.debug("No console device found associated "
+ "with passed serial devices")

else:
raise RuntimeError, _("Unknown device type device type '%s'" %
diff -r 8ff3fe2b729e -r 2bbb1937e47b src/vmm-details.glade
--- a/src/vmm-details.glade Fri Jul 18 21:34:13 2008 -0400
+++ b/src/vmm-details.glade Thu Jul 24 14:41:42 2008 -0400
@@ -1550,7 +1550,7 @@
<widget class="GtkHPaned" id="hpaned1">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="position">200</property>
+ <property name="position">230</property>

<child>
<widget class="GtkVBox" id="vbox53">
@@ -4658,6 +4658,299 @@
<property name="type">tab</property>
</packing>
</child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox59">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkFrame" id="frame14">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment160">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkTable" id="table37">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="n_rows">3</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="GtkLabel" id="label503">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Device Type:</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">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label504">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Target Port:</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="label505">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Source Path:</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="char-dev-type">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">label506</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">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="char-target-port">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">label507</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">1</property>
+ <property name="right_attach">2</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="char-source-path">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">label508</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">1</property>
+ <property name="right_attach">2</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>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="char-type">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;b&gt;insert type&lt;/b&gt;</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</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="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">15</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox15">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="config-char-remove">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-remove</property>
+ <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_config_char_remove_clicked" last_modification_time="Sat, 19 Jul 2008 01:39:51 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label501">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Char</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.5</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="type">tab</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="shrink">True</property>
_______________________________________________
et-mgmt-tools mailing list
et-mgmt-tools@redhat.com
https://www.redhat.com/mailman/listinfo/et-mgmt-tools
 
Old 07-29-2008, 08:39 AM
"Daniel P. Berrange"
 
Default virt-manager: show serial/parallel devices

On Mon, Jul 28, 2008 at 11:51:49AM -0400, Cole Robinson wrote:
> The attached patch teaches virt-manager how to parse VM
> character devices, showing them in the details section.
> This patch also implements removing these devices.
>
> There are a couple quirks though:
>
> 1) All the possible character device xml properties
> aren't accounted for. This only parses target port,
> device type, and source path. I figure this covers
> the common cases, and is easily expandable.
>
> 2) Explicit entries are only set for serial and parallel
> devices, not console devices. Since by default, console
> is really just a duplicate of the first serial device,
> we try to detect this and label said serial device as
> appropriately (seen in the second screen shot).
> This simplifies things a good deal, and makes deleting
> easier, since in order to remove the console or
> first serial device, both xml blocks need to be removed
> simultaneously (not sure if this is a libvirt bug or not).

I think that is probably a bug. Can you re-test with the latest
CVS snapshot of libvirt where I've changed the handling a little
bit. Basically you should never need to add or remove a 'console'
device explicitly. Either it is there permanently (eg, Xen PV
always has a console), or it is automatically added/removed when
the first serial device is added or removed.


> diff -r 8ff3fe2b729e -r 2bbb1937e47b src/virtManager/details.py
> --- a/src/virtManager/details.py Fri Jul 18 21:34:13 2008 -0400
> +++ b/src/virtManager/details.py Thu Jul 24 14:41:42 2008 -0400
> @@ -56,6 +56,7 @@
> HW_LIST_TYPE_INPUT = 5
> HW_LIST_TYPE_GRAPHICS = 6
> HW_LIST_TYPE_SOUND = 7
> +HW_LIST_TYPE_CHAR = 8
>
> # Console pages
> PAGE_UNAVAILABLE = 0
> @@ -254,6 +255,7 @@
> "on_config_input_remove_clicked": self.remove_input,
> "on_config_graphics_remove_clicked": self.remove_graphics,
> "on_config_sound_remove_clicked": self.remove_sound,
> + "on_config_char_remove_clicked": self.remove_char,
> "on_add_hardware_button_clicked": self.add_hardware,
>
> "on_details_menu_view_fullscreen_activate": self.toggle_fullscreen,
> @@ -541,6 +543,8 @@
> self.refresh_graphics_page()
> elif pagetype == HW_LIST_TYPE_SOUND:
> self.refresh_sound_page()
> + elif pagetype == HW_LIST_TYPE_CHAR:
> + self.refresh_char_page()
> elif pagetype == HW_LIST_TYPE_BOOT:
> self.refresh_boot_page()
> self.window.get_widget("config-boot-options-apply").set_sensitive(False)
> @@ -727,6 +731,8 @@
> self.refresh_graphics_page()
> elif pagetype == HW_LIST_TYPE_SOUND:
> self.refresh_sound_page()
> + elif pagetype == HW_LIST_TYPE_CHAR:
> + self.refresh_char_page()
>
> def refresh_summary(self):
> self.window.get_widget("overview-cpu-usage-text").set_text("%d %%" % self.vm.cpu_time_percentage())
> @@ -911,6 +917,26 @@
> self.window.get_widget("config-sound-remove").set_sensitive(False)
> else:
> self.window.get_widget("config-sound-remove").set_sensitive(True)
> +
> + def refresh_char_page(self):
> + vmlist = self.window.get_widget("hw-list")
> + selection = vmlist.get_selection()
> + active = selection.get_selected()
> + if active[1] is None:
> + return
> + char = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
> + typelabel = "<b>%s Device %s</b>" % (char[0].capitalize(),
> + char[5] and _("(Primary Console)") or "")
> + self.window.get_widget("char-type").set_markup(typelabel)
> + self.window.get_widget("char-dev-type").set_text(char[1] or "-")
> + self.window.get_widget("char-target-port").set_text(char[2])
> + self.window.get_widget("char-source-path").set_text(char[4] or "-")
> +
> + # Can't remove char dev from live guest
> + if self.vm.is_active():
> + self.window.get_widget("config-char-remove").set_sensitive(False)
> + else:
> + self.window.get_widget("config-char-remove").set_sensitive(True)
>
> def refresh_boot_page(self):
> # Refresh autostart
> @@ -1330,6 +1356,20 @@
> self.remove_device(xml)
> self.refresh_resources()
>
> + def remove_char(self, src):
> + vmlist = self.window.get_widget("hw-list")
> + selection = vmlist.get_selection()
> + active = selection.get_selected()
> + if active[1] is None:
> + return
> + char = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
> +
> + xml = "<%s>
" % char[0] +
> + " <target port='%s'/>
" % char[2] +
> + "</%s>" % char[0]
> + self.remove_device(xml)
> + self.refresh_resources()
> +
> def prepare_hw_list(self):
> hw_list_model = gtk.ListStore(str, str, int, gtk.gdk.Pixbuf, int, gobject.TYPE_PYOBJECT)
> self.window.get_widget("hw-list").set_model(hw_list_model)
> @@ -1479,6 +1519,27 @@
> if missing:
> hw_list_model.insert(insertAt, [_("Sound: %s" % sound[3]), gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_SOUND, sound])
>
> +
> + # Populate list of char devices
> + currentChars = {}
> + for char in self.vm.get_char_devices():
> + missing = True
> + insertAt = 0
> + currentChars[char[3]] = 1
> + for row in hw_list_model:
> + if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_CHAR and
> + row[HW_LIST_COL_DEVICE][3] == char[3]:
> + # Update metadata
> + row[HW_LIST_COL_DEVICE] = char
> + missing = False
> +
> + if row[HW_LIST_COL_TYPE] <= HW_LIST_TYPE_CHAR:
> + insertAt = insertAt + 1
> + # Add in row
> + if missing:
> + hw_list_model.insert(insertAt, ["%s %s" % (char[0].capitalize(), char[2]), gtk.STOCK_CONNECT, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_CHAR, char])
> +
> +
> # Now remove any no longer current devs
> devs = range(len(hw_list_model))
> devs.reverse()
> @@ -1497,6 +1558,9 @@
> removeIt = True
> elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_SOUND and not
> currentSounds.has_key(row[HW_LIST_COL_DEVICE][3]):
> + removeIt = True
> + elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_CHAR and not
> + currentChars.has_key(row[HW_LIST_COL_DEVICE][3]):
> removeIt = True
>
> if removeIt:
> diff -r 8ff3fe2b729e -r 2bbb1937e47b src/virtManager/domain.py
> --- a/src/virtManager/domain.py Fri Jul 18 21:34:13 2008 -0400
> +++ b/src/virtManager/domain.py Thu Jul 24 14:41:42 2008 -0400
> @@ -702,6 +702,46 @@
>
> return self._parse_device_xml(_parse_sound_devs)
>
> + def get_char_devices(self):
> + def _parse_char_devs(ctx):
> + chars = []
> + devs = []
> + cons = ctx.xpathEval("/domain/devices/console")
> + devs.extend(ctx.xpathEval("/domain/devices/parallel"))
> + devs.extend(ctx.xpathEval("/domain/devices/serial"))
> +
> + # Since there is only one 'console' device ever in the xml
> + # find its port (if present)
> + cons_port = None
> + for node in cons:
> + for child in node.children:
> + if child.name == "target":
> + cons_port = child.prop("port")
> +
> + for node in devs:
> + char_type = node.name
> + dev_type = node.prop("type")
> + target_port = None
> + source_path = None
> + console_dev = False
> +
> + for child in node.children:
> + if child.name == "target":
> + target_port = child.prop("port")
> + if child.name == "source":
> + source_path = child.prop("path")
> +
> + if node.name == "serial" and target_port == cons_port:
> + # Console is just a dupe of this serial device
> + console_dev = True
> +
> + chars.append([char_type, dev_type, target_port,
> + "%s:%s" % (char_type, target_port),
> + source_path, console_dev])
> + return chars
> +
> + return self._parse_device_xml(_parse_char_devs)
> +
> def _parse_device_xml(self, parse_function):
> doc = None
> ctx = None
> @@ -803,6 +843,30 @@
> if len(model) > 0 and model[0].content != None:
> logging.debug("Looking for type %s" % model[0].content)
> ret = ctx.xpathEval("/domain/devices/sound[@model='%s']" % model[0].content)
> +
> + elif dev_type == "parallel" or dev_type == "console" or
> + dev_type == "serial":
> + port = dev_ctx.xpathEval("/%s/target/@port" % dev_type)
> + if port and len(port) > 0 and port[0].content != None:
> + logging.debug("Looking for %s w/ port %s" % (dev_type,
> + port))
> + ret = ctx.xpathEval("/domain/devices/%s[target/@port='%s']" % (dev_type, port[0].content))
> +
> + # If serial and console are both present, console is
> + # probably (always?) just a dup of the 'primary' serial
> + # device. Try and find an associated console device with
> + # the same port and remove that as well, otherwise the
> + # removal doesn't go through
> + if dev_type == "serial":
> + cons_ret = ctx.xpathEval("/domain/devices/console[target/@port='%s']" % port[0].content)
> + if cons_ret and len(cons_ret) > 0:
> + logging.debug("Also removing console device "
> + "associated with serial dev.")
> + cons_ret[0].unlinkNode()
> + cons_ret[0].freeNode()
> + else:
> + logging.debug("No console device found associated "
> + "with passed serial devices")
>
> else:
> raise RuntimeError, _("Unknown device type device type '%s'" %
> diff -r 8ff3fe2b729e -r 2bbb1937e47b src/vmm-details.glade
> --- a/src/vmm-details.glade Fri Jul 18 21:34:13 2008 -0400
> +++ b/src/vmm-details.glade Thu Jul 24 14:41:42 2008 -0400
> @@ -1550,7 +1550,7 @@
> <widget class="GtkHPaned" id="hpaned1">
> <property name="visible">True</property>
> <property name="can_focus">True</property>
> - <property name="position">200</property>
> + <property name="position">230</property>
>
> <child>
> <widget class="GtkVBox" id="vbox53">
> @@ -4658,6 +4658,299 @@
> <property name="type">tab</property>
> </packing>
> </child>
> +
> + <child>
> + <widget class="GtkVBox" id="vbox59">
> + <property name="visible">True</property>
> + <property name="homogeneous">False</property>
> + <property name="spacing">0</property>
> +
> + <child>
> + <widget class="GtkFrame" id="frame14">
> + <property name="visible">True</property>
> + <property name="label_xalign">0</property>
> + <property name="label_yalign">0.5</property>
> + <property name="shadow_type">GTK_SHADOW_NONE</property>
> +
> + <child>
> + <widget class="GtkAlignment" id="alignment160">
> + <property name="visible">True</property>
> + <property name="xalign">0.5</property>
> + <property name="yalign">0.5</property>
> + <property name="xscale">1</property>
> + <property name="yscale">1</property>
> + <property name="top_padding">0</property>
> + <property name="bottom_padding">0</property>
> + <property name="left_padding">12</property>
> + <property name="right_padding">0</property>
> +
> + <child>
> + <widget class="GtkTable" id="table37">
> + <property name="border_width">3</property>
> + <property name="visible">True</property>
> + <property name="n_rows">3</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="GtkLabel" id="label503">
> + <property name="visible">True</property>
> + <property name="label" translatable="yes">Device Type:</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">0</property>
> + <property name="bottom_attach">1</property>
> + <property name="x_options">fill</property>
> + <property name="y_options"></property>
> + </packing>
> + </child>
> +
> + <child>
> + <widget class="GtkLabel" id="label504">
> + <property name="visible">True</property>
> + <property name="label" translatable="yes">Target Port:</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="label505">
> + <property name="visible">True</property>
> + <property name="label" translatable="yes">Source Path:</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="char-dev-type">
> + <property name="visible">True</property>
> + <property name="label" translatable="yes">label506</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">1</property>
> + <property name="right_attach">2</property>
> + <property name="top_attach">0</property>
> + <property name="bottom_attach">1</property>
> + <property name="x_options">fill</property>
> + <property name="y_options"></property>
> + </packing>
> + </child>
> +
> + <child>
> + <widget class="GtkLabel" id="char-target-port">
> + <property name="visible">True</property>
> + <property name="label" translatable="yes">label507</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">1</property>
> + <property name="right_attach">2</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="char-source-path">
> + <property name="visible">True</property>
> + <property name="label" translatable="yes">label508</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">1</property>
> + <property name="right_attach">2</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>
> + </widget>
> + </child>
> + </widget>
> + </child>
> +
> + <child>
> + <widget class="GtkLabel" id="char-type">
> + <property name="visible">True</property>
> + <property name="label" translatable="yes">&lt;b&gt;insert type&lt;/b&gt;</property>
> + <property name="use_underline">False</property>
> + <property name="use_markup">True</property>
> + <property name="justify">GTK_JUSTIFY_LEFT</property>
> + <property name="wrap">False</property>
> + <property name="selectable">False</property>
> + <property name="xalign">0.5</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="type">label_item</property>
> + </packing>
> + </child>
> + </widget>
> + <packing>
> + <property name="padding">15</property>
> + <property name="expand">True</property>
> + <property name="fill">True</property>
> + </packing>
> + </child>
> +
> + <child>
> + <widget class="GtkHButtonBox" id="hbuttonbox15">
> + <property name="border_width">6</property>
> + <property name="visible">True</property>
> + <property name="layout_style">GTK_BUTTONBOX_END</property>
> + <property name="spacing">0</property>
> +
> + <child>
> + <widget class="GtkButton" id="config-char-remove">
> + <property name="visible">True</property>
> + <property name="can_default">True</property>
> + <property name="can_focus">True</property>
> + <property name="label">gtk-remove</property>
> + <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_config_char_remove_clicked" last_modification_time="Sat, 19 Jul 2008 01:39:51 GMT"/>
> + </widget>
> + </child>
> + </widget>
> + <packing>
> + <property name="padding">0</property>
> + <property name="expand">False</property>
> + <property name="fill">True</property>
> + </packing>
> + </child>
> + </widget>
> + <packing>
> + <property name="tab_expand">False</property>
> + <property name="tab_fill">True</property>
> + </packing>
> + </child>
> +
> + <child>
> + <widget class="GtkLabel" id="label501">
> + <property name="visible">True</property>
> + <property name="label" translatable="yes">Char</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.5</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="type">tab</property>
> + </packing>
> + </child>
> </widget>
> <packing>
> <property name="shrink">True</property>

> _______________________________________________
> et-mgmt-tools mailing list
> et-mgmt-tools@redhat.com
> https://www.redhat.com/mailman/listinfo/et-mgmt-tools

--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

_______________________________________________
et-mgmt-tools mailing list
et-mgmt-tools@redhat.com
https://www.redhat.com/mailman/listinfo/et-mgmt-tools
 
Old 07-29-2008, 04:28 PM
Cole Robinson
 
Default virt-manager: show serial/parallel devices

Daniel P. Berrange wrote:
> On Mon, Jul 28, 2008 at 11:51:49AM -0400, Cole Robinson wrote:
>> The attached patch teaches virt-manager how to parse VM
>> character devices, showing them in the details section.
>> This patch also implements removing these devices.
>>
>> There are a couple quirks though:
>>
>> 1) All the possible character device xml properties
>> aren't accounted for. This only parses target port,
>> device type, and source path. I figure this covers
>> the common cases, and is easily expandable.
>>
>> 2) Explicit entries are only set for serial and parallel
>> devices, not console devices. Since by default, console
>> is really just a duplicate of the first serial device,
>> we try to detect this and label said serial device as
>> appropriately (seen in the second screen shot).
>> This simplifies things a good deal, and makes deleting
>> easier, since in order to remove the console or
>> first serial device, both xml blocks need to be removed
>> simultaneously (not sure if this is a libvirt bug or not).
>
> I think that is probably a bug. Can you re-test with the latest
> CVS snapshot of libvirt where I've changed the handling a little
> bit. Basically you should never need to add or remove a 'console'
> device explicitly. Either it is there permanently (eg, Xen PV
> always has a console), or it is automatically added/removed when
> the first serial device is added or removed.
>
>

Cool, things seem to work with current upstream.

As far as the virt-manager code though, do you think it's a reasonable
approach (don't have an explicit console entry)?

Thanks,
Cole

_______________________________________________
et-mgmt-tools mailing list
et-mgmt-tools@redhat.com
https://www.redhat.com/mailman/listinfo/et-mgmt-tools
 
Old 07-29-2008, 04:51 PM
"Daniel P. Berrange"
 
Default virt-manager: show serial/parallel devices

On Tue, Jul 29, 2008 at 12:28:18PM -0400, Cole Robinson wrote:
> Daniel P. Berrange wrote:
> > On Mon, Jul 28, 2008 at 11:51:49AM -0400, Cole Robinson wrote:
> >> The attached patch teaches virt-manager how to parse VM
> >> character devices, showing them in the details section.
> >> This patch also implements removing these devices.
> >>
> >> There are a couple quirks though:
> >>
> >> 1) All the possible character device xml properties
> >> aren't accounted for. This only parses target port,
> >> device type, and source path. I figure this covers
> >> the common cases, and is easily expandable.
> >>
> >> 2) Explicit entries are only set for serial and parallel
> >> devices, not console devices. Since by default, console
> >> is really just a duplicate of the first serial device,
> >> we try to detect this and label said serial device as
> >> appropriately (seen in the second screen shot).
> >> This simplifies things a good deal, and makes deleting
> >> easier, since in order to remove the console or
> >> first serial device, both xml blocks need to be removed
> >> simultaneously (not sure if this is a libvirt bug or not).
> >
> > I think that is probably a bug. Can you re-test with the latest
> > CVS snapshot of libvirt where I've changed the handling a little
> > bit. Basically you should never need to add or remove a 'console'
> > device explicitly. Either it is there permanently (eg, Xen PV
> > always has a console), or it is automatically added/removed when
> > the first serial device is added or removed.
>
> Cool, things seem to work with current upstream.
>
> As far as the virt-manager code though, do you think it's a reasonable
> approach (don't have an explicit console entry)?

This a little bit of an annoying part due to the way we had to maintain
backwards comaptability with the XML format. You can skip the 'console'
entry if-and-only-if there is at least one serial device. If there's
no serial device, you'll need to explicitly list the console.

Daniel
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

_______________________________________________
et-mgmt-tools mailing list
et-mgmt-tools@redhat.com
https://www.redhat.com/mailman/listinfo/et-mgmt-tools
 
Old 07-31-2008, 03:29 PM
Cole Robinson
 
Default virt-manager: show serial/parallel devices

Daniel P. Berrange wrote:
> On Tue, Jul 29, 2008 at 12:28:18PM -0400, Cole Robinson wrote:
>> Daniel P. Berrange wrote:
>>> On Mon, Jul 28, 2008 at 11:51:49AM -0400, Cole Robinson wrote:
>>>> The attached patch teaches virt-manager how to parse VM
>>>> character devices, showing them in the details section.
>>>> This patch also implements removing these devices.
>>>>
>>>> There are a couple quirks though:
>>>>
>>>> 1) All the possible character device xml properties
>>>> aren't accounted for. This only parses target port,
>>>> device type, and source path. I figure this covers
>>>> the common cases, and is easily expandable.
>>>>
>>>> 2) Explicit entries are only set for serial and parallel
>>>> devices, not console devices. Since by default, console
>>>> is really just a duplicate of the first serial device,
>>>> we try to detect this and label said serial device as
>>>> appropriately (seen in the second screen shot).
>>>> This simplifies things a good deal, and makes deleting
>>>> easier, since in order to remove the console or
>>>> first serial device, both xml blocks need to be removed
>>>> simultaneously (not sure if this is a libvirt bug or not).
>>> I think that is probably a bug. Can you re-test with the latest
>>> CVS snapshot of libvirt where I've changed the handling a little
>>> bit. Basically you should never need to add or remove a 'console'
>>> device explicitly. Either it is there permanently (eg, Xen PV
>>> always has a console), or it is automatically added/removed when
>>> the first serial device is added or removed.
>>
>> Cool, things seem to work with current upstream.
>>
>> As far as the virt-manager code though, do you think it's a reasonable
>> approach (don't have an explicit console entry)?
>
> This a little bit of an annoying part due to the way we had to maintain
> backwards comaptability with the XML format. You can skip the 'console'
> entry if-and-only-if there is at least one serial device. If there's
> no serial device, you'll need to explicitly list the console.
>

Okay, i've committed this. The PV consoles will now be explictly listed.
I left the special case "remove console and serial at the same time" code
in incase this is released before a new libvirt spin.

http://hg.et.redhat.com/virt/applications/virt-manager--devel?cs=66ace61933db

Thanks,
Cole

_______________________________________________
et-mgmt-tools mailing list
et-mgmt-tools@redhat.com
https://www.redhat.com/mailman/listinfo/et-mgmt-tools
 

Thread Tools




All times are GMT. The time now is 08:31 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org