]> xenbits.xensource.com Git - osstest/openstack-nova.git/commitdiff
Guestfs handle no passwd or group in image
authorAndrea Frittoli <andrea.frittoli@gmail.com>
Mon, 5 Dec 2016 15:34:11 +0000 (15:34 +0000)
committerAndrea Frittoli <andrea.frittoli@gmail.com>
Fri, 9 Dec 2016 12:48:44 +0000 (12:48 +0000)
When setting ownership of a file or directory, the guestfs driver
looks for the /etc/passwd and/or /etc/group files. In case they
are not found, the current driver lets the auges RuntimeError
through, which does not produce a very helpful error message.
Fixing that by handling the original exception and rasing a
Nova exception with more details in it.

Related-bug: #1646002

Change-Id: I2d15865c8be13b938e10e67c1b1b160f2a80f0c0

nova/tests/unit/virt/disk/vfs/fakeguestfs.py
nova/tests/unit/virt/disk/vfs/test_guestfs.py
nova/virt/disk/vfs/guestfs.py

index 3cec75feb2699b7ca15745112a4b317fce46c7b5..4887280496aa123b259db94a29af1f281698f665 100644 (file)
@@ -22,6 +22,7 @@ EVENT_TRACE = 0x4
 class GuestFS(object):
     SUPPORT_CLOSE_ON_EXIT = True
     SUPPORT_RETURN_DICT = True
+    CAN_SET_OWNERSHIP = True
 
     def __init__(self, **kwargs):
         if not self.SUPPORT_CLOSE_ON_EXIT and 'close_on_exit' in kwargs:
@@ -164,6 +165,11 @@ class GuestFS(object):
         if not self.auginit:
             raise RuntimeError("Augeus not initialized")
 
+        if ((cfgpath.startswith("/files/etc/passwd") or
+                cfgpath.startswith("/files/etc/group")) and not
+                self.CAN_SET_OWNERSHIP):
+            raise RuntimeError("Node not found %s", cfgpath)
+
         if cfgpath == "/files/etc/passwd/root/uid":
             return 0
         elif cfgpath == "/files/etc/passwd/fred/uid":
index e087e6011f85e674b108fe4f84ca97b3ea4dbbd0..9cb879f709592a82a8859fe4a04bb32acc58e6ea 100644 (file)
@@ -253,6 +253,20 @@ class VirtDiskVFSGuestFSTest(test.NoDBTestCase):
 
         vfs.teardown()
 
+    def test_set_ownership_not_supported(self):
+        # NOTE(andreaf) Setting ownership relies on /etc/passwd and/or
+        # /etc/group being available in the image, which is not always the
+        # case - e.g. CirrOS image before boot.
+        vfs = vfsimpl.VFSGuestFS(self.qcowfile)
+        vfs.setup()
+        self.stub_out('nova.tests.unit.virt.disk.vfs.fakeguestfs.GuestFS.'
+                      'CAN_SET_OWNERSHIP', False)
+
+        self.assertRaises(exception.NovaException, vfs.set_ownership,
+                          "/some/file", "fred", None)
+        self.assertRaises(exception.NovaException, vfs.set_ownership,
+                          "/some/file", None, "users")
+
     def test_close_on_error(self):
         vfs = vfsimpl.VFSGuestFS(self.qcowfile)
         vfs.setup()
index 68fb4c32d317b7434526520922c4ee4cc2a61a1f..82343d94b18d4953eeb99493b42d7aca3455a878 100644 (file)
@@ -316,13 +316,20 @@ class VFSGuestFS(vfs.VFS):
         uid = -1
         gid = -1
 
+        def _get_item_id(id_path):
+            try:
+                return int(self.handle.aug_get("/files/etc/" + id_path))
+            except RuntimeError as e:
+                msg = _("Error obtaining uid/gid for %(user)s/%(group)s: "
+                        " path %(id_path)s not found (%(e)s)") % {
+                    'id_path': "/files/etc/" + id_path, 'user': user,
+                    'group': group, 'e': e}
+                raise exception.NovaException(msg)
+
         if user is not None:
-            uid = int(self.handle.aug_get(
-                    "/files/etc/passwd/" + user + "/uid"))
+            uid = _get_item_id('passwd/' + user + '/uid')
         if group is not None:
-            gid = int(self.handle.aug_get(
-                    "/files/etc/group/" + group + "/gid"))
-
+            gid = _get_item_id('group/' + group + '/gid')
         LOG.debug("chown uid=%(uid)d gid=%(gid)s",
                   {'uid': uid, 'gid': gid})
         self.handle.chown(uid, gid, path)