Ignore IOError when creating 'console.log'

In 'd4e6bd8', and later refined in 'ec6ed24c', an issue with the the
Quobyte CI was resolved by ensuring that the 'console.log' file is
always created, even when libvirt's 'dynamic_ownership' config option
is set to '0'. However, attempting to take ownership of this file can
cause issues when 'dynamic_ownership' is set to '1' and a user attempts
to reschedule an instance to a host where it was previously located. In
this case, the permissions on the file have already been co-opted by
libvirt, and attempting to change them results in an IOError.

The easiest fix for this is to simply ignore the IOError, as the file
already exists and libvirt has set correct permissions already. This is
what do here. A longer term fix would be to avoid changing the
permissions only for the offending Quobytes block devices, but this is
likely not backportable and will be done in a follow-up fix.

Change-Id: I353afd57be207330757580447a1b606c7b9b7c09
Partial-bug: #1634282
Related-bug: #1597644
Related-bug: #1609298
(cherry picked from commit 1848860fd4)
This commit is contained in:
Stephen Finucane 2016-11-02 12:43:35 +00:00 committed by Sylvain Bauza
parent c2c91ce445
commit a96092d0e4
2 changed files with 44 additions and 1 deletions

View File

@ -10851,6 +10851,42 @@ class LibvirtConnTestCase(test.NoDBTestCase):
drvr._create_swap('/dev/something', 1)
def test_ensure_console_log_for_instance_pass(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
with test.nested(
mock.patch.object(drvr, '_get_console_log_path'),
mock.patch.object(fake_libvirt_utils, 'file_open')
) as (mock_path, mock_open):
drvr._ensure_console_log_for_instance(mock.ANY)
mock_path.assert_called_once()
mock_open.assert_called_once()
def test_ensure_console_log_for_instance_pass_w_permissions(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
with test.nested(
mock.patch.object(drvr, '_get_console_log_path'),
mock.patch.object(fake_libvirt_utils, 'file_open',
side_effect=IOError(errno.EPERM, 'exc'))
) as (mock_path, mock_open):
drvr._ensure_console_log_for_instance(mock.ANY)
mock_path.assert_called_once()
mock_open.assert_called_once()
def test_ensure_console_log_for_instance_fail(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
with test.nested(
mock.patch.object(drvr, '_get_console_log_path'),
mock.patch.object(fake_libvirt_utils, 'file_open',
side_effect=IOError(errno.EREMOTE, 'exc'))
) as (mock_path, mock_open):
self.assertRaises(
IOError,
drvr._ensure_console_log_for_instance,
mock.ANY)
def test_get_console_output_file(self):
fake_libvirt_utils.files['console.log'] = '01234567890'

View File

@ -2867,7 +2867,14 @@ class LibvirtDriver(driver.ComputeDriver):
console_file = self._get_console_log_path(instance)
LOG.debug('Ensure instance console log exists: %s', console_file,
instance=instance)
libvirt_utils.file_open(console_file, 'a').close()
try:
libvirt_utils.file_open(console_file, 'a').close()
# NOTE(sfinucan): We can safely ignore permission issues here and
# assume that it is libvirt that has taken ownership of this file.
except IOError as ex:
if ex.errno != errno.EPERM:
raise
LOG.debug('Console file already exists: %s.', console_file)
@staticmethod
def _get_disk_config_path(instance, suffix=''):