-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
957 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
320 changes: 320 additions & 0 deletions
320
xattr-removal_patch/Mitaka/xattr-removal_mitaka-nova_plain-diff.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,320 @@ | ||
diff --git a/etc/nova/rootwrap.d/compute.filters b/etc/nova/rootwrap.d/compute.filters | ||
index e471848..aeb3170 100644 | ||
--- a/etc/nova/rootwrap.d/compute.filters | ||
+++ b/etc/nova/rootwrap.d/compute.filters | ||
@@ -261,5 +261,9 @@ | ||
# nova/virt/libvirt/utils.py: | ||
touch: CommandFilter, touch, root | ||
|
||
+# nova/virt/libvirt/volume/quobyte.py | ||
+mount.quobyte: CommandFilter, mount.quobyte, root | ||
+umount.quobyte: CommandFilter, umount.quobyte, root | ||
+ | ||
# nova/virt/libvirt/volume/vzstorage.py | ||
pstorage-mount: CommandFilter, pstorage-mount, root | ||
diff --git a/nova/tests/unit/virt/libvirt/volume/test_quobyte.py b/nova/tests/unit/virt/libvirt/volume/test_quobyte.py | ||
index a43a79a..2197c78 100644 | ||
--- a/nova/tests/unit/virt/libvirt/volume/test_quobyte.py | ||
+++ b/nova/tests/unit/virt/libvirt/volume/test_quobyte.py | ||
@@ -15,12 +15,15 @@ | ||
"""Unit tests for the Quobyte volume driver module.""" | ||
|
||
import os | ||
+import traceback | ||
|
||
import mock | ||
from oslo_concurrency import processutils | ||
from oslo_utils import fileutils | ||
+import psutil | ||
+import six | ||
|
||
-from nova import exception | ||
+from nova import exception as nova_exception | ||
from nova import test | ||
from nova.tests.unit.virt.libvirt.volume import test_volume | ||
from nova import utils | ||
@@ -30,6 +33,31 @@ | ||
|
||
class QuobyteTestCase(test.NoDBTestCase): | ||
"""Tests the nova.virt.libvirt.volume.quobyte module utilities.""" | ||
+ | ||
+ TEST_MNT_POINT = "/tmp/test_mpt" | ||
+ | ||
+ def assertRaisesAndMessageMatches( | ||
+ self, excClass, msg, callableObj, *args, **kwargs): | ||
+ """Ensure that the specified exception was raised. """ | ||
+ | ||
+ caught = False | ||
+ try: | ||
+ callableObj(*args, **kwargs) | ||
+ except Exception as exc: | ||
+ caught = True | ||
+ self.assertIsInstance(exc, excClass, | ||
+ 'Wrong exception caught: %s Stacktrace: %s' % | ||
+ (exc, traceback.format_exc())) | ||
+ self.assertIn(msg, six.text_type(exc)) | ||
+ | ||
+ if not caught: | ||
+ self.fail('Expected raised exception but nothing caught.') | ||
+ | ||
+ def get_mock_partitions(self): | ||
+ mypart = mock.Mock() | ||
+ mypart.device = "quobyte@" | ||
+ mypart.mountpoint = self.TEST_MNT_POINT | ||
+ return [mypart] | ||
|
||
@mock.patch.object(fileutils, "ensure_tree") | ||
@mock.patch.object(utils, "execute") | ||
@@ -43,6 +71,7 @@ | ||
|
||
mock_ensure_tree.assert_called_once_with(export_mnt_base) | ||
expected_commands = [mock.call('mount.quobyte', | ||
+ '--disable-xattrs', | ||
quobyte_volume, | ||
export_mnt_base, | ||
check_exit_code=[0, 4]) | ||
@@ -66,6 +95,7 @@ | ||
|
||
mock_ensure_tree.assert_called_once_with(export_mnt_base) | ||
expected_commands = [mock.call('mount.quobyte', | ||
+ '--disable-xattrs', | ||
quobyte_volume, | ||
export_mnt_base, | ||
'-c', | ||
@@ -141,49 +171,82 @@ | ||
"the Quobyte Volume at %s", | ||
export_mnt_base)) | ||
|
||
- @mock.patch.object(os, "access", return_value=True) | ||
- @mock.patch.object(utils, "execute") | ||
- def test_quobyte_is_valid_volume(self, mock_execute, mock_access): | ||
- mnt_base = '/mnt' | ||
- quobyte_volume = '192.168.1.1/volume-00001' | ||
- export_mnt_base = os.path.join(mnt_base, | ||
- utils.get_hash_str(quobyte_volume)) | ||
+ @mock.patch.object(psutil, "disk_partitions") | ||
+ @mock.patch.object(os, "stat") | ||
+ def test_validate_volume_all_good(self, stat_mock, part_mock): | ||
+ part_mock.return_value = self.get_mock_partitions() | ||
+ drv = quobyte | ||
|
||
- quobyte.validate_volume(export_mnt_base) | ||
+ def statMockCall(*args): | ||
+ if args[0] == self.TEST_MNT_POINT: | ||
+ stat_result = mock.Mock() | ||
+ stat_result.st_size = 0 | ||
+ return stat_result | ||
+ return os.stat(args) | ||
+ stat_mock.side_effect = statMockCall | ||
|
||
- mock_execute.assert_called_once_with('getfattr', | ||
- '-n', | ||
- 'quobyte.info', | ||
- export_mnt_base) | ||
+ drv.validate_volume(self.TEST_MNT_POINT) | ||
|
||
- @mock.patch.object(utils, "execute", | ||
- side_effect=(processutils. | ||
- ProcessExecutionError)) | ||
- def test_quobyte_is_valid_volume_vol_not_valid_volume(self, mock_execute): | ||
- mnt_base = '/mnt' | ||
- quobyte_volume = '192.168.1.1/volume-00001' | ||
- export_mnt_base = os.path.join(mnt_base, | ||
- utils.get_hash_str(quobyte_volume)) | ||
+ stat_mock.assert_called_once_with(self.TEST_MNT_POINT) | ||
+ part_mock.assert_called_once_with(all=True) | ||
|
||
- self.assertRaises(exception.NovaException, | ||
- quobyte.validate_volume, | ||
- export_mnt_base) | ||
+ @mock.patch.object(psutil, "disk_partitions") | ||
+ @mock.patch.object(os, "stat") | ||
+ def test_validate_volume_mount_not_working(self, stat_mock, part_mock): | ||
+ part_mock.return_value = self.get_mock_partitions() | ||
+ drv = quobyte | ||
|
||
- @mock.patch.object(os, "access", return_value=False) | ||
- @mock.patch.object(utils, "execute", | ||
- side_effect=(processutils. | ||
- ProcessExecutionError)) | ||
- def test_quobyte_is_valid_volume_vol_no_valid_access(self, | ||
- mock_execute, | ||
- mock_access): | ||
- mnt_base = '/mnt' | ||
- quobyte_volume = '192.168.1.1/volume-00001' | ||
- export_mnt_base = os.path.join(mnt_base, | ||
- utils.get_hash_str(quobyte_volume)) | ||
+ def statMockCall(*args): | ||
+ print (args) | ||
+ if args[0] == self.TEST_MNT_POINT: | ||
+ raise nova_exception.InvalidVolume() | ||
+ stat_mock.side_effect = [statMockCall, os.stat] | ||
|
||
- self.assertRaises(exception.NovaException, | ||
- quobyte.validate_volume, | ||
- export_mnt_base) | ||
+ self.assertRaises( | ||
+ excClass=nova_exception.InvalidVolume, | ||
+ callableObj=drv.validate_volume, | ||
+ mount_path=self.TEST_MNT_POINT) | ||
+ stat_mock.assert_called_with(self.TEST_MNT_POINT) | ||
+ part_mock.assert_called_once_with(all=True) | ||
+ | ||
+ def test_validate_volume_no_mtab_entry(self): | ||
+ msg = ("No matching Quobyte mount entry for %(mpt)s" | ||
+ " could be found for validation in partition list." | ||
+ % {'mpt': self.TEST_MNT_POINT}) | ||
+ | ||
+ self.assertRaisesAndMessageMatches( | ||
+ nova_exception.InvalidVolume, | ||
+ msg, | ||
+ quobyte.validate_volume, | ||
+ self.TEST_MNT_POINT) | ||
+ | ||
+ @mock.patch.object(psutil, "disk_partitions") | ||
+ def test_validate_volume_wrong_mount_type(self, part_mock): | ||
+ mypart = mock.Mock() | ||
+ mypart.device = "not-quobyte" | ||
+ mypart.mountpoint = self.TEST_MNT_POINT | ||
+ part_mock.return_value = [mypart] | ||
+ msg = ("The mount %(mpt)s is not a valid" | ||
+ " Quobyte volume according to partition list." | ||
+ % {'mpt': self.TEST_MNT_POINT}) | ||
+ | ||
+ self.assertRaisesAndMessageMatches( | ||
+ nova_exception.InvalidVolume, | ||
+ msg, | ||
+ quobyte.validate_volume, | ||
+ self.TEST_MNT_POINT) | ||
+ part_mock.assert_called_once_with(all=True) | ||
+ | ||
+ @mock.patch.object(psutil, "disk_partitions") | ||
+ def test_validate_volume_stale_mount(self, part_mock): | ||
+ part_mock.return_value = self.get_mock_partitions() | ||
+ | ||
+ # As this uses a local fs the dir size is >0, raising an exception | ||
+ self.assertRaises( | ||
+ nova_exception.InvalidVolume, | ||
+ quobyte.validate_volume, | ||
+ self.TEST_MNT_POINT) | ||
+ part_mock.assert_called_once_with(all=True) | ||
|
||
|
||
class LibvirtQuobyteVolumeDriverTestCase( | ||
@@ -332,12 +395,12 @@ | ||
|
||
def exe_side_effect(*cmd, **kwargs): | ||
if cmd == mock.ANY: | ||
- raise exception.NovaException() | ||
+ raise nova_exception.NovaException() | ||
|
||
with mock.patch.object(quobyte, | ||
'validate_volume') as mock_execute: | ||
mock_execute.side_effect = exe_side_effect | ||
- self.assertRaises(exception.NovaException, | ||
+ self.assertRaises(nova_exception.NovaException, | ||
libvirt_driver.connect_volume, | ||
connection_info, | ||
self.disk_info) | ||
diff --git a/nova/virt/libvirt/volume/quobyte.py b/nova/virt/libvirt/volume/quobyte.py | ||
index 284a084..97a36ea 100644 | ||
--- a/nova/virt/libvirt/volume/quobyte.py | ||
+++ b/nova/virt/libvirt/volume/quobyte.py | ||
@@ -19,6 +19,7 @@ | ||
from oslo_concurrency import processutils | ||
from oslo_log import log as logging | ||
from oslo_utils import fileutils | ||
+import psutil | ||
import six | ||
|
||
import nova.conf | ||
@@ -26,6 +27,7 @@ | ||
from nova.i18n import _ | ||
from nova.i18n import _LE | ||
from nova.i18n import _LI | ||
+from nova.i18n import _LW | ||
from nova import utils | ||
from nova.virt.libvirt import utils as libvirt_utils | ||
from nova.virt.libvirt.volume import fs | ||
@@ -44,7 +46,7 @@ | ||
"""Wraps execute calls for mounting a Quobyte volume""" | ||
fileutils.ensure_tree(mnt_base) | ||
|
||
- command = ['mount.quobyte', volume, mnt_base] | ||
+ command = ['mount.quobyte', '--disable-xattrs', volume, mnt_base] | ||
if configfile: | ||
command.extend(['-c', configfile]) | ||
|
||
@@ -69,21 +71,46 @@ | ||
mnt_base) | ||
|
||
|
||
-def validate_volume(mnt_base): | ||
- """Wraps execute calls for checking validity of a Quobyte volume""" | ||
- command = ['getfattr', "-n", "quobyte.info", mnt_base] | ||
- try: | ||
- utils.execute(*command) | ||
- except processutils.ProcessExecutionError as exc: | ||
- msg = (_("The mount %(mount_path)s is not a valid" | ||
- " Quobyte volume. Error: %(exc)s") | ||
- % {'mount_path': mnt_base, 'exc': exc}) | ||
- raise nova_exception.InternalError(msg) | ||
- | ||
- if not os.access(mnt_base, os.W_OK | os.X_OK): | ||
- msg = (_LE("Volume is not writable. Please broaden the file" | ||
- " permissions. Mount: %s") % mnt_base) | ||
- raise nova_exception.InternalError(msg) | ||
+def validate_volume(mount_path): | ||
+ """Runs a number of tests on the expected Quobyte mount""" | ||
+ partitions = psutil.disk_partitions(all=True) | ||
+ for p in partitions: | ||
+ if mount_path != p.mountpoint: | ||
+ continue | ||
+ if p.device.startswith("quobyte@"): | ||
+ try: | ||
+ statresult = os.stat(mount_path) | ||
+ # Note(kaisers): Quobyte always shows mount points with size 0 | ||
+ if statresult.st_size == 0: | ||
+ # client looks healthy | ||
+ if not os.access(mount_path, | ||
+ os.W_OK | os.X_OK): | ||
+ LOG.warning(_LW("Volume is not writable. " | ||
+ "Please broaden the file" | ||
+ " permissions." | ||
+ " Mount: %s"), | ||
+ mount_path) | ||
+ return # we're happy here | ||
+ else: | ||
+ msg = (_("The mount %(mount_path)s is not a " | ||
+ "valid Quobyte volume. Stale mount?") | ||
+ % {'mount_path': mount_path}) | ||
+ raise nova_exception.InvalidVolume(msg) | ||
+ except Exception as exc: | ||
+ msg = (_("The mount %(mount_path)s is not a valid" | ||
+ " Quobyte volume. Error: %(exc)s . " | ||
+ " Possibly a Quobyte client crash?") | ||
+ % {'mount_path': mount_path, 'exc': exc}) | ||
+ raise nova_exception.InvalidVolume(msg) | ||
+ else: | ||
+ msg = (_("The mount %(mount_path)s is not a valid" | ||
+ " Quobyte volume according to partition list.") | ||
+ % {'mount_path': mount_path}) | ||
+ raise nova_exception.InvalidVolume(msg) | ||
+ msg = (_("No matching Quobyte mount entry for %(mount_path)s" | ||
+ " could be found for validation in partition list.") | ||
+ % {'mount_path': mount_path}) | ||
+ raise nova_exception.InvalidVolume(msg) | ||
|
||
|
||
class LibvirtQuobyteVolumeDriver(fs.LibvirtBaseFileSystemVolumeDriver): | ||
@@ -127,8 +154,8 @@ | ||
|
||
if not mounted: | ||
mount_volume(quobyte_volume, | ||
- mount_path, | ||
- CONF.libvirt.quobyte_client_cfg) | ||
+ mount_path, | ||
+ CONF.libvirt.quobyte_client_cfg) | ||
|
||
validate_volume(mount_path) | ||
|
Oops, something went wrong.