Blob Blame History Raw
# HG changeset patch
# User Cole Robinson <crobinso@redhat.com>
# 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 <crobinso@redhat.com>
# 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):