summaryrefslogtreecommitdiff
path: root/oslo_vmware/api.py
diff options
context:
space:
mode:
authorVipin Balachandran <vbala@vmware.com>2015-01-09 19:20:41 +0530
committerVipin Balachandran <vbala@vmware.com>2015-01-20 15:15:14 +0530
commita229faf8ba59724a4fda3f37d5a7473376f93d9c (patch)
tree3b616e1cd7b8ec04427b3b4fe1df916077dd4a7f /oslo_vmware/api.py
parent2df3a6200ab5f87dc01a809ae31329087ff87b4d (diff)
downloadoslo-vmware-a229faf8ba59724a4fda3f37d5a7473376f93d9c.tar.gz
Fix race during session creation
Concurrent VIM API invocations after session expiration would result in concurrent login attempts. In such cases, if a login attempt is made after a successful one, it would result in InvalidLogin. This is because vCenter server won't allow login within an active session. On the other hand, if two or more login attempts reach vCenter at the same, it would result in session leak-- the last one returned overwrite any of the previous sessions. This patch prevents the race condition by making session creation synchronized and checking for an active session before login attempt. We can also remove the call to terminate previous session after login since a login is attempted only if there is no active session. Change-Id: Ib4ca3553ce14c80ab722092907d797767072741c Closes-Bug: #1409014
Diffstat (limited to 'oslo_vmware/api.py')
-rw-r--r--oslo_vmware/api.py30
1 files changed, 10 insertions, 20 deletions
diff --git a/oslo_vmware/api.py b/oslo_vmware/api.py
index 61886fa..8f393ab 100644
--- a/oslo_vmware/api.py
+++ b/oslo_vmware/api.py
@@ -23,6 +23,7 @@ in case of connection problems or server API call overload.
import logging
+from oslo_concurrency import lockutils
import six
from oslo.utils import excutils
@@ -211,15 +212,23 @@ class VMwareAPISession(object):
return self._pbm
@RetryDecorator(exceptions=(exceptions.VimConnectionException,))
+ @lockutils.synchronized('oslo_vmware_api_lock')
def _create_session(self):
"""Establish session with the server."""
+ # Another thread might have created the session while the current one
+ # was waiting for the lock.
+ if self._session_id and self.is_current_session_active():
+ LOG.debug("Current session: %s is active.",
+ _trunc_id(self._session_id))
+ return
+
session_manager = self.vim.service_content.sessionManager
# Login and create new session with the server for making API calls.
LOG.debug("Logging in with username = %s.", self._server_username)
session = self.vim.Login(session_manager,
userName=self._server_username,
password=self._server_password)
- prev_session_id, self._session_id = self._session_id, session.key
+ self._session_id = session.key
# We need to save the username in the session since we may need it
# later to check active session. The SessionIsActive method requires
# the username parameter to be exactly same as that in the session
@@ -230,25 +239,6 @@ class VMwareAPISession(object):
"%s."),
_trunc_id(self._session_id))
- # Terminate the previous session (if exists) for preserving sessions
- # as there is a limit on the number of sessions we can have.
- if prev_session_id:
- try:
- LOG.info(_LI("Terminating the previous session with ID = %s"),
- _trunc_id(prev_session_id))
- self.vim.TerminateSession(session_manager,
- sessionId=[prev_session_id])
- except Exception:
- # This exception is something we can live with. It is
- # just an extra caution on our side. The session might
- # have been cleared already. We could have made a call to
- # SessionIsActive, but that is an overhead because we
- # anyway would have to call TerminateSession.
- LOG.warn(_LW("Error occurred while terminating the previous "
- "session with ID = %s."),
- _trunc_id(prev_session_id),
- exc_info=True)
-
# Set PBM client cookie.
if self._pbm is not None:
self._pbm.set_soap_cookie(self._vim.get_http_cookie())