From a8a375285f64c0e82e70b96d8487a2a8f8b770cb Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Sep 24 2009 15:47:35 +0000 Subject: Fix cdrom installs where the iso is a storage volume (bz 524109) Fix path permissions for kernel/initrd download location (bz 523960) --- diff --git a/virt-manager-0.8.0-fix-path-perms.patch b/virt-manager-0.8.0-fix-path-perms.patch new file mode 100644 index 0000000..38ebfa7 --- /dev/null +++ b/virt-manager-0.8.0-fix-path-perms.patch @@ -0,0 +1,349 @@ +# HG changeset patch +# User Cole Robinson +# Date 1253738576 14400 +# Node ID e7ee75a8f1353f2c42df93b5090b05fbdf89720a +# Parent 292a065aad7e4e5e5d50a71337efab2361378313 +Add dialog-with-checkbox helper functions. + +Useful for things like "Don't show this again'. + +diff -r 292a065aad7e -r e7ee75a8f135 src/virtManager/error.py +--- a/src/virtManager/error.py Wed Sep 23 11:49:35 2009 -0400 ++++ b/src/virtManager/error.py Wed Sep 23 16:42:56 2009 -0400 +@@ -131,3 +131,61 @@ + def ok_cancel(self, text1, text2=None): + return self._show_warning(gtk.BUTTONS_OK_CANCEL, text1, text2) + ++ def warn_chkbox(self, text1, text2=None, chktext=None): ++ chkbox = vmmCheckDialog(self.parent, gtk.MESSAGE_WARNING) ++ return chkbox.show_chkbox(text1, text2, chktext) ++ ++ def err_chkbox(self, text1, text2=None, chktext=None): ++ chkbox = vmmCheckDialog(self.parent, gtk.MESSAGE_ERROR) ++ return chkbox.show_chkbox(text1, text2, chktext) ++ ++class vmmCheckDialog (gtk.MessageDialog): ++ def __init__ (self, parent=None, typ=gtk.MESSAGE_INFO): ++ if typ == gtk.MESSAGE_WARNING: ++ buttons = gtk.BUTTONS_OK_CANCEL ++ else: ++ buttons = gtk.BUTTONS_OK ++ ++ gtk.MessageDialog.__init__ (self, parent, 0, typ, buttons) ++ ++ self.connect("response", self.response_cb) ++ self.connect("delete-event", self.hide_on_delete) ++ self.set_title("") ++ ++ self.chk_vbox = gtk.VBox(False, False) ++ self.chk_vbox.set_spacing(0) ++ ++ self.chk_align = gtk.Alignment() ++ self.chk_align.set_padding(0, 0, 62, 0) ++ self.chk_align.add(self.chk_vbox) ++ ++ self.chk_align.show_all() ++ self.vbox.pack_start(self.chk_align) ++ ++ def response_cb(self, src, ignore): ++ src.hide() ++ ++ def show_chkbox(self, text1, text2=None, chktext=None): ++ chkbox = None ++ res = None ++ chkres = None ++ ++ self.hide() ++ for c in self.chk_vbox.get_children(): ++ self.chk_vbox.remove(c) ++ ++ self.set_property("text", text1) ++ ++ if text2: ++ self.format_secondary_text(text2) ++ ++ if chktext: ++ chkbox = gtk.CheckButton(chktext) ++ self.chk_vbox.add(chkbox) ++ chkbox.show() ++ ++ res = self.run() in [ gtk.RESPONSE_YES, gtk.RESPONSE_OK ] ++ if chktext: ++ res = [res, chkbox.get_active()] ++ ++ return res +# HG changeset patch +# User Cole Robinson +# Date 1253738620 14400 +# Node ID f5f3ff4f8942d631234f8e008d806bd502c58bc3 +# Parent e7ee75a8f1353f2c42df93b5090b05fbdf89720a +connection: Add is_qemu_system helper. + +diff -r e7ee75a8f135 -r f5f3ff4f8942 src/virtManager/connection.py +--- a/src/virtManager/connection.py Wed Sep 23 16:42:56 2009 -0400 ++++ b/src/virtManager/connection.py Wed Sep 23 16:43:40 2009 -0400 +@@ -201,6 +201,13 @@ + def is_nodedev_capable(self): + return virtinst.NodeDeviceParser.is_nodedev_capable(self.vmm) + ++ def is_qemu_system(self): ++ (scheme, ignore, ignore, ++ path, ignore, ignore) = virtinst.util.uri_split(self.uri) ++ if path == "/system" and scheme.startswith("qemu"): ++ return True ++ return False ++ + def is_qemu_session(self): + (scheme, ignore, ignore, + path, ignore, ignore) = virtinst.util.uri_split(self.uri) +# HG changeset patch +# User Cole Robinson +# Date 1253806909 14400 +# Node ID cfcd19d057ddc973a129e7816cd4ea39f0d4365a +# Parent f5f3ff4f8942d631234f8e008d806bd502c58bc3 +create: Don't prompt with same dialog multiple times. + +diff -r f5f3ff4f8942 -r cfcd19d057dd src/virtManager/create.py +--- a/src/virtManager/create.py Wed Sep 23 16:43:40 2009 -0400 ++++ b/src/virtManager/create.py Thu Sep 24 11:41:49 2009 -0400 +@@ -1122,7 +1122,7 @@ + if pagenum == PAGE_NAME: + return self.validate_name_page() + elif pagenum == PAGE_INSTALL: +- return self.validate_install_page() ++ return self.validate_install_page(revalidate=False) + elif pagenum == PAGE_MEM: + return self.validate_mem_page() + elif pagenum == PAGE_STORAGE: +@@ -1135,7 +1135,7 @@ + return False + elif not self.validate_mem_page(): + return False +- return self.validate_storage_page() ++ return self.validate_storage_page(revalidate=False) + + elif pagenum == PAGE_FINISH: + # Since we allow the user to change to change HV type + arch +@@ -1169,7 +1169,7 @@ + + return True + +- def validate_install_page(self): ++ def validate_install_page(self, revalidate=True): + instmethod = self.get_config_install_page() + installer = None + location = None +@@ -1270,7 +1270,7 @@ + + return True + +- def validate_storage_page(self): ++ def validate_storage_page(self, revalidate=True): + use_storage = self.window.get_widget("enable-storage").get_active() + + self.guest.disks = [] +@@ -1296,19 +1296,21 @@ + return self.verr(_("Storage parameter error."), str(e)) + + isfatal, errmsg = disk.is_size_conflict() +- if not isfatal and errmsg: ++ if not revalidate and 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 +- if disk.is_conflict_disk(self.guest.conn): +- return self.err.yes_no(_('Disk "%s" is already in use by another ' +- 'guest!' % disk.path), +- _("Do you really want to use the disk?")) +- else: +- return True ++ if not revalidate and disk.is_conflict_disk(self.guest.conn): ++ res = self.err.yes_no(_('Disk "%s" is already in use by another ' ++ 'guest!' % disk.path), ++ _("Do you really want to use the disk?")) ++ if not res: ++ return False ++ ++ return True + + def validate_final_page(self): + nettype, devname, macaddr = self.get_config_network_info() +diff -r 343b42ebee5b src/virtManager/addhardware.py +--- a/src/virtManager/addhardware.py Thu Sep 24 11:41:49 2009 -0400 ++++ b/src/virtManager/addhardware.py Thu Sep 24 11:44:49 2009 -0400 +@@ -31,6 +31,7 @@ + import virtinst + from virtinst import VirtualCharDevice, VirtualDevice, VirtualVideoDevice + ++import virtManager.create + import virtManager.util as vmmutil + from virtManager.asyncjob import vmmAsyncJob + from virtManager.error import vmmErrorDialog +@@ -1054,6 +1055,7 @@ + return self.err.val_err(_("Hardware Type Required"), \ + _("You must specify what type of hardware to add.")) + self._dev = None ++ + elif page_num == PAGE_DISK: + path = self.get_config_disk_image() + if path == None or len(path) == 0: +@@ -1102,6 +1104,11 @@ + _("Do you really want to use the disk?")) + return res + ++ # Make sure qemu can access path ++ virtManager.create.check_path_search_for_qemu(self, ++ self.vm.connection, ++ self._dev.path) ++ + elif page_num == PAGE_NETWORK: + net = self.get_config_network() + if self.window.get_widget("net-type-network").get_active(): +diff -r 343b42ebee5b src/virtManager/choosecd.py +--- a/src/virtManager/choosecd.py Thu Sep 24 11:41:49 2009 -0400 ++++ b/src/virtManager/choosecd.py Thu Sep 24 11:44:49 2009 -0400 +@@ -24,6 +24,7 @@ + import virtinst + + import virtManager.opticalhelper ++import virtManager.create + from virtManager.storagebrowse import vmmStorageBrowser + from virtManager.error import vmmErrorDialog + +@@ -108,6 +109,10 @@ + except Exception, e: + return self.err.val_err(_("Invalid Media Path"), str(e)) + ++ # Make sure qemu can access the path ++ virtManager.create.check_path_search_for_qemu(self, self.conn, ++ disk.path) ++ + self.emit("cdrom-chosen", disk.type, disk.path, self.dev_id_info) + self.cancel() + +diff -r 343b42ebee5b src/virtManager/config.py +--- a/src/virtManager/config.py Thu Sep 24 11:41:49 2009 -0400 ++++ b/src/virtManager/config.py Thu Sep 24 11:44:49 2009 -0400 +@@ -558,3 +558,15 @@ + else: + return os.getcwd() + ++ def add_perms_fix_ignore(self, pathlist): ++ current_list = self.get_perms_fix_ignore() or [] ++ for path in pathlist: ++ if path in current_list: ++ continue ++ current_list.append(path) ++ self.conf.set_list(self.conf_dir + "/paths/perms_fix_ignore", ++ gconf.VALUE_STRING, ++ current_list) ++ def get_perms_fix_ignore(self): ++ return self.conf.get_list(self.conf_dir + "/paths/perms_fix_ignore", ++ gconf.VALUE_STRING) +diff -r 343b42ebee5b src/virtManager/create.py +--- a/src/virtManager/create.py Thu Sep 24 11:41:49 2009 -0400 ++++ b/src/virtManager/create.py Thu Sep 24 11:44:49 2009 -0400 +@@ -30,6 +30,7 @@ + + import virtinst + from virtinst import VirtualNetworkInterface ++from virtinst import VirtualDisk + + import virtManager.opticalhelper + from virtManager import util +@@ -53,6 +54,54 @@ + INSTALL_PAGE_URL = 1 + INSTALL_PAGE_PXE = 2 + ++def check_path_search_for_qemu(vmm_obj, conn, path): ++ if conn.is_remote() or not conn.is_qemu_system(): ++ return ++ ++ user = "qemu" ++ ++ skip_paths = vmm_obj.config.get_perms_fix_ignore() ++ broken_paths = VirtualDisk.check_path_search_for_user(conn.vmm, path, user) ++ for p in broken_paths: ++ if p in skip_paths: ++ broken_paths.remove(p) ++ ++ if not broken_paths: ++ return ++ ++ logging.debug("No search access for dirs: %s" % broken_paths) ++ resp, chkres = vmm_obj.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.")) ++ ++ if chkres: ++ vmm_obj.config.add_perms_fix_ignore(broken_paths) ++ if not resp: ++ return ++ ++ logging.debug("Attempting to correct permission issues.") ++ errors = VirtualDisk.fix_path_search_for_user(conn.vmm, path, user) ++ if not errors: ++ return ++ ++ errmsg = _("Errors were encountered changing permissions for the " ++ "following directories:") ++ details = "" ++ for path, error in errors.items(): ++ if path not in broken_paths: ++ continue ++ details += "%s : %s\n" % (path, error) ++ ++ logging.debug("Permission errors:\n%s" % details) ++ ++ ignore, chkres = vmm_obj.err.err_chkbox(errmsg, details, ++ _("Don't ask about these directories again.")) ++ ++ if chkres: ++ vmm_obj.config.add_perms_fix_ignore(errors.keys()) ++ + class vmmCreate(gobject.GObject): + __gsignals__ = { + "action-show-console": (gobject.SIGNAL_RUN_FIRST, +@@ -1245,6 +1294,11 @@ + return self.err.val_err(_("Error setting OS information."), + str(e)) + ++ if instmethod == INSTALL_PAGE_ISO and not revalidate: ++ # Check if 'qemu' user can access disk ++ check_path_search_for_qemu(self, self.conn, ++ self.guest.installer.location) ++ + # Validation passed, store the install path (if there is one) in + # gconf + self.get_config_local_media(store_media=True) +@@ -1286,10 +1340,10 @@ + if not diskpath: + return self.verr(_("A storage path must be specified.")) + +- disk = virtinst.VirtualDisk(conn = self.conn.vmm, +- path = diskpath, +- size = disksize, +- sparse = sparse) ++ disk = VirtualDisk(conn = self.conn.vmm, ++ path = diskpath, ++ size = disksize, ++ sparse = sparse) + + self.guest.disks.append(disk) + except Exception, e: +@@ -1310,6 +1364,10 @@ + if not res: + return False + ++ if not revalidate: ++ # Check if 'qemu' user can access disk ++ check_path_search_for_qemu(self, self.conn, disk.path) ++ + return True + + def validate_final_page(self): diff --git a/virt-manager-0.8.0-refresh-disk-space.patch b/virt-manager-0.8.0-refresh-disk-space.patch new file mode 100644 index 0000000..7ccd235 --- /dev/null +++ b/virt-manager-0.8.0-refresh-disk-space.patch @@ -0,0 +1,96 @@ +# HG changeset patch +# User Cole Robinson +# Date 1253563791 14400 +# Node ID f75237b0a84e73552a55ef0121215633c4530879 +# Parent d3b377306a994f66cd1c03f3bcbef17c4b060720 +Use timer to refresh available disk space in 'New VM' wizard (bz 502777) + +diff -r d3b377306a99 -r f75237b0a84e src/virtManager/create.py +--- a/src/virtManager/create.py Thu Sep 17 13:45:53 2009 -0400 ++++ b/src/virtManager/create.py Mon Sep 21 16:09:51 2009 -0400 +@@ -93,6 +93,10 @@ + # 'Guest' class from the previous failed install + self.failed_guest = None + ++ # Host space polling ++ self.host_storage_timer = None ++ self.host_storage = None ++ + self.window.signal_autoconnect({ + "on_vmm_newcreate_delete_event" : self.close, + +@@ -136,8 +140,18 @@ + + def close(self, ignore1=None, ignore2=None): + self.topwin.hide() ++ self.remove_timers() ++ + return 1 + ++ def remove_timers(self): ++ try: ++ if self.host_storage_timer: ++ gobject.source_remote(self.host_storage_timer) ++ self.host_storage_timer = None ++ except: ++ pass ++ + def set_conn(self, newconn): + if self.conn == newconn: + return +@@ -303,9 +317,11 @@ + self.window.get_widget("config-cpus").set_value(1) + + # Storage ++ if not self.host_storage_timer: ++ self.host_storage_timer = gobject.timeout_add(3 * 1000, ++ self.host_space_tick) + self.window.get_widget("enable-storage").set_active(True) + self.window.get_widget("config-storage-create").set_active(True) +- # FIXME: Make sure this doesn't exceed host? + self.window.get_widget("config-storage-size").set_value(8) + self.window.get_widget("config-storage-entry").set_text("") + self.window.get_widget("config-storage-nosparse").set_active(True) +@@ -437,11 +453,6 @@ + # Storage + have_storage = (is_local or is_storage_capable) + storage_tooltip = None +- max_storage = self.host_disk_space() +- hd_label = "%s available on the host" % self.pretty_storage(max_storage) +- hd_label = ("%s" % hd_label) +- self.window.get_widget("phys-hd-label").set_markup(hd_label) +- self.window.get_widget("config-storage-size").set_range(1, max_storage) + + use_storage = self.window.get_widget("config-storage-select") + storage_area = self.window.get_widget("config-storage-area") +@@ -863,6 +874,7 @@ + # FIXME: use a conn specific function after we send pool-added + pool = virtinst.util.lookup_pool_by_path(self.conn.vmm, path) + if pool: ++ pool.refresh(0) + avail = int(virtinst.util.get_xml_path(pool.XMLDesc(0), + "/pool/available")) + +@@ -870,7 +882,21 @@ + vfs = os.statvfs(os.path.dirname(path)) + avail = vfs[statvfs.F_FRSIZE] * vfs[statvfs.F_BAVAIL] + +- return int(avail / 1024.0 / 1024.0 / 1024.0) ++ return float(avail / 1024.0 / 1024.0 / 1024.0) ++ ++ def host_space_tick(self): ++ max_storage = self.host_disk_space() ++ if self.host_storage == max_storage: ++ return 1 ++ self.host_storage = max_storage ++ ++ hd_label = ("%s available in the default location" % ++ self.pretty_storage(max_storage)) ++ hd_label = ("%s" % hd_label) ++ self.window.get_widget("phys-hd-label").set_markup(hd_label) ++ self.window.get_widget("config-storage-size").set_range(1, self.host_storage) ++ ++ return 1 + + def get_config_network_info(self): + netidx = self.window.get_widget("config-netdev").get_active() diff --git a/virt-manager.spec b/virt-manager.spec index 4091cbe..aae61a5 100644 --- a/virt-manager.spec +++ b/virt-manager.spec @@ -8,7 +8,7 @@ Name: virt-manager Version: 0.8.0 -Release: 4%{_extra_release} +Release: 5%{_extra_release} Summary: Virtual Machine Manager Group: Applications/Emulators @@ -36,6 +36,10 @@ Patch6: %{name}-%{version}-conn-close-exception.patch Patch7: %{name}-%{version}-manager-ui-tweaks.patch # Generate better errors is disk/net stats polling fails Patch8: %{name}-%{version}-stats-logging.patch +# Refresh host disk space in create wizard (bz 502777) +Patch9: %{name}-%{version}-refresh-disk-space.patch +# Offer to fix disk permission issues (bz 517379) +Patch10: %{name}-%{version}-fix-path-perms.patch # These two are just the oldest version tested Requires: pygtk2 >= 1.99.12-6 @@ -61,7 +65,7 @@ Requires: gnome-python2-gnome # Minimum we've tested with Requires: libxml2-python >= 2.6.23 # Required to install Xen & QEMU guests -Requires: python-virtinst >= 0.500.0 +Requires: python-virtinst >= 0.500.0-4 # Required for loading the glade UI Requires: pygtk2-libglade # Required for our graphics which are currently SVG format @@ -111,6 +115,8 @@ cp %{SOURCE3} pixmaps %patch6 -p1 %patch7 -p1 %patch8 -p1 +%patch9 -p1 +%patch10 -p1 %build %configure @@ -184,6 +190,10 @@ fi %{_datadir}/dbus-1/services/%{name}.service %changelog +* Thu Sep 24 2009 Cole Robinson - 0.8.0-5.fc12 +- Refresh host disk space in create wizard (bz 502777) +- Offer to fix disk permission issues (bz 517379) + * Thu Sep 17 2009 Cole Robinson - 0.8.0-4.fc12 - Don't close libvirt connection for non-fatal errors (bz 522168) - Manager UI tweaks diff --git a/virtinst-0.500.0-change-path-perms.patch b/virtinst-0.500.0-change-path-perms.patch new file mode 100644 index 0000000..00ec87a --- /dev/null +++ b/virtinst-0.500.0-change-path-perms.patch @@ -0,0 +1,193 @@ +# HG changeset patch +# User Cole Robinson +# Date 1253738317 14400 +# Node ID 53cd275974ab35a790b4c4bf1424d0950d5b095e +# Parent aff98f0152935ad7cd57e86c4172a6683e6306c5 +VirtualDisk: Add methods for checking/changing path perms for username. + +Since libvirtd can now run qemu processes as non-root, the tools need to +try to check directory permissions and make sure they are at least searchable +by a specific username. This simply implements the functions to make that +happen. + +diff -r aff98f015293 -r 53cd275974ab virtinst/VirtualDisk.py +--- a/virtinst/VirtualDisk.py Mon Sep 21 15:52:04 2009 -0400 ++++ b/virtinst/VirtualDisk.py Wed Sep 23 16:38:37 2009 -0400 +@@ -19,9 +19,11 @@ + # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + # MA 02110-1301 USA. + +-import os, statvfs ++import os, stat, pwd, statvfs + import subprocess + import logging ++import re ++ + import urlgrabber.progress as progress + import libvirt + +@@ -69,6 +71,46 @@ + + return fmt + ++def _name_uid(user): ++ """ ++ Return UID for string username ++ """ ++ pwdinfo = pwd.getpwnam(user) ++ return pwdinfo[2] ++ ++def _is_dir_searchable(uid, username, path): ++ """ ++ Check if passed directory is searchable by uid ++ """ ++ try: ++ statinfo = os.stat(path) ++ except OSError: ++ return False ++ ++ if uid == statinfo.st_uid: ++ flag = stat.S_IXUSR ++ elif uid == statinfo.st_gid: ++ flag = stat.S_IXGRP ++ else: ++ flag = stat.S_IXOTH ++ ++ if bool(statinfo.st_mode & flag): ++ return True ++ ++ # Check POSIX ACL (since that is what we use to 'fix' access) ++ cmd = ["getfacl", path] ++ proc = subprocess.Popen(cmd, ++ stdout=subprocess.PIPE, ++ stderr=subprocess.PIPE) ++ out, err = proc.communicate() ++ ++ if proc.returncode != 0: ++ logging.debug("Cmd '%s' failed: %s" % (cmd, err)) ++ return False ++ ++ return bool(re.search("user:%s:..x" % username, out)) ++ ++ + class VirtualDisk(VirtualDevice): + """ + Builds a libvirt domain disk xml description +@@ -156,6 +198,63 @@ + + return False + ++ @staticmethod ++ def check_path_search_for_user(conn, path, username): ++ """ ++ Check if the passed user has search permissions for all the ++ directories in the disk path. ++ ++ @return: List of the directories the user cannot search, or empty list ++ @rtype : C{list} ++ """ ++ if _util.is_uri_remote(conn.getURI()): ++ return [] ++ ++ uid = _name_uid(username) ++ fixlist = [] ++ ++ dirname, base = os.path.split(path) ++ while base: ++ if not _is_dir_searchable(uid, username, dirname): ++ fixlist.append(dirname) ++ ++ dirname, base = os.path.split(dirname) ++ ++ return fixlist ++ ++ @staticmethod ++ def fix_path_search_for_user(conn, path, username): ++ """ ++ Try to fix any permission problems found by check_path_search_for_user ++ ++ @return: Return a dictionary of entries { broken path : error msg } ++ @rtype : C{dict} ++ """ ++ fixlist = VirtualDisk.check_path_search_for_user(conn, path, username) ++ if not fixlist: ++ return [] ++ ++ fixlist.reverse() ++ errdict = {} ++ ++ for dirname in fixlist: ++ try: ++ cmd = ["setfacl", "--modify", "user:%s:x" % username, dirname] ++ proc = subprocess.Popen(cmd, ++ stdout=subprocess.PIPE, ++ stderr=subprocess.PIPE) ++ out, err = proc.communicate() ++ ++ logging.debug("Cmd '%s' output: \nout=%s, \nerr=%s" % ++ (cmd, out, err)) ++ if proc.returncode != 0: ++ raise ValueError(err) ++ except Exception, e: ++ errdict[dirname] = str(e) ++ ++ return errdict ++ ++ + def __init__(self, path=None, size=None, transient=False, type=None, + device=DEVICE_DISK, driverName=None, driverType=None, + readOnly=False, sparse=True, conn=None, volObject=None, +# HG changeset patch +# User Cole Robinson +# Date 1253741935 14400 +# Node ID a523260ac56eb90e1eda067c2bbd5fc726bb0165 +# Parent 53cd275974ab35a790b4c4bf1424d0950d5b095e +VirtualDisk: Teach perms changing functions about a target directory. + +diff -r 53cd275974ab -r a523260ac56e virtinst/VirtualDisk.py +--- a/virtinst/VirtualDisk.py Wed Sep 23 16:38:37 2009 -0400 ++++ b/virtinst/VirtualDisk.py Wed Sep 23 17:38:55 2009 -0400 +@@ -213,7 +213,12 @@ + uid = _name_uid(username) + fixlist = [] + +- dirname, base = os.path.split(path) ++ if os.path.isdir(path): ++ dirname = path ++ base = "-" ++ else: ++ dirname, base = os.path.split(path) ++ + while base: + if not _is_dir_searchable(uid, username, dirname): + fixlist.append(dirname) +diff -r 53cd275974ab virtinst/Installer.py +--- a/virtinst/Installer.py Wed Sep 23 16:38:37 2009 -0400 ++++ b/virtinst/Installer.py Wed Sep 23 17:32:14 2009 -0400 +@@ -141,12 +141,20 @@ + return XEN_SCRATCH + if os.path.exists(LIBVIRT_SCRATCH): + return LIBVIRT_SCRATCH +- else: +- scratch = os.path.expanduser("~/.virtinst/boot") +- if not os.path.exists(scratch): +- os.makedirs(scratch, 0750) +- _util.selinux_restorecon(scratch) +- return scratch ++ ++ scratch = os.path.expanduser("~/.virtinst/boot") ++ if not os.path.exists(scratch): ++ os.makedirs(scratch, 0751) ++ ++ if (self.conn and ++ not _util.is_uri_remote(self.conn.getURI()) and ++ _util.is_qemu_system(self.conn.getURI())): ++ # If we are using local qemu:///system, try to make sure the ++ # download location is searchable by the 'qemu' user ++ VirtualDisk.fix_path_search_for_user(self.conn, scratch, "qemu") ++ ++ _util.selinux_restorecon(scratch) ++ return scratch + scratchdir = property(get_scratchdir) + + def get_cdrom(self): diff --git a/virtinst-0.500.0-no-iso-driver.patch b/virtinst-0.500.0-no-iso-driver.patch new file mode 100644 index 0000000..b441e5d --- /dev/null +++ b/virtinst-0.500.0-no-iso-driver.patch @@ -0,0 +1,196 @@ +# HG changeset patch +# User Cole Robinson +# Date 1253562724 14400 +# Node ID aff98f0152935ad7cd57e86c4172a6683e6306c5 +# Parent 143b09da8bccc3b6b2069c29073ea5a6ef9ce69b +VirtualDisk: Don't use 'iso' as a qemu driver name (bz 524109) + +diff -r 143b09da8bcc -r aff98f015293 tests/testdriver.xml +--- a/tests/testdriver.xml Mon Sep 21 15:47:33 2009 -0400 ++++ b/tests/testdriver.xml Mon Sep 21 15:52:04 2009 -0400 +@@ -67,6 +67,22 @@ + + + ++ iso-vol ++ 1000000 ++ 50000 ++ ++ ++ ++ ++ ++ bochs-vol ++ 1000000 ++ 50000 ++ ++ ++ ++ ++ + testvol1.img + 1000000 + 50000 +diff -r 143b09da8bcc -r aff98f015293 tests/xmlconfig-xml/misc-qemu-iso-disk.xml +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/tests/xmlconfig-xml/misc-qemu-iso-disk.xml Mon Sep 21 15:52:04 2009 -0400 +@@ -0,0 +1,36 @@ ++ ++ TestGuest ++ 204800 ++ 409600 ++ 12345678-1234-1234-1234-123456789012 ++ ++ hvm ++ /usr/lib/xen/boot/hvmloader ++ ++ ++ ++ ++ ++ ++ destroy ++ destroy ++ destroy ++ 5 ++ ++ /usr/lib/xen/bin/qemu-dm ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff -r 143b09da8bcc -r aff98f015293 tests/xmlconfig.py +--- a/tests/xmlconfig.py Mon Sep 21 15:47:33 2009 -0400 ++++ b/tests/xmlconfig.py Mon Sep 21 15:52:04 2009 -0400 +@@ -302,9 +302,15 @@ + g.disks.append(get_blkdisk()) + self._compare(g, "misc-qemu-driver-name", True) + ++ VirtualDisk._get_uri = new_get_uri + g = get_basic_fullyvirt_guest() + g.disks.append(get_filedisk()) + self._compare(g, "misc-qemu-driver-type", True) ++ ++ VirtualDisk._get_uri = new_get_uri ++ g = get_basic_fullyvirt_guest() ++ g.disks.append(get_filedisk("/default-pool/iso-vol")) ++ self._compare(g, "misc-qemu-iso-disk", True) + finally: + VirtualDisk._get_uri = oldgetdriver + +diff -r 143b09da8bcc -r aff98f015293 virtinst/VirtualDisk.py +--- a/virtinst/VirtualDisk.py Mon Sep 21 15:47:33 2009 -0400 ++++ b/virtinst/VirtualDisk.py Mon Sep 21 15:52:04 2009 -0400 +@@ -55,6 +55,20 @@ + except OSError: + return False + ++def _qemu_sanitize_drvtype(phystype, fmt): ++ """ ++ Sanitize libvirt storage volume format to a valid qemu driver type ++ """ ++ raw_list = [ "iso" ] ++ ++ if phystype == VirtualDisk.TYPE_BLOCK: ++ return VirtualDisk.DRIVER_QEMU_RAW ++ ++ if fmt in raw_list: ++ return VirtualDisk.DRIVER_QEMU_RAW ++ ++ return fmt ++ + class VirtualDisk(VirtualDevice): + """ + Builds a libvirt domain disk xml description +@@ -490,8 +504,8 @@ + + http://lists.gnu.org/archive/html/qemu-devel/2008-04/msg00675.html + """ +- drvname = None +- drvtype = None ++ drvname = self._driverName ++ drvtype = self._driverType + + if self.conn: + driver = _util.get_uri_driver(self._get_uri()) +@@ -499,15 +513,15 @@ + drvname = self.DRIVER_QEMU + + if self.vol_object: +- drvtype = _util.get_xml_path(self.vol_object.XMLDesc(0), +- "/volume/target/format/@type") ++ fmt = _util.get_xml_path(self.vol_object.XMLDesc(0), ++ "/volume/target/format/@type") ++ if drvname == self.DRIVER_QEMU: ++ drvtype = _qemu_sanitize_drvtype(self.type, fmt) + + elif self.vol_install: + if drvname == self.DRIVER_QEMU: +- if self.vol_install.file_type == libvirt.VIR_STORAGE_VOL_FILE: +- drvtype = self.vol_install.format +- else: +- drvtype = self.DRIVER_QEMU_RAW ++ drvtype = _qemu_sanitize_drvtype(self.type, ++ self.vol_install.format) + + elif self.__creating_storage(): + if drvname == self.DRIVER_QEMU: +@@ -729,8 +743,10 @@ + managed_storage = self.__storage_specified() + create_media = self.__creating_storage() + ++ self.__set_dev_type() + self.__set_size() + self.__set_format() ++ self.__set_driver() + + if not self.selinux_label: + # If we are using existing storage, pull the label from it +@@ -745,9 +761,6 @@ + + self._selinux_label = context or "" + +- # Set driverName + driverType +- self.__set_driver() +- + # If not creating the storage, our job is easy + if not create_media: + # Make sure we have access to the local path +@@ -757,7 +770,6 @@ + raise ValueError(_("The path '%s' must be a file or a " + "device, not a directory") % self.path) + +- self.__set_dev_type() + return True + + +@@ -770,7 +782,6 @@ + if self.type is self.TYPE_BLOCK: + raise ValueError, _("Local block device path '%s' must " + "exist.") % self.path +- self.set_type(self.TYPE_FILE, validate=False) + + # Path doesn't exist: make sure we have write access to dir + if not os.access(os.path.dirname(self.path), os.R_OK): +@@ -782,9 +793,6 @@ + if not os.access(os.path.dirname(self.path), os.W_OK): + raise ValueError, _("No write access to directory '%s'") % \ + os.path.dirname(self.path) +- else: +- # Set dev type from existing storage +- self.__set_dev_type() + + # Applicable for managed or local storage + ret = self.is_size_conflict()