Fixed concurrent access to direct io test file

When instances are deployed concurrently on multiple
compute nodes, nova-compute may fail on checking
direct io capabilities when instance_path is shared
across nodes. This fails on shared storage, that
doesn't support concurrent write access to the
same file, i.e. Virtuozzo Storage. To fix that we add
random string at the end of test file name.

Closes-Bug: #1727369
Change-Id: I085ade355fba0e9727a38d2dcbc9cffa735a62d1
Signed-off-by: Pavel Glushchak <pglushchak@virtuozzo.com>
This commit is contained in:
Pavel Glushchak 2017-10-25 15:58:01 +03:00 committed by melanie witt
parent 20bc0136d0
commit 26521718bd
5 changed files with 21 additions and 4 deletions
nova
privsep
tests
functional
unit
privsep
virt/libvirt
utils.py

@ -27,6 +27,7 @@ import os
from oslo_log import log as logging
from oslo_utils import excutils
from nova import utils as nova_utils
LOG = logging.getLogger(__name__)
@ -37,7 +38,9 @@ def supports_direct_io(dirpath):
LOG.debug("This python runtime does not support direct I/O")
return False
testfile = os.path.join(dirpath, ".directio.test")
file_name = "%s.%s" % (".directio.test",
nova_utils.generate_random_string())
testfile = os.path.join(dirpath, file_name)
hasDirectIO = True
fd = None

@ -633,6 +633,8 @@ class ServersTest(ServersTestBase):
self.assertIn('reservation_id', response)
reservation_id = response['reservation_id']
self.assertNotIn(reservation_id, ['', None])
# Assert that the reservation_id itself has the expected format
self.assertRegex(reservation_id, 'r-[0-9a-zA-Z]{8}')
# Create 1 more server, which should not return a reservation_id
server = self._build_minimal_create_server_request()

@ -36,21 +36,25 @@ class SupportDirectIOTestCase(test.NoDBTestCase):
self.einval.errno = errno.EINVAL
self.enoent = OSError()
self.enoent.errno = errno.ENOENT
self.test_path = os.path.join('.', '.directio.test')
self.test_path = os.path.join('.', '.directio.test.abc123')
self.io_flags = os.O_CREAT | os.O_WRONLY | os.O_DIRECT
open_patcher = mock.patch('os.open')
write_patcher = mock.patch('os.write')
close_patcher = mock.patch('os.close')
unlink_patcher = mock.patch('os.unlink')
random_string_patcher = mock.patch('nova.utils.generate_random_string',
return_value='abc123')
self.addCleanup(open_patcher.stop)
self.addCleanup(write_patcher.stop)
self.addCleanup(close_patcher.stop)
self.addCleanup(unlink_patcher.stop)
self.addCleanup(random_string_patcher.stop)
self.mock_open = open_patcher.start()
self.mock_write = write_patcher.start()
self.mock_close = close_patcher.start()
self.mock_unlink = unlink_patcher.start()
random_string_patcher.start()
def test_supports_direct_io(self):
self.mock_open.return_value = 3

@ -2435,6 +2435,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(0, len(cfg.cputune.vcpupin))
self.assertIsNone(cfg.cpu.numa)
@mock.patch('nova.privsep.utils.supports_direct_io',
new=mock.Mock(return_value=True))
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_no_fit(self, is_able):
@ -2686,6 +2688,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertEqual(0, len(cfg.cputune.vcpupin))
self.assertIsNone(cfg.cpu.numa)
@mock.patch('nova.privsep.utils.supports_direct_io',
new=mock.Mock(return_value=True))
@mock.patch.object(
host.Host, "is_cpu_control_policy_capable", return_value=True)
def test_get_guest_config_numa_host_instance_2pci_no_fit(self, is_able):

@ -244,9 +244,13 @@ def ssh_execute(dest, *cmd, **kwargs):
def generate_uid(topic, size=8):
random_string = generate_random_string(size)
return '%s-%s' % (topic, random_string)
def generate_random_string(size=8):
characters = '01234567890abcdefghijklmnopqrstuvwxyz'
choices = [random.choice(characters) for _x in range(size)]
return '%s-%s' % (topic, ''.join(choices))
return ''.join([random.choice(characters) for _x in range(size)])
# Default symbols to use for passwords. Avoids visually confusing characters.