diff options
author | Cole Robinson <crobinso@redhat.com> | 2019-06-16 21:45:19 -0400 |
---|---|---|
committer | Cole Robinson <crobinso@redhat.com> | 2019-06-17 00:12:32 -0400 |
commit | 9be836102e745cd3824cd89af1bc30278913b6d7 (patch) | |
tree | 16ba169ce22651791a7d4051fdf27e93eead9088 /virtManager/device/addstorage.py | |
parent | a6c07fbfdc8d49107d9b7089ee7056980a5372a1 (diff) | |
download | virt-manager-9be836102e745cd3824cd89af1bc30278913b6d7.tar.gz |
virtManager: move device UI files to virtManager/device/
Diffstat (limited to 'virtManager/device/addstorage.py')
-rw-r--r-- | virtManager/device/addstorage.py | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/virtManager/device/addstorage.py b/virtManager/device/addstorage.py new file mode 100644 index 00000000..03838b2c --- /dev/null +++ b/virtManager/device/addstorage.py @@ -0,0 +1,233 @@ +# Copyright (C) 2014 Red Hat, Inc. +# +# This work is licensed under the GNU GPLv2 or later. +# See the COPYING file in the top-level directory. + +import os + +from gi.repository import Gtk + +import virtinst +from virtinst import log + +from .. import uiutil +from ..baseclass import vmmGObjectUI + + +class vmmAddStorage(vmmGObjectUI): + __gsignals__ = { + "browse-clicked": (vmmGObjectUI.RUN_FIRST, None, [object]), + "storage-toggled": (vmmGObjectUI.RUN_FIRST, None, [object]) + } + + def __init__(self, conn, builder, topwin): + vmmGObjectUI.__init__(self, "addstorage.ui", None, + builder=builder, topwin=topwin) + self.conn = conn + + self.builder.connect_signals({ + "on_storage_browse_clicked": self._browse_storage, + "on_storage_select_toggled": self._toggle_storage_select, + }) + + self.top_box = self.widget("storage-box") + + def _cleanup(self): + self.conn = None + + + ########################## + # Initialization methods # + ########################## + + def _host_disk_space(self): + try: + pool = self.conn.get_default_pool() + if pool and pool.is_active(): + # Rate limit this, since it can be spammed at dialog startup time + if pool.secs_since_last_refresh() > 10: + pool.refresh() + avail = int(pool.get_available()) + return float(avail / 1024.0 / 1024.0 / 1024.0) + except Exception: + log.exception("Error determining host disk space") + return -1 + + def _update_host_space(self): + widget = self.widget("phys-hd-label") + max_storage = self._host_disk_space() + + def pretty_storage(size): + if size == -1: + return "Unknown GiB" + return "%.1f GiB" % float(size) + + hd_label = (_("%s available in the default location") % + pretty_storage(max_storage)) + hd_label = ("<span color='#484848'>%s</span>" % hd_label) + widget.set_markup(hd_label) + + + ############## + # Public API # + ############## + + @staticmethod + def check_path_search(src, conn, path): + skip_paths = src.config.get_perms_fix_ignore() + searchdata = virtinst.DeviceDisk.check_path_search( + conn.get_backend(), path) + + broken_paths = searchdata.fixlist[:] + for p in broken_paths[:]: + if p in skip_paths: + broken_paths.remove(p) + + if not broken_paths: + return + + log.debug("No search access for dirs: %s", broken_paths) + resp, chkres = src.err.warn_chkbox( + _("The emulator may not have search permissions " + "for the path '%s'.") % path, + _("Do you want to correct this now?"), + _("Don't ask about these directories again."), + buttons=Gtk.ButtonsType.YES_NO) + + if chkres: + src.config.add_perms_fix_ignore(broken_paths) + if not resp: + return + + log.debug("Attempting to correct permission issues.") + errors = virtinst.DeviceDisk.fix_path_search( + conn.get_backend(), searchdata) + if not errors: + return + + errmsg = _("Errors were encountered changing permissions for the " + "following directories:") + details = "" + for p, error in errors.items(): + if p not in broken_paths: + continue + details += "%s : %s\n" % (p, error) + details += "\nIt is very likely the VM will fail to start up." + + log.debug("Permission errors:\n%s", details) + + ignore, chkres = src.err.err_chkbox(errmsg, details, + _("Don't ask about these directories again.")) + + if chkres: + src.config.add_perms_fix_ignore(list(errors.keys())) + + def reset_state(self): + self._update_host_space() + self.widget("storage-create").set_active(True) + self.widget("storage-size").set_value(20) + self.widget("storage-entry").set_text("") + self.widget("storage-create-box").set_sensitive(True) + + storage_tooltip = None + + can_storage = (not self.conn.is_remote() or + self.conn.is_storage_capable()) + use_storage = self.widget("storage-select") + storage_area = self.widget("storage-box") + + storage_area.set_sensitive(can_storage) + if not can_storage: + storage_tooltip = _("Connection does not support storage" + " management.") + use_storage.set_sensitive(True) + storage_area.set_tooltip_text(storage_tooltip or "") + + def get_default_path(self, name, collideguest=None): + pool = self.conn.get_default_pool() + if not pool: + return + + fmt = self.conn.get_default_storage_format() + suffix = virtinst.StorageVolume.get_file_extension_for_format(fmt) + suffix = suffix or ".img" + + path = virtinst.StorageVolume.find_free_name( + self.conn.get_backend(), pool.get_backend(), name, + suffix=suffix, collideguest=collideguest) + + return os.path.join(pool.xmlobj.target_path, path) + + def is_default_storage(self): + return self.widget("storage-create").get_active() + + def build_device(self, vmname, + path=None, device="disk", collideguest=None): + if path is None: + if self.is_default_storage(): + path = self.get_default_path(vmname, collideguest=collideguest) + else: + path = self.widget("storage-entry").get_text().strip() + + disk = virtinst.DeviceDisk(self.conn.get_backend()) + disk.path = path or None + disk.device = device + + if disk.wants_storage_creation(): + pool = disk.get_parent_pool() + size = uiutil.spin_get_helper(self.widget("storage-size")) + sparse = False + + vol_install = virtinst.DeviceDisk.build_vol_install( + disk.conn, os.path.basename(disk.path), pool, + size, sparse) + disk.set_vol_install(vol_install) + + fmt = self.conn.get_default_storage_format() + if disk.get_vol_install().supports_property("format"): + log.debug("Using default prefs format=%s for path=%s", + fmt, disk.path) + disk.get_vol_install().format = fmt + else: + log.debug("path=%s can not use default prefs format=%s, " + "not setting it", disk.path, fmt) + + return disk + + def validate_device(self, disk): + if not disk.path and disk.device in ["disk", "lun"]: + return self.err.val_err(_("A storage path must be specified.")) + + disk.validate() + + isfatal, errmsg = disk.is_size_conflict() + if not isfatal and errmsg: + # Fatal errors are reported when setting 'size' + res = self.err.ok_cancel(_("Not Enough Free Space"), errmsg) + if not res: + return False + + # Disk collision + names = disk.is_conflict_disk() + if names: + res = self.err.yes_no( + _('Disk "%s" is already in use by other guests %s') % + (disk.path, names), + _("Do you really want to use the disk?")) + if not res: + return False + + self.check_path_search(self, self.conn, disk.path) + + + ############# + # Listeners # + ############# + + def _browse_storage(self, ignore): + self.emit("browse-clicked", self.widget("storage-entry")) + + def _toggle_storage_select(self, src): + act = src.get_active() + self.widget("storage-browse-box").set_sensitive(act) + self.emit("storage-toggled", src) |