mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
Support viewing and removing VM 'video' devices.
This commit is contained in:
parent
79f3e9987e
commit
10be2d2a45
@ -61,12 +61,13 @@ HW_LIST_TYPE_GRAPHICS = 8
|
|||||||
HW_LIST_TYPE_SOUND = 9
|
HW_LIST_TYPE_SOUND = 9
|
||||||
HW_LIST_TYPE_CHAR = 10
|
HW_LIST_TYPE_CHAR = 10
|
||||||
HW_LIST_TYPE_HOSTDEV = 11
|
HW_LIST_TYPE_HOSTDEV = 11
|
||||||
|
HW_LIST_TYPE_VIDEO = 12
|
||||||
|
|
||||||
apply_pages = [ HW_LIST_TYPE_GENERAL, HW_LIST_TYPE_CPU, HW_LIST_TYPE_MEMORY,
|
apply_pages = [ HW_LIST_TYPE_GENERAL, HW_LIST_TYPE_CPU, HW_LIST_TYPE_MEMORY,
|
||||||
HW_LIST_TYPE_BOOT]
|
HW_LIST_TYPE_BOOT]
|
||||||
remove_pages = [ HW_LIST_TYPE_DISK, HW_LIST_TYPE_NIC, HW_LIST_TYPE_INPUT,
|
remove_pages = [ HW_LIST_TYPE_DISK, HW_LIST_TYPE_NIC, HW_LIST_TYPE_INPUT,
|
||||||
HW_LIST_TYPE_GRAPHICS, HW_LIST_TYPE_SOUND, HW_LIST_TYPE_CHAR,
|
HW_LIST_TYPE_GRAPHICS, HW_LIST_TYPE_SOUND, HW_LIST_TYPE_CHAR,
|
||||||
HW_LIST_TYPE_HOSTDEV ]
|
HW_LIST_TYPE_HOSTDEV, HW_LIST_TYPE_VIDEO ]
|
||||||
|
|
||||||
# Console pages
|
# Console pages
|
||||||
PAGE_UNAVAILABLE = 0
|
PAGE_UNAVAILABLE = 0
|
||||||
@ -693,6 +694,8 @@ class vmmDetails(gobject.GObject):
|
|||||||
self.refresh_char_page()
|
self.refresh_char_page()
|
||||||
elif pagetype == HW_LIST_TYPE_HOSTDEV:
|
elif pagetype == HW_LIST_TYPE_HOSTDEV:
|
||||||
self.refresh_hostdev_page()
|
self.refresh_hostdev_page()
|
||||||
|
elif pagetype == HW_LIST_TYPE_VIDEO:
|
||||||
|
self.refresh_video_page()
|
||||||
else:
|
else:
|
||||||
pagetype = -1
|
pagetype = -1
|
||||||
|
|
||||||
@ -1142,6 +1145,20 @@ class vmmDetails(gobject.GObject):
|
|||||||
self.window.get_widget("hostdev-mode").set_text(hostdevinfo[3])
|
self.window.get_widget("hostdev-mode").set_text(hostdevinfo[3])
|
||||||
self.window.get_widget("hostdev-source").set_text(hostdevinfo[5])
|
self.window.get_widget("hostdev-source").set_text(hostdevinfo[5])
|
||||||
|
|
||||||
|
def refresh_video_page(self):
|
||||||
|
vidinfo = self.get_hw_selection(HW_LIST_COL_DEVICE)
|
||||||
|
if not vidinfo:
|
||||||
|
return
|
||||||
|
|
||||||
|
ignore, ignore, model, ram, heads = vidinfo
|
||||||
|
try:
|
||||||
|
ramlabel = ram and "%d MB" % (int(ram) / 1024) or "-"
|
||||||
|
except:
|
||||||
|
ramlabel = "-"
|
||||||
|
|
||||||
|
self.window.get_widget("video-model").set_text(model)
|
||||||
|
self.window.get_widget("video-ram").set_text(ramlabel)
|
||||||
|
self.window.get_widget("video-heads").set_text(heads and heads or "-")
|
||||||
|
|
||||||
def refresh_boot_page(self):
|
def refresh_boot_page(self):
|
||||||
# Refresh autostart
|
# Refresh autostart
|
||||||
@ -1743,6 +1760,7 @@ class vmmDetails(gobject.GObject):
|
|||||||
currentSounds = {}
|
currentSounds = {}
|
||||||
currentChars = {}
|
currentChars = {}
|
||||||
currentHostdevs = {}
|
currentHostdevs = {}
|
||||||
|
currentVids = {}
|
||||||
|
|
||||||
def update_hwlist(hwtype, info):
|
def update_hwlist(hwtype, info):
|
||||||
"""Return (true if we updated an entry,
|
"""Return (true if we updated an entry,
|
||||||
@ -1843,6 +1861,17 @@ class vmmDetails(gobject.GObject):
|
|||||||
if missing:
|
if missing:
|
||||||
hw_list_model.insert(insertAt, [hostdevinfo[2], None, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_HOSTDEV, hostdevinfo])
|
hw_list_model.insert(insertAt, [hostdevinfo[2], None, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_HOSTDEV, hostdevinfo])
|
||||||
|
|
||||||
|
# Populate video devices
|
||||||
|
for vidinfo in self.vm.get_video_devices():
|
||||||
|
currentVids[vidinfo[2]] = 1
|
||||||
|
missing, insertAt = update_hwlist(HW_LIST_TYPE_VIDEO,
|
||||||
|
vidinfo)
|
||||||
|
|
||||||
|
if missing:
|
||||||
|
hw_list_model.insert(insertAt,
|
||||||
|
[_("Video"), gtk.STOCK_SELECT_COLOR,
|
||||||
|
gtk.ICON_SIZE_LARGE_TOOLBAR,
|
||||||
|
None, HW_LIST_TYPE_VIDEO, vidinfo])
|
||||||
|
|
||||||
# Now remove any no longer current devs
|
# Now remove any no longer current devs
|
||||||
devs = range(len(hw_list_model))
|
devs = range(len(hw_list_model))
|
||||||
@ -1852,26 +1881,21 @@ class vmmDetails(gobject.GObject):
|
|||||||
row = hw_list_model[i]
|
row = hw_list_model[i]
|
||||||
removeIt = False
|
removeIt = False
|
||||||
|
|
||||||
if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_DISK and not \
|
mapping = {
|
||||||
currentDisks.has_key(row[HW_LIST_COL_DEVICE][2]):
|
HW_LIST_TYPE_DISK : currentDisks,
|
||||||
removeIt = True
|
HW_LIST_TYPE_NIC : currentNICs,
|
||||||
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_NIC and not \
|
HW_LIST_TYPE_INPUT : currentInputs,
|
||||||
currentNICs.has_key(row[HW_LIST_COL_DEVICE][2]):
|
HW_LIST_TYPE_GRAPHICS : currentGraphics,
|
||||||
removeIt = True
|
HW_LIST_TYPE_SOUND : currentSounds,
|
||||||
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_INPUT and not \
|
HW_LIST_TYPE_CHAR : currentChars,
|
||||||
currentInputs.has_key(row[HW_LIST_COL_DEVICE][2]):
|
HW_LIST_TYPE_HOSTDEV : currentHostdevs,
|
||||||
removeIt = True
|
HW_LIST_TYPE_VIDEO : currentVids,
|
||||||
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_GRAPHICS and not \
|
}
|
||||||
currentGraphics.has_key(row[HW_LIST_COL_DEVICE][2]):
|
|
||||||
removeIt = True
|
|
||||||
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_SOUND and not \
|
hwtype = row[HW_LIST_COL_TYPE]
|
||||||
currentSounds.has_key(row[HW_LIST_COL_DEVICE][2]):
|
if (mapping.has_key(hwtype) and not
|
||||||
removeIt = True
|
mapping[hwtype].has_key(row[HW_LIST_COL_DEVICE][2])):
|
||||||
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_CHAR and not \
|
|
||||||
currentChars.has_key(row[HW_LIST_COL_DEVICE][2]):
|
|
||||||
removeIt = True
|
|
||||||
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_HOSTDEV and not \
|
|
||||||
currentHostdevs.has_key(row[HW_LIST_COL_DEVICE][2]):
|
|
||||||
removeIt = True
|
removeIt = True
|
||||||
|
|
||||||
if removeIt:
|
if removeIt:
|
||||||
@ -1880,7 +1904,8 @@ class vmmDetails(gobject.GObject):
|
|||||||
(selModel, selIter) = hw_list.get_selection().get_selected()
|
(selModel, selIter) = hw_list.get_selection().get_selected()
|
||||||
selType = selModel.get_value(selIter, HW_LIST_COL_TYPE)
|
selType = selModel.get_value(selIter, HW_LIST_COL_TYPE)
|
||||||
selInfo = selModel.get_value(selIter, HW_LIST_COL_DEVICE)
|
selInfo = selModel.get_value(selIter, HW_LIST_COL_DEVICE)
|
||||||
if selType == row[HW_LIST_COL_TYPE] and selInfo[2] == row[HW_LIST_COL_DEVICE][2]:
|
if (selType == row[HW_LIST_COL_TYPE] and
|
||||||
|
selInfo[2] == row[HW_LIST_COL_DEVICE][2]):
|
||||||
hw_list.get_selection().select_iter(selModel.iter_nth_child(None, 0))
|
hw_list.get_selection().select_iter(selModel.iter_nth_child(None, 0))
|
||||||
|
|
||||||
# Now actually remove it
|
# Now actually remove it
|
||||||
|
@ -28,6 +28,13 @@ import difflib
|
|||||||
from virtManager import util
|
from virtManager import util
|
||||||
import virtinst.util as vutil
|
import virtinst.util as vutil
|
||||||
|
|
||||||
|
def safeint(val, fmt="%.3d"):
|
||||||
|
try:
|
||||||
|
int(val)
|
||||||
|
except:
|
||||||
|
return str(val)
|
||||||
|
return fmt % int(val)
|
||||||
|
|
||||||
class vmmDomain(gobject.GObject):
|
class vmmDomain(gobject.GObject):
|
||||||
__gsignals__ = {
|
__gsignals__ = {
|
||||||
"status-changed": (gobject.SIGNAL_RUN_FIRST,
|
"status-changed": (gobject.SIGNAL_RUN_FIRST,
|
||||||
@ -932,6 +939,32 @@ class vmmDomain(gobject.GObject):
|
|||||||
|
|
||||||
return self._parse_device_xml(_parse_char_devs)
|
return self._parse_device_xml(_parse_char_devs)
|
||||||
|
|
||||||
|
def get_video_devices(self):
|
||||||
|
def _parse_video_devs(ctx):
|
||||||
|
vids = []
|
||||||
|
devs = ctx.xpathEval("/domain/devices/video")
|
||||||
|
|
||||||
|
for dev in devs:
|
||||||
|
model = None
|
||||||
|
ram = None
|
||||||
|
heads = None
|
||||||
|
|
||||||
|
for node in dev.children or []:
|
||||||
|
if node.name == "model":
|
||||||
|
model = node.prop("type")
|
||||||
|
ram = node.prop("vram")
|
||||||
|
heads = node.prop("heads")
|
||||||
|
|
||||||
|
if ram:
|
||||||
|
ram = safeint(ram, "%d")
|
||||||
|
|
||||||
|
unique = [model, ram, heads]
|
||||||
|
row = ["video", unique, model, ram, heads]
|
||||||
|
vids.append(row)
|
||||||
|
|
||||||
|
return vids
|
||||||
|
return self._parse_device_xml(_parse_video_devs)
|
||||||
|
|
||||||
def get_hostdev_devices(self):
|
def get_hostdev_devices(self):
|
||||||
def _parse_hostdev_devs(ctx):
|
def _parse_hostdev_devs(ctx):
|
||||||
hostdevs = []
|
hostdevs = []
|
||||||
@ -954,13 +987,6 @@ class vmmDomain(gobject.GObject):
|
|||||||
val = val[2:]
|
val = val[2:]
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def safeint(val, fmt="%.3d"):
|
|
||||||
try:
|
|
||||||
int(val)
|
|
||||||
except:
|
|
||||||
return str(val)
|
|
||||||
return fmt % int(val)
|
|
||||||
|
|
||||||
def set_uniq(baseent, propname, node):
|
def set_uniq(baseent, propname, node):
|
||||||
val = node.prop(propname)
|
val = node.prop(propname)
|
||||||
if not unique.has_key(baseent):
|
if not unique.has_key(baseent):
|
||||||
@ -1028,15 +1054,10 @@ class vmmDomain(gobject.GObject):
|
|||||||
|
|
||||||
|
|
||||||
def _parse_device_xml(self, parse_function):
|
def _parse_device_xml(self, parse_function):
|
||||||
ret = []
|
|
||||||
def parse_wrap_func(doc, ctx):
|
def parse_wrap_func(doc, ctx):
|
||||||
return parse_function(ctx)
|
return parse_function(ctx)
|
||||||
|
|
||||||
try:
|
return util.xml_parse_wrapper(self.get_xml(), parse_wrap_func)
|
||||||
ret = util.xml_parse_wrapper(self.get_xml(), parse_wrap_func)
|
|
||||||
except Exception, e:
|
|
||||||
raise RuntimeError(_("Error parsing domain xml: %s") % str(e))
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def _add_xml_device(self, xml, devxml):
|
def _add_xml_device(self, xml, devxml):
|
||||||
"""
|
"""
|
||||||
@ -1136,6 +1157,19 @@ class vmmDomain(gobject.GObject):
|
|||||||
logging.debug("Hostdev xpath string: %s" % xpath)
|
logging.debug("Hostdev xpath string: %s" % xpath)
|
||||||
ret = ctx.xpathEval(xpath)
|
ret = ctx.xpathEval(xpath)
|
||||||
|
|
||||||
|
elif dev_type == "video":
|
||||||
|
model, ram, heads = dev_id_info
|
||||||
|
xpath = "/domain/devices/video"
|
||||||
|
|
||||||
|
xpath += "[model/@type='%s'" % model
|
||||||
|
if ram:
|
||||||
|
xpath += " and model/@vram='%s'" % ram
|
||||||
|
if heads:
|
||||||
|
xpath += " and model/@heads='%s'" % heads
|
||||||
|
xpath += "][1]"
|
||||||
|
|
||||||
|
ret = ctx.xpathEval(xpath)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise RuntimeError, _("Unknown device type '%s'" % dev_type)
|
raise RuntimeError, _("Unknown device type '%s'" % dev_type)
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user