VMware: Handle concurrent registrations of the VC extension

During initialization, the Nova compute driver checks whether a
vCenter extension with key 'org.openstack.compute' exists and if
not, it registers one. This is a race condition. If multiple
services try to register the same extension, only one of them
will succeed. The fix is to catch InvalidArgument fault from
vSphere API and ignore the exception.

Change-Id: I92c24709a2f55b601c31a31b9e748f19e7e31984
Closes-Bug: #1704952
This commit is contained in:
Radoslav Gerganov 2017-07-18 11:18:42 +03:00 committed by Chris Dent
parent 100a194ab1
commit 46c7fa492f
2 changed files with 26 additions and 7 deletions

View File

@ -2055,6 +2055,18 @@ class VMwareAPIVMTestCase(test.NoDBTestCase,
'find_extension',
constants.EXTENSION_KEY)
def test_register_extension_concurrent(self):
def fake_call_method(module, method, *args, **kwargs):
if method == "find_extension":
return None
elif method == "register_extension":
raise vexc.VimFaultException(['InvalidArgument'], 'error')
else:
raise Exception()
with (mock.patch.object(
self.conn._session, '_call_method', fake_call_method)):
self.conn._register_openstack_extension()
def test_list_instances(self):
instances = self.conn.list_instances()
self.assertEqual(0, len(instances))

View File

@ -183,16 +183,23 @@ class VMwareVCDriver(driver.ComputeDriver):
def _register_openstack_extension(self):
# Register an 'OpenStack' extension in vCenter
LOG.debug('Registering extension %s with vCenter',
constants.EXTENSION_KEY)
os_extension = self._session._call_method(vim_util, 'find_extension',
constants.EXTENSION_KEY)
if os_extension is None:
LOG.debug('Extension does not exist. Registering type %s.',
constants.EXTENSION_TYPE_INSTANCE)
self._session._call_method(vim_util, 'register_extension',
constants.EXTENSION_KEY,
constants.EXTENSION_TYPE_INSTANCE)
try:
self._session._call_method(vim_util, 'register_extension',
constants.EXTENSION_KEY,
constants.EXTENSION_TYPE_INSTANCE)
LOG.info('Registered extension %s with vCenter',
constants.EXTENSION_KEY)
except vexc.VimFaultException as e:
with excutils.save_and_reraise_exception() as ctx:
if 'InvalidArgument' in e.fault_list:
LOG.debug('Extension %s already exists.',
constants.EXTENSION_KEY)
ctx.reraise = False
else:
LOG.debug('Extension %s already exists.', constants.EXTENSION_KEY)
def cleanup(self, context, instance, network_info, block_device_info=None,
destroy_disks=True, migrate_data=None, destroy_vifs=True):