# Copyright (C) 2006-2007, 2013, 2014 Red Hat, Inc. # Copyright (C) 2006 Hugh O. Brock # Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. # # This work is licensed under the GNU GPLv2 or later. # See the COPYING file in the top-level directory. from gi.repository import Gtk from virtinst import DeviceFilesystem from virtinst import xmlutil from ..lib import uiutil from ..baseclass import vmmGObjectUI from ..storagebrowse import vmmStorageBrowser _EDIT_FS_ENUM = range(1, 8) ( _EDIT_FS_TYPE, _EDIT_FS_DRIVER, _EDIT_FS_SOURCE, _EDIT_FS_RAM_SOURCE, _EDIT_FS_READONLY, _EDIT_FS_TARGET, _EDIT_FS_FORMAT, ) = _EDIT_FS_ENUM class vmmFSDetails(vmmGObjectUI): __gsignals__ = { "changed": (vmmGObjectUI.RUN_FIRST, None, []) } def __init__(self, vm, builder, topwin): vmmGObjectUI.__init__(self, "fsdetails.ui", None, builder=builder, topwin=topwin) self.vm = vm self.conn = vm.conn self._storage_browser = None self._active_edits = [] def _e(edittype): def signal_cb(*args): self._change_cb(edittype) return signal_cb self.builder.connect_signals({ "on_fs_source_browse_clicked": self._browse_fs_source_cb, "on_fs_type_combo_changed": _e(_EDIT_FS_TYPE), "on_fs_driver_combo_changed": _e(_EDIT_FS_DRIVER), "on_fs_readonly_toggled": _e(_EDIT_FS_READONLY), "on_fs_format_combo_changed": _e(_EDIT_FS_FORMAT), "on_fs_source_changed": _e(_EDIT_FS_SOURCE), "on_fs_ram_source_changed": _e(_EDIT_FS_RAM_SOURCE), "on_fs_target_changed": _e(_EDIT_FS_TARGET), }) self._init_ui() self.top_box = self.widget("vmm-fs-details") def _cleanup(self): self.vm = None self.conn = None if self._storage_browser: self._storage_browser.cleanup() self._storage_browser = None ########################## # Initialization methods # ########################## def _init_ui(self): def simple_store_set(comboname, values): combo = self.widget(comboname) # [XML value, label] model = Gtk.ListStore(str, str) combo.set_model(model) uiutil.init_combo_text_column(combo, 1) for xmlval in values: label = xmlval if xmlval is None: label = _("Hypervisor default") model.append([xmlval, label]) # Filesystem widgets if self.conn.is_container_only(): simple_store_set("fs-type-combo", [DeviceFilesystem.TYPE_MOUNT, DeviceFilesystem.TYPE_FILE, DeviceFilesystem.TYPE_BLOCK, DeviceFilesystem.TYPE_RAM]) else: simple_store_set("fs-type-combo", [DeviceFilesystem.TYPE_MOUNT]) if self.conn.is_container_only(): simple_store_set("fs-driver-combo", [DeviceFilesystem.DRIVER_LOOP, DeviceFilesystem.DRIVER_NBD, None]) else: domcaps = self.vm.get_domain_capabilities() rows = [] if domcaps.supports_filesystem_virtiofs(): rows.append(["virtiofs", "virtiofs"]) rows.append([None, "virtio-9p"]) uiutil.build_simple_combo( self.widget("fs-driver-combo"), rows, sort=False) simple_store_set("fs-format-combo", ["raw", "qcow2"]) self.widget("fs-readonly").set_visible( self.conn.is_qemu() or self.conn.is_test() or self.conn.is_lxc()) ############## # UI syncing # ############## def _sync_ui(self): fstype = uiutil.get_list_selection(self.widget("fs-type-combo")) fsdriver = uiutil.get_list_selection(self.widget("fs-driver-combo")) is_qemu = self.conn.is_qemu() or self.conn.is_test() show_ram_source = fstype == DeviceFilesystem.TYPE_RAM uiutil.set_grid_row_visible( self.widget("fs-ram-source-box"), show_ram_source) uiutil.set_grid_row_visible( self.widget("fs-source-box"), not show_ram_source) show_format = bool( fsdriver == DeviceFilesystem.DRIVER_NBD) uiutil.set_grid_row_visible( self.widget("fs-format-combo"), show_format) show_driver_combo = is_qemu or fstype == DeviceFilesystem.TYPE_FILE if fstype == DeviceFilesystem.TYPE_TEMPLATE: source_text = _("Te_mplate:") else: source_text = _("_Source path:") self.widget("fs-source-title").set_text(source_text) self.widget("fs-source-title").set_use_underline(True) uiutil.set_grid_row_visible( self.widget("fs-type-combo"), not is_qemu) uiutil.set_grid_row_visible( self.widget("fs-driver-combo"), show_driver_combo) need_shared_mem = fsdriver == "virtiofs" have_shared_mem, _shared_mem_err = self.vm.has_shared_mem() show_shared_mem_warn = need_shared_mem and not have_shared_mem uiutil.set_grid_row_visible( self.widget("fs-driver-warn-box"), show_shared_mem_warn) if show_shared_mem_warn: label = _( "You may need to 'Enable shared memory' on the 'Memory' screen.") self.widget("fs-driver-warn").set_markup( "%s" % xmlutil.xml_escape(label)) ############## # Public API # ############## def reset_state(self): self.widget("fs-type-combo").set_active(0) self.widget("fs-driver-combo").set_active(0) self.widget("fs-format-combo").set_active(0) self.widget("fs-source").set_text("") self.widget("fs-target").set_text("") self.widget("fs-readonly").set_active(False) self._sync_ui() self._active_edits = [] def set_dev(self, dev): self.reset_state() uiutil.set_list_selection( self.widget("fs-type-combo"), dev.type) uiutil.set_list_selection( self.widget("fs-driver-combo"), dev.driver_type) uiutil.set_list_selection( self.widget("fs-format-combo"), dev.driver_format) if dev.type != DeviceFilesystem.TYPE_RAM: self.widget("fs-source").set_text(dev.source or "") else: self.widget("fs-ram-source-spin").set_value(int(dev.source) // 1024) self.widget("fs-target").set_text(dev.target or "") self.widget("fs-readonly").set_active(dev.readonly) self._active_edits = [] ################### # Device building # ################### def _set_values(self, dev): fstype = uiutil.get_list_selection(self.widget("fs-type-combo")) usage = uiutil.spin_get_helper(self.widget("fs-ram-source-spin")) source = self.widget("fs-source").get_text() target = self.widget("fs-target").get_text() readonly = self.widget("fs-readonly").get_active() fsformat = uiutil.get_list_selection(self.widget("fs-format-combo")) if not self.widget("fs-format-combo").get_visible(): fsformat = None driver = uiutil.get_list_selection(self.widget("fs-driver-combo")) if not self.widget("fs-driver-combo").get_visible(): driver = None if _EDIT_FS_TYPE in self._active_edits: dev.type = fstype if (_EDIT_FS_RAM_SOURCE in self._active_edits or _EDIT_FS_SOURCE in self._active_edits): if fstype == DeviceFilesystem.TYPE_RAM: dev.source = usage dev.source_units = 'MiB' else: dev.source = source if _EDIT_FS_TARGET in self._active_edits: dev.target = target if _EDIT_FS_READONLY in self._active_edits: dev.readonly = readonly if _EDIT_FS_DRIVER in self._active_edits: origdriver = dev.driver_type dev.driver_type = driver if origdriver == "virtiofs" or driver == "virtiofs": # Need to reset the accessmode for virtiofs dev.accessmode = dev.default_accessmode() if _EDIT_FS_FORMAT in self._active_edits: dev.driver_format = fsformat def build_device(self): self._active_edits = _EDIT_FS_ENUM[:] conn = self.conn.get_backend() dev = DeviceFilesystem(conn) self._set_values(dev) dev.validate_target(dev.target) dev.validate() return dev def update_device(self, dev): newdev = DeviceFilesystem(dev.conn, parsexml=dev.get_xml()) self._set_values(newdev) return newdev #################### # Internal helpers # #################### def _browse_file(self, textent, isdir=False): def set_storage_cb(src, path): if path: textent.set_text(path) reason = (isdir and vmmStorageBrowser.REASON_FS or vmmStorageBrowser.REASON_IMAGE) if self._storage_browser is None: self._storage_browser = vmmStorageBrowser(self.conn) self._storage_browser.set_finish_cb(set_storage_cb) self._storage_browser.set_browse_reason(reason) self._storage_browser.show(self.topwin.get_ancestor(Gtk.Window)) ############# # Listeners # ############# def _change_cb(self, edittype): self._sync_ui() if edittype not in self._active_edits: self._active_edits.append(edittype) self.emit("changed") def _browse_fs_source_cb(self, src): self._browse_file(self.widget("fs-source"), isdir=True)