mirror of
https://github.com/virt-manager/virt-manager.git
synced 2026-08-14 06:54:51 -05:00
Break out shared storage UI to storagelist.py (bz 1060433)
We were already sharing a chunk of this in a haphazard way. Now officially break it all out, similar to netlist.py. This mostly unifies the views of host->storage and storagebrowser.py
This commit is contained in:
+17
-530
@@ -22,20 +22,16 @@ import logging
|
||||
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
from virtinst import VirtualDisk
|
||||
from virtinst import StoragePool
|
||||
from virtinst import Interface
|
||||
|
||||
from . import uiutil
|
||||
from .asyncjob import vmmAsyncJob
|
||||
from .createnet import vmmCreateNetwork
|
||||
from .createpool import vmmCreatePool
|
||||
from .createvol import vmmCreateVolume
|
||||
from .createinterface import vmmCreateInterface
|
||||
from .baseclass import vmmGObjectUI
|
||||
from .createnet import vmmCreateNetwork
|
||||
from .createinterface import vmmCreateInterface
|
||||
from .graphwidgets import Sparkline
|
||||
from .storagelist import vmmStorageList
|
||||
|
||||
INTERFACE_PAGE_INFO = 0
|
||||
INTERFACE_PAGE_ERROR = 1
|
||||
@@ -46,11 +42,6 @@ EDIT_NET_AUTOSTART,
|
||||
EDIT_NET_QOS,
|
||||
) = range(3)
|
||||
|
||||
EDIT_POOL_IDS = (
|
||||
EDIT_POOL_NAME,
|
||||
EDIT_POOL_AUTOSTART,
|
||||
) = range(100, 102)
|
||||
|
||||
EDIT_INTERFACE_IDS = (
|
||||
EDIT_INTERFACE_STARTMODE,
|
||||
) = range(200, 201)
|
||||
@@ -76,11 +67,7 @@ class vmmHost(vmmGObjectUI):
|
||||
self.ICON_SHUTOFF = "state_shutoff"
|
||||
|
||||
self.addnet = None
|
||||
self.addpool = None
|
||||
self.addvol = None
|
||||
self.addinterface = None
|
||||
self.volmenu = None
|
||||
self._in_refresh = False
|
||||
|
||||
self.active_edits = []
|
||||
|
||||
@@ -88,8 +75,9 @@ class vmmHost(vmmGObjectUI):
|
||||
self.memory_usage_graph = None
|
||||
self.init_conn_state()
|
||||
|
||||
self.init_net_state()
|
||||
self.storagelist = None
|
||||
self.init_storage_state()
|
||||
self.init_net_state()
|
||||
self.init_interface_state()
|
||||
|
||||
self.builder.connect_signals({
|
||||
@@ -111,20 +99,6 @@ class vmmHost(vmmGObjectUI):
|
||||
"on_net_name_changed": (lambda *x:
|
||||
self.enable_net_apply(x, EDIT_NET_NAME)),
|
||||
|
||||
"on_pool_add_clicked" : self.add_pool,
|
||||
"on_vol_add_clicked" : self.add_vol,
|
||||
"on_pool_stop_clicked": self.stop_pool,
|
||||
"on_pool_start_clicked": self.start_pool,
|
||||
"on_pool_delete_clicked": self.delete_pool,
|
||||
"on_pool_refresh_clicked": self.pool_refresh,
|
||||
"on_pool_autostart_toggled": self.pool_autostart_changed,
|
||||
"on_vol_delete_clicked": self.delete_vol,
|
||||
"on_vol_list_button_press_event": self.popup_vol_menu,
|
||||
"on_pool_apply_clicked": (lambda *x: self.pool_apply()),
|
||||
"on_vol_list_changed": self.vol_selected,
|
||||
"on_pool_name_changed": (lambda *x:
|
||||
self.enable_pool_apply(x, EDIT_POOL_NAME)),
|
||||
|
||||
"on_interface_add_clicked" : self.add_interface,
|
||||
"on_interface_start_clicked" : self.start_interface,
|
||||
"on_interface_stop_clicked" : self.stop_interface,
|
||||
@@ -153,7 +127,6 @@ class vmmHost(vmmGObjectUI):
|
||||
})
|
||||
|
||||
self.repopulate_networks()
|
||||
self.repopulate_storage_pools()
|
||||
self.repopulate_interfaces()
|
||||
|
||||
self.conn.connect("net-added", self.repopulate_networks)
|
||||
@@ -161,11 +134,6 @@ class vmmHost(vmmGObjectUI):
|
||||
self.conn.connect("net-started", self.refresh_network)
|
||||
self.conn.connect("net-stopped", self.refresh_network)
|
||||
|
||||
self.conn.connect("pool-added", self.repopulate_storage_pools)
|
||||
self.conn.connect("pool-removed", self.repopulate_storage_pools)
|
||||
self.conn.connect("pool-started", self.refresh_storage_pool)
|
||||
self.conn.connect("pool-stopped", self.refresh_storage_pool)
|
||||
|
||||
self.conn.connect("interface-added", self.repopulate_interfaces)
|
||||
self.conn.connect("interface-removed", self.repopulate_interfaces)
|
||||
self.conn.connect("interface-started", self.refresh_interface)
|
||||
@@ -173,7 +141,11 @@ class vmmHost(vmmGObjectUI):
|
||||
|
||||
self.conn.connect("state-changed", self.conn_state_changed)
|
||||
self.conn.connect("resources-sampled", self.refresh_resources)
|
||||
self.reset_state()
|
||||
|
||||
self.refresh_resources()
|
||||
self.conn_state_changed()
|
||||
self.widget("config-autoconnect").set_active(
|
||||
self.conn.get_autoconnect())
|
||||
|
||||
|
||||
def init_net_state(self):
|
||||
@@ -200,51 +172,9 @@ class vmmHost(vmmGObjectUI):
|
||||
netListModel.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
||||
|
||||
def init_storage_state(self):
|
||||
self.widget("storage-pages").set_show_tabs(False)
|
||||
self.storagelist = vmmStorageList(self.conn, self.builder, self.topwin)
|
||||
self.widget("storage-align").add(self.storagelist.top_box)
|
||||
|
||||
self.volmenu = Gtk.Menu()
|
||||
volCopyPath = Gtk.ImageMenuItem.new_with_label(_("Copy Volume Path"))
|
||||
volCopyImage = Gtk.Image()
|
||||
volCopyImage.set_from_stock(Gtk.STOCK_COPY, Gtk.IconSize.MENU)
|
||||
volCopyPath.set_image(volCopyImage)
|
||||
volCopyPath.show()
|
||||
volCopyPath.connect("activate", self.copy_vol_path)
|
||||
self.volmenu.add(volCopyPath)
|
||||
|
||||
volListModel = Gtk.ListStore(str, str, str, str, str)
|
||||
self.widget("vol-list").set_model(volListModel)
|
||||
|
||||
volCol = Gtk.TreeViewColumn("Volumes")
|
||||
vol_txt1 = Gtk.CellRendererText()
|
||||
volCol.pack_start(vol_txt1, True)
|
||||
volCol.add_attribute(vol_txt1, 'text', 1)
|
||||
volCol.set_sort_column_id(1)
|
||||
self.widget("vol-list").append_column(volCol)
|
||||
|
||||
volSizeCol = Gtk.TreeViewColumn("Size")
|
||||
vol_txt2 = Gtk.CellRendererText()
|
||||
volSizeCol.pack_start(vol_txt2, False)
|
||||
volSizeCol.add_attribute(vol_txt2, 'text', 2)
|
||||
volSizeCol.set_sort_column_id(2)
|
||||
self.widget("vol-list").append_column(volSizeCol)
|
||||
|
||||
volFormatCol = Gtk.TreeViewColumn("Format")
|
||||
vol_txt3 = Gtk.CellRendererText()
|
||||
volFormatCol.pack_start(vol_txt3, False)
|
||||
volFormatCol.add_attribute(vol_txt3, 'text', 3)
|
||||
volFormatCol.set_sort_column_id(3)
|
||||
self.widget("vol-list").append_column(volFormatCol)
|
||||
|
||||
volUseCol = Gtk.TreeViewColumn("Used By")
|
||||
vol_txt4 = Gtk.CellRendererText()
|
||||
volUseCol.pack_start(vol_txt4, False)
|
||||
volUseCol.add_attribute(vol_txt4, 'text', 4)
|
||||
volUseCol.set_sort_column_id(4)
|
||||
self.widget("vol-list").append_column(volUseCol)
|
||||
|
||||
volListModel.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
||||
|
||||
self.init_pool_list()
|
||||
|
||||
def init_interface_state(self):
|
||||
self.widget("interface-pages").set_show_tabs(False)
|
||||
@@ -346,25 +276,17 @@ class vmmHost(vmmGObjectUI):
|
||||
def _cleanup(self):
|
||||
self.conn = None
|
||||
|
||||
self.storagelist.cleanup()
|
||||
self.storagelist = None
|
||||
|
||||
if self.addnet:
|
||||
self.addnet.cleanup()
|
||||
self.addnet = None
|
||||
|
||||
if self.addpool:
|
||||
self.addpool.cleanup()
|
||||
self.addpool = None
|
||||
|
||||
if self.addvol:
|
||||
self.addvol.cleanup()
|
||||
self.addvol = None
|
||||
|
||||
if self.addinterface:
|
||||
self.addinterface.cleanup()
|
||||
self.addinterface = None
|
||||
|
||||
self.volmenu.destroy()
|
||||
self.volmenu = None
|
||||
|
||||
self.cpu_usage_graph.destroy()
|
||||
self.cpu_usage_graph = None
|
||||
|
||||
@@ -380,13 +302,6 @@ class vmmHost(vmmGObjectUI):
|
||||
def exit_app(self, src_ignore):
|
||||
self.emit("action-exit-app")
|
||||
|
||||
def reset_state(self):
|
||||
self.refresh_resources()
|
||||
self.conn_state_changed()
|
||||
|
||||
# Update autostart value
|
||||
auto = self.conn.get_autoconnect()
|
||||
self.widget("config-autoconnect").set_active(auto)
|
||||
|
||||
def page_changed(self, src, child, pagenum):
|
||||
ignore = src
|
||||
@@ -396,8 +311,7 @@ class vmmHost(vmmGObjectUI):
|
||||
self.repopulate_networks()
|
||||
self.conn.schedule_priority_tick(pollnet=True)
|
||||
elif pagenum == 2:
|
||||
self.repopulate_storage_volumes()
|
||||
self.conn.schedule_priority_tick(pollpool=True)
|
||||
self.storagelist.refresh_page()
|
||||
elif pagenum == 3:
|
||||
self.repopulate_interfaces()
|
||||
self.conn.schedule_priority_tick(polliface=True)
|
||||
@@ -425,18 +339,14 @@ class vmmHost(vmmGObjectUI):
|
||||
self.widget("menu_file_restore_saved").set_sensitive(conn_active)
|
||||
self.widget("net-add").set_sensitive(conn_active and
|
||||
self.conn.is_network_capable())
|
||||
self.widget("pool-add").set_sensitive(conn_active and
|
||||
self.conn.is_storage_capable())
|
||||
self.widget("interface-add").set_sensitive(conn_active and
|
||||
self.conn.is_interface_capable())
|
||||
|
||||
if not conn_active:
|
||||
self.set_net_error_page(_("Connection not active."))
|
||||
self.set_storage_error_page(_("Connection not active."))
|
||||
self.set_interface_error_page(_("Connection not active."))
|
||||
|
||||
self.repopulate_networks()
|
||||
self.repopulate_storage_pools()
|
||||
self.repopulate_interfaces()
|
||||
return
|
||||
|
||||
@@ -445,10 +355,6 @@ class vmmHost(vmmGObjectUI):
|
||||
_("Libvirt connection does not support virtual network "
|
||||
"management."))
|
||||
|
||||
if not self.conn.is_storage_capable():
|
||||
self.set_storage_error_page(
|
||||
_("Libvirt connection does not support storage management."))
|
||||
|
||||
if not self.conn.is_interface_capable():
|
||||
self.set_interface_error_page(
|
||||
_("Libvirt connection does not support interface management."))
|
||||
@@ -800,313 +706,6 @@ class vmmHost(vmmGObjectUI):
|
||||
curnet and curnet.get_connkey() or None)
|
||||
|
||||
|
||||
# ------------------------------
|
||||
# Storage Manager methods
|
||||
# ------------------------------
|
||||
|
||||
|
||||
def stop_pool(self, src_ignore):
|
||||
pool = self.current_pool()
|
||||
if pool is None:
|
||||
return
|
||||
|
||||
logging.debug("Stopping pool '%s'", pool.get_name())
|
||||
vmmAsyncJob.simple_async_noshow(pool.stop, [], self,
|
||||
_("Error stopping pool '%s'") % pool.get_name())
|
||||
|
||||
def start_pool(self, src_ignore):
|
||||
pool = self.current_pool()
|
||||
if pool is None:
|
||||
return
|
||||
|
||||
logging.debug("Starting pool '%s'", pool.get_name())
|
||||
vmmAsyncJob.simple_async_noshow(pool.start, [], self,
|
||||
_("Error starting pool '%s'") % pool.get_name())
|
||||
|
||||
def delete_pool(self, src_ignore):
|
||||
pool = self.current_pool()
|
||||
if pool is None:
|
||||
return
|
||||
|
||||
result = self.err.yes_no(_("Are you sure you want to permanently "
|
||||
"delete the pool %s?") % pool.get_name())
|
||||
if not result:
|
||||
return
|
||||
|
||||
logging.debug("Deleting pool '%s'", pool.get_name())
|
||||
vmmAsyncJob.simple_async_noshow(pool.delete, [], self,
|
||||
_("Error deleting pool '%s'") % pool.get_name())
|
||||
|
||||
def pool_refresh(self, src_ignore):
|
||||
if self._in_refresh:
|
||||
logging.debug("Already refreshing the pool, skipping")
|
||||
return
|
||||
|
||||
if not self.confirm_changes():
|
||||
return
|
||||
|
||||
pool = self.current_pool()
|
||||
if pool is None:
|
||||
return
|
||||
|
||||
self._in_refresh = True
|
||||
|
||||
def cb():
|
||||
try:
|
||||
pool.refresh()
|
||||
self.idle_add(self.refresh_current_pool)
|
||||
finally:
|
||||
self._in_refresh = False
|
||||
|
||||
logging.debug("Refresh pool '%s'", pool.get_name())
|
||||
vmmAsyncJob.simple_async_noshow(cb, [], self,
|
||||
_("Error refreshing pool '%s'") % pool.get_name())
|
||||
|
||||
def delete_vol(self, src_ignore):
|
||||
vol = self.current_vol()
|
||||
if vol is None:
|
||||
return
|
||||
|
||||
result = self.err.yes_no(_("Are you sure you want to permanently "
|
||||
"delete the volume %s?") % vol.get_name())
|
||||
if not result:
|
||||
return
|
||||
|
||||
def cb():
|
||||
vol.delete()
|
||||
def idlecb():
|
||||
self.refresh_current_pool()
|
||||
self.repopulate_storage_volumes()
|
||||
self.idle_add(idlecb)
|
||||
|
||||
logging.debug("Deleting volume '%s'", vol.get_name())
|
||||
vmmAsyncJob.simple_async_noshow(cb, [], self,
|
||||
_("Error refreshing volume '%s'") % vol.get_name())
|
||||
|
||||
def add_pool(self, src_ignore):
|
||||
logging.debug("Launching 'Add Pool' wizard")
|
||||
try:
|
||||
if self.addpool is None:
|
||||
self.addpool = vmmCreatePool(self.conn)
|
||||
self.addpool.show(self.topwin)
|
||||
except Exception, e:
|
||||
self.err.show_err(_("Error launching pool wizard: %s") % str(e))
|
||||
|
||||
def add_vol(self, src_ignore):
|
||||
pool = self.current_pool()
|
||||
if pool is None:
|
||||
return
|
||||
|
||||
logging.debug("Launching 'Add Volume' wizard for pool '%s'",
|
||||
pool.get_name())
|
||||
try:
|
||||
if self.addvol is None:
|
||||
self.addvol = vmmCreateVolume(self.conn, pool)
|
||||
self.addvol.connect("vol-created", self.refresh_current_pool)
|
||||
else:
|
||||
self.addvol.set_parent_pool(self.conn, pool)
|
||||
self.addvol.show(self.topwin)
|
||||
except Exception, e:
|
||||
self.err.show_err(_("Error launching volume wizard: %s") % str(e))
|
||||
|
||||
def refresh_current_pool(self, ignore1=None):
|
||||
cp = self.current_pool()
|
||||
if cp is None:
|
||||
return
|
||||
cp.refresh()
|
||||
self.refresh_storage_pool(None, cp.get_connkey())
|
||||
|
||||
def current_pool(self):
|
||||
connkey = uiutil.get_list_selection(self.widget("pool-list"), 0)
|
||||
try:
|
||||
return connkey and self.conn.get_pool(connkey)
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def current_vol(self):
|
||||
pool = self.current_pool()
|
||||
if not pool:
|
||||
return None
|
||||
|
||||
connkey = uiutil.get_list_selection(self.widget("vol-list"), 0)
|
||||
try:
|
||||
return connkey and pool.get_volume(connkey)
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def pool_apply(self):
|
||||
pool = self.current_pool()
|
||||
if pool is None:
|
||||
return
|
||||
|
||||
logging.debug("Applying changes for pool '%s'", pool.get_name())
|
||||
try:
|
||||
if EDIT_POOL_AUTOSTART in self.active_edits:
|
||||
auto = self.widget("pool-autostart").get_active()
|
||||
pool.set_autostart(auto)
|
||||
if EDIT_POOL_NAME in self.active_edits:
|
||||
pool.define_name(self.widget("pool-name-entry").get_text())
|
||||
self.idle_add(self.repopulate_storage_pools)
|
||||
except Exception, e:
|
||||
self.err.show_err(_("Error changing pool settings: %s") % str(e))
|
||||
return
|
||||
|
||||
self.disable_pool_apply()
|
||||
|
||||
def disable_pool_apply(self):
|
||||
for i in EDIT_POOL_IDS:
|
||||
if i in self.active_edits:
|
||||
self.active_edits.remove(i)
|
||||
|
||||
self.widget("pool-apply").set_sensitive(False)
|
||||
|
||||
def enable_pool_apply(self, *arglist):
|
||||
edittype = arglist[-1]
|
||||
self.widget("pool-apply").set_sensitive(True)
|
||||
if edittype not in self.active_edits:
|
||||
self.active_edits.append(edittype)
|
||||
|
||||
def pool_autostart_changed(self, src_ignore):
|
||||
auto = self.widget("pool-autostart").get_active()
|
||||
self.widget("pool-autostart").set_label(auto and
|
||||
_("On Boot") or
|
||||
_("Never"))
|
||||
self.enable_pool_apply(EDIT_POOL_AUTOSTART)
|
||||
|
||||
def set_storage_error_page(self, msg):
|
||||
self.reset_pool_state()
|
||||
self.widget("storage-pages").set_current_page(1)
|
||||
self.widget("storage-error-label").set_text(msg)
|
||||
|
||||
def pool_selected(self, src):
|
||||
model, treeiter = src.get_selected()
|
||||
if treeiter is None:
|
||||
self.set_storage_error_page(_("No storage pool selected."))
|
||||
return
|
||||
|
||||
self.widget("storage-pages").set_current_page(0)
|
||||
connkey = model[treeiter][0]
|
||||
|
||||
try:
|
||||
self.populate_pool_state(connkey)
|
||||
except Exception, e:
|
||||
logging.exception(e)
|
||||
self.set_storage_error_page(_("Error selecting pool: %s") % e)
|
||||
self.disable_pool_apply()
|
||||
|
||||
def populate_pool_state(self, connkey):
|
||||
pool = self.conn.get_pool(connkey)
|
||||
pool.tick()
|
||||
auto = pool.get_autostart()
|
||||
active = pool.is_active()
|
||||
|
||||
# Set pool details state
|
||||
self.widget("pool-details").set_sensitive(True)
|
||||
self.widget("pool-name").set_markup("<b>%s:</b>" %
|
||||
pool.get_name())
|
||||
self.widget("pool-name-entry").set_text(pool.get_name())
|
||||
self.widget("pool-name-entry").set_editable(not active)
|
||||
self.widget("pool-sizes").set_markup(
|
||||
"""<span size="large">%s Free</span> / <i>%s In Use</i>""" %
|
||||
(pool.get_pretty_available(), pool.get_pretty_allocation()))
|
||||
self.widget("pool-type").set_text(
|
||||
StoragePool.get_pool_type_desc(pool.get_type()))
|
||||
self.widget("pool-location").set_text(
|
||||
pool.get_target_path())
|
||||
self.widget("pool-state-icon").set_from_icon_name(
|
||||
((active and self.ICON_RUNNING) or self.ICON_SHUTOFF),
|
||||
Gtk.IconSize.BUTTON)
|
||||
self.widget("pool-state").set_text(
|
||||
(active and _("Active")) or _("Inactive"))
|
||||
self.widget("pool-autostart").set_label(
|
||||
(auto and _("On Boot")) or _("Never"))
|
||||
self.widget("pool-autostart").set_active(auto)
|
||||
|
||||
self.widget("vol-list").set_sensitive(active)
|
||||
self.repopulate_storage_volumes()
|
||||
|
||||
self.widget("pool-delete").set_sensitive(not active)
|
||||
self.widget("pool-stop").set_sensitive(active)
|
||||
self.widget("pool-start").set_sensitive(not active)
|
||||
self.widget("vol-add").set_sensitive(active)
|
||||
self.widget("vol-add").set_tooltip_text(_("Create new volume"))
|
||||
self.widget("vol-delete").set_sensitive(False)
|
||||
|
||||
if active and not pool.supports_volume_creation():
|
||||
self.widget("vol-add").set_sensitive(False)
|
||||
self.widget("vol-add").set_tooltip_text(
|
||||
_("Pool does not support volume creation"))
|
||||
|
||||
def refresh_storage_pool(self, src, connkey):
|
||||
ignore = src
|
||||
refresh_pool_in_list(self.widget("pool-list"), self.conn, connkey)
|
||||
curpool = self.current_pool()
|
||||
if curpool.get_connkey() != connkey:
|
||||
return
|
||||
|
||||
# Currently selected pool changed state: force a 'pool_selected' to
|
||||
# update vol list
|
||||
self.pool_selected(self.widget("pool-list").get_selection())
|
||||
|
||||
def reset_pool_state(self):
|
||||
self.widget("pool-details").set_sensitive(False)
|
||||
self.widget("pool-name").set_text("")
|
||||
self.widget("pool-name-entry").set_text("")
|
||||
self.widget("pool-sizes").set_markup("""<span size="large"> </span>""")
|
||||
self.widget("pool-type").set_text("")
|
||||
self.widget("pool-location").set_text("")
|
||||
self.widget("pool-state-icon").set_from_icon_name(self.ICON_SHUTOFF,
|
||||
Gtk.IconSize.BUTTON)
|
||||
self.widget("pool-state").set_text(_("Inactive"))
|
||||
self.widget("vol-list").get_model().clear()
|
||||
self.widget("pool-autostart").set_label(_("Never"))
|
||||
self.widget("pool-autostart").set_active(False)
|
||||
|
||||
self.widget("pool-delete").set_sensitive(False)
|
||||
self.widget("pool-stop").set_sensitive(False)
|
||||
self.widget("pool-start").set_sensitive(False)
|
||||
self.widget("vol-add").set_sensitive(False)
|
||||
self.widget("vol-delete").set_sensitive(False)
|
||||
self.widget("vol-list").set_sensitive(False)
|
||||
self.disable_pool_apply()
|
||||
|
||||
def vol_selected(self, src):
|
||||
model, treeiter = src.get_selected()
|
||||
ignore = model
|
||||
if treeiter is None:
|
||||
self.widget("vol-delete").set_sensitive(False)
|
||||
return
|
||||
|
||||
self.widget("vol-delete").set_sensitive(True)
|
||||
|
||||
def popup_vol_menu(self, widget_ignore, event):
|
||||
if event.button != 3:
|
||||
return
|
||||
|
||||
self.volmenu.popup(None, None, None, None, 0, event.time)
|
||||
|
||||
def copy_vol_path(self, ignore=None):
|
||||
vol = self.current_vol()
|
||||
if not vol:
|
||||
return
|
||||
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
|
||||
target_path = vol.get_target_path()
|
||||
if target_path:
|
||||
clipboard.set_text(target_path, -1)
|
||||
|
||||
|
||||
def repopulate_storage_pools(self, src=None, connkey=None):
|
||||
ignore = src
|
||||
ignore = connkey
|
||||
pool_list = self.widget("pool-list")
|
||||
populate_storage_pools(pool_list, self.conn, self.current_pool())
|
||||
|
||||
def repopulate_storage_volumes(self):
|
||||
list_widget = self.widget("vol-list")
|
||||
pool = self.current_pool()
|
||||
populate_storage_volumes(list_widget, pool, None)
|
||||
|
||||
|
||||
#############################
|
||||
# Interface manager methods #
|
||||
#############################
|
||||
@@ -1382,9 +981,7 @@ class vmmHost(vmmGObjectUI):
|
||||
chktext=_("Don't warn me again."),
|
||||
default=False):
|
||||
|
||||
if all([edit in EDIT_POOL_IDS for edit in self.active_edits]):
|
||||
self.pool_apply()
|
||||
elif all([edit in EDIT_NET_IDS for edit in self.active_edits]):
|
||||
if all([edit in EDIT_NET_IDS for edit in self.active_edits]):
|
||||
self.net_apply()
|
||||
elif all([edit in EDIT_INTERFACE_IDS
|
||||
for edit in self.active_edits]):
|
||||
@@ -1392,113 +989,3 @@ class vmmHost(vmmGObjectUI):
|
||||
|
||||
self.active_edits = []
|
||||
return True
|
||||
|
||||
def init_pool_list(self):
|
||||
pool_list = self.widget("pool-list")
|
||||
init_pool_list(pool_list, self.pool_selected)
|
||||
|
||||
sel = pool_list.get_selection()
|
||||
sel.set_select_function((lambda *x: self.confirm_changes()),
|
||||
None)
|
||||
|
||||
|
||||
# These functions are broken out, since they are used by storage browser
|
||||
# dialog.
|
||||
|
||||
def init_pool_list(pool_list, changed_func):
|
||||
poolListModel = Gtk.ListStore(str, str, bool, str)
|
||||
pool_list.set_model(poolListModel)
|
||||
|
||||
pool_list.get_selection().connect("changed", changed_func)
|
||||
|
||||
poolCol = Gtk.TreeViewColumn("Storage Pools")
|
||||
pool_txt = Gtk.CellRendererText()
|
||||
pool_per = Gtk.CellRendererText()
|
||||
poolCol.pack_start(pool_per, False)
|
||||
poolCol.pack_start(pool_txt, True)
|
||||
poolCol.add_attribute(pool_txt, 'markup', 1)
|
||||
poolCol.add_attribute(pool_txt, 'sensitive', 2)
|
||||
poolCol.add_attribute(pool_per, 'markup', 3)
|
||||
pool_list.append_column(poolCol)
|
||||
poolListModel.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
||||
|
||||
|
||||
def refresh_pool_in_list(pool_list, conn, connkey):
|
||||
for row in pool_list.get_model():
|
||||
if row[0] != connkey:
|
||||
continue
|
||||
|
||||
# Update active sensitivity and percent available for passed key
|
||||
row[3] = get_pool_size_percent(conn, connkey)
|
||||
row[2] = conn.get_pool(connkey).is_active()
|
||||
return
|
||||
|
||||
|
||||
def populate_storage_pools(pool_list, conn, curpool):
|
||||
model = pool_list.get_model()
|
||||
# Prevent events while the model is modified
|
||||
pool_list.set_model(None)
|
||||
pool_list.get_selection().unselect_all()
|
||||
model.clear()
|
||||
for pool in conn.list_pools():
|
||||
connkey = pool.get_connkey()
|
||||
per = get_pool_size_percent(conn, connkey)
|
||||
pool = conn.get_pool(connkey)
|
||||
|
||||
name = pool.get_name()
|
||||
typ = StoragePool.get_pool_type_desc(pool.get_type())
|
||||
label = "%s\n<span size='small'>%s</span>" % (name, typ)
|
||||
|
||||
model.append([connkey, label, pool.is_active(), per])
|
||||
|
||||
pool_list.set_model(model)
|
||||
uiutil.set_row_selection(pool_list,
|
||||
curpool and curpool.get_connkey() or None)
|
||||
|
||||
|
||||
def populate_storage_volumes(list_widget, pool, sensitive_cb):
|
||||
vols = pool and pool.get_volumes() or {}
|
||||
model = list_widget.get_model()
|
||||
list_widget.get_selection().unselect_all()
|
||||
model.clear()
|
||||
|
||||
for key in vols.keys():
|
||||
vol = vols[key]
|
||||
|
||||
try:
|
||||
path = vol.get_target_path()
|
||||
name = vol.get_pretty_name(pool.get_type())
|
||||
cap = vol.get_pretty_capacity()
|
||||
fmt = vol.get_format() or ""
|
||||
except:
|
||||
logging.debug("Error getting volume info for '%s', "
|
||||
"hiding it", key, exc_info=True)
|
||||
continue
|
||||
|
||||
namestr = None
|
||||
try:
|
||||
if path:
|
||||
names = VirtualDisk.path_in_use_by(vol.conn.get_backend(),
|
||||
path)
|
||||
namestr = ", ".join(names)
|
||||
if not namestr:
|
||||
namestr = None
|
||||
except:
|
||||
logging.exception("Failed to determine if storage volume in "
|
||||
"use.")
|
||||
|
||||
row = [key, name, cap, fmt, namestr]
|
||||
if sensitive_cb:
|
||||
row.append(sensitive_cb(fmt))
|
||||
model.append(row)
|
||||
|
||||
|
||||
def get_pool_size_percent(conn, connkey):
|
||||
pool = conn.get_pool(connkey)
|
||||
cap = pool.get_capacity()
|
||||
alloc = pool.get_allocation()
|
||||
if not cap or alloc is None:
|
||||
per = 0
|
||||
else:
|
||||
per = int(((float(alloc) / float(cap)) * 100))
|
||||
return "<span size='small' color='#484848'>%s%%</span>" % int(per)
|
||||
|
||||
Reference in New Issue
Block a user