Merge "Upversioning platform horizon to master"

This commit is contained in:
Zuul 2019-03-15 15:48:07 +00:00 committed by Gerrit Code Review
commit a5710beaf3
28 changed files with 111 additions and 1562 deletions

View File

@ -25,10 +25,6 @@ openstack-murano-doc
python2-muranoclient
python-muranoclient-doc
# openstack-murano-ui
openstack-murano-ui
openstack-murano-ui-doc
# openstack-ironic
openstack-ironic-common
openstack-ironic-api
@ -162,9 +158,6 @@ rabbitmq-server-config
# python-openstackclient
python2-openstackclient
# python-django-openstack-auth
python2-django-openstack-auth
# python-wsme
python2-wsme

View File

@ -15,7 +15,6 @@ openstack-neutron-wheels
openstack-nova-wheels
python-cinderclient-wheels
python-django-horizon-wheels
python-django-openstack-auth-wheels
python-glanceclient-wheels
python-gnocchiclient-wheels
python-ironicclient-wheels

View File

@ -1,6 +1,5 @@
openstack/openstack-murano
openstack/python-muranoclient
openstack/openstack-murano-ui
openstack/openstack-ironic
openstack/python-ironicclient
openstack/python-magnumclient
@ -37,7 +36,6 @@ openstack/python-neutronclient
openstack/python-nova
openstack/python-novaclient
openstack/python-openstackdocstheme
openstack/python-oslo-concurrency
openstack/python-oslo-service
openstack/python-oslo-messaging
openstack/python-pankoclient
@ -45,7 +43,6 @@ openstack/rabbitmq-server
openstack/rabbitmq-server-config
openstack/python-openstackclient
openstack/python-openstacksdk
openstack/python-django-openstack-auth
openstack/python-wsme
openstack/distributedcloud
openstack/distributedcloud-client

View File

@ -1 +0,0 @@
TIS_PATCH_VER=5

View File

@ -1,25 +0,0 @@
From bb0de73901801c5919041fa73699d6cc5e14495a Mon Sep 17 00:00:00 2001
From: Scott Little <scott.little@windriver.com>
Date: Wed, 8 Nov 2017 13:52:34 -0500
Subject: [PATCH] Update package versioning for TIS format
---
SPECS/python-django-openstack-auth.spec | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/SPECS/python-django-openstack-auth.spec b/SPECS/python-django-openstack-auth.spec
index 7ac6008..fd06bbc 100644
--- a/SPECS/python-django-openstack-auth.spec
+++ b/SPECS/python-django-openstack-auth.spec
@@ -7,7 +7,7 @@
Name: python-django-openstack-auth
Version: 3.6.1
-Release: 1%{?dist}
+Release: 1.el7%{?_tis_dist}.%{tis_patch_ver}
Summary: Django authentication backend for OpenStack Keystone
License: BSD
--
1.8.3.1

View File

@ -1,36 +0,0 @@
From 70ecee3d9c45b338a03e32cf59485ada4804f24d Mon Sep 17 00:00:00 2001
From: Kam Nasim <kam.nasim@windriver.com>
Date: Wed, 8 Nov 2017 14:14:54 -0500
Subject: [PATCH] remove rpm build-time TOX tests
---
SPECS/python-django-openstack-auth.spec | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/SPECS/python-django-openstack-auth.spec b/SPECS/python-django-openstack-auth.spec
index fd06bbc..2ab88bc 100644
--- a/SPECS/python-django-openstack-auth.spec
+++ b/SPECS/python-django-openstack-auth.spec
@@ -129,7 +129,7 @@ find . -name "django.po" -exec rm -f '{}' \;
%endif
# generate html docs
-PYTHONPATH=.:$PYTHONPATH sphinx-build doc/source html
+#PYTHONPATH=.:$PYTHONPATH sphinx-build doc/source html
%install
%{__python2} setup.py install --skip-build --root %{buildroot}
@@ -150,10 +150,6 @@ rm -rf %{buildroot}/%{python3_sitelib}/openstack_auth/tests
%endif
-%check
-export PYTHONPATH=$PYTHONPATH
-%{__python} openstack_auth/tests/run_tests.py
-
%files -n python2-django-openstack-auth -f django.lang
%license LICENSE
%dir %{python_sitelib}/openstack_auth
--
1.8.3.1

View File

@ -1,47 +0,0 @@
From 4e7ae98c2ffb058711338161a283ce04e47d6bc9 Mon Sep 17 00:00:00 2001
From: Kam Nasim <kam.nasim@windriver.com>
Date: Wed, 8 Nov 2017 16:54:56 -0500
Subject: [PATCH] meta to roll in pike rebase patches
---
SPECS/python-django-openstack-auth.spec | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/SPECS/python-django-openstack-auth.spec b/SPECS/python-django-openstack-auth.spec
index 3c65c20..6bd7088 100644
--- a/SPECS/python-django-openstack-auth.spec
+++ b/SPECS/python-django-openstack-auth.spec
@@ -14,6 +14,9 @@ License: BSD
URL: http://pypi.python.org/pypi/django_openstack_auth/
Source0: https://tarballs.openstack.org/django_openstack_auth/django_openstack_auth-%{upstream_version}.tar.gz
+# WRS Patches
+Patch0001: 0001-Pike-rebase-for-openstack-auth.patch
+
BuildArch: noarch
BuildRequires: git
@@ -45,6 +48,11 @@ BuildRequires: python-mox3
BuildRequires: python-mock
BuildRequires: python-testscenarios
+#WRS: Need these for build_sphinx
+BuildRequires: tsconfig
+BuildRequires: python2-pycodestyle
+BuildRequires: python2-oslo-concurrency
+
Requires: python-django
BuildRequires: python-django
@@ -107,7 +115,7 @@ Keystone V2 API.
%prep
-%autosetup -n %{pypi_name}-%{upstream_version} -S git
+%autosetup -n %{pypi_name}-%{upstream_version} -S git -p1
# Remove the requirements file so that pbr hooks don't add it
--
1.8.3.1

View File

@ -1,24 +0,0 @@
From 5dc546e81e87d78f97af2fd734d41119faa866fe Mon Sep 17 00:00:00 2001
From: Kam Nasim <kam.nasim@windriver.com>
Date: Mon, 12 Feb 2018 11:04:17 -0500
Subject: [PATCH] meta patch for disable-token-validation-per-auth-request
---
SPECS/python-django-openstack-auth.spec | 1 +
1 file changed, 1 insertion(+)
diff --git a/SPECS/python-django-openstack-auth.spec b/SPECS/python-django-openstack-auth.spec
index 4960ab2..3a462de 100644
--- a/SPECS/python-django-openstack-auth.spec
+++ b/SPECS/python-django-openstack-auth.spec
@@ -16,6 +16,7 @@ Source0: https://tarballs.openstack.org/django_openstack_auth/django_open
# WRS Patches
Patch0001: 0001-Pike-rebase-for-openstack-auth.patch
+Patch0002: 0002-disable-token-validation-per-auth-request.patch
BuildArch: noarch
--
1.8.3.1

View File

@ -1,25 +0,0 @@
From ac0df9c1b8cddc4bb5a06d7e1226144d3f85e83d Mon Sep 17 00:00:00 2001
From: Kam Nasim <kam.nasim@windriver.com>
Date: Wed, 14 Feb 2018 10:39:33 -0500
Subject: [PATCH] meta patch for
cache-authorized-tenants-in-cookie-to-improve-performance
---
SPECS/python-django-openstack-auth.spec | 1 +
1 file changed, 1 insertion(+)
diff --git a/SPECS/python-django-openstack-auth.spec b/SPECS/python-django-openstack-auth.spec
index 3a462de..21e4bde 100644
--- a/SPECS/python-django-openstack-auth.spec
+++ b/SPECS/python-django-openstack-auth.spec
@@ -17,6 +17,7 @@ Source0: https://tarballs.openstack.org/django_openstack_auth/django_open
# WRS Patches
Patch0001: 0001-Pike-rebase-for-openstack-auth.patch
Patch0002: 0002-disable-token-validation-per-auth-request.patch
+Patch0003: 0003-cache-authorized-tenants-in-cookie-to-improve-performance.patch
BuildArch: noarch
--
1.8.3.1

View File

@ -1,24 +0,0 @@
From 186e684a33b3db1c5a5fc010cdb63b459351fcb7 Mon Sep 17 00:00:00 2001
From: Kam Nasim <kam.nasim@windriver.com>
Date: Wed, 30 May 2018 11:28:49 -0400
Subject: [PATCH] meta patch for distributed keystone
---
SPECS/python-django-openstack-auth.spec | 1 +
1 file changed, 1 insertion(+)
diff --git a/SPECS/python-django-openstack-auth.spec b/SPECS/python-django-openstack-auth.spec
index 21e4bde..f925d87 100644
--- a/SPECS/python-django-openstack-auth.spec
+++ b/SPECS/python-django-openstack-auth.spec
@@ -18,6 +18,7 @@ Source0: https://tarballs.openstack.org/django_openstack_auth/django_open
Patch0001: 0001-Pike-rebase-for-openstack-auth.patch
Patch0002: 0002-disable-token-validation-per-auth-request.patch
Patch0003: 0003-cache-authorized-tenants-in-cookie-to-improve-performance.patch
+Patch0004: 0004-Distributed-Keystone.patch
BuildArch: noarch
--
1.8.3.1

View File

@ -1,24 +0,0 @@
From c047aecf35d067390d0e80e0149725c3031a19c3 Mon Sep 17 00:00:00 2001
From: Tyler Smith <tyler.smith@windriver.com>
Date: Fri, 29 Jun 2018 20:07:09 -0500
Subject: [PATCH 1/1] [PATCH] meta patch for distributed keystone fix
---
SPECS/python-django-openstack-auth.spec | 1 +
1 file changed, 1 insertion(+)
diff --git a/SPECS/python-django-openstack-auth.spec b/SPECS/python-django-openstack-auth.spec
index 90b4692..89acf21 100644
--- a/SPECS/python-django-openstack-auth.spec
+++ b/SPECS/python-django-openstack-auth.spec
@@ -19,6 +19,7 @@ Patch0001: 0001-Pike-rebase-for-openstack-auth.patch
Patch0002: 0002-disable-token-validation-per-auth-request.patch
Patch0003: 0003-cache-authorized-tenants-in-cookie-to-improve-performance.patch
Patch0004: 0004-Distributed-Keystone.patch
+Patch0005: fix_for_dc_region_switching.patch
BuildArch: noarch
--
2.7.4

View File

@ -1,58 +0,0 @@
From 1a5349cf73177d155a3309737635bc1ae22ae051 Mon Sep 17 00:00:00 2001
From: Don Penney <don.penney@windriver.com>
Date: Mon, 17 Dec 2018 09:16:20 -0600
Subject: [PATCH] Build python wheel
---
SPECS/python-django-openstack-auth.spec | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/SPECS/python-django-openstack-auth.spec b/SPECS/python-django-openstack-auth.spec
index 89acf21..5e9e8e0 100644
--- a/SPECS/python-django-openstack-auth.spec
+++ b/SPECS/python-django-openstack-auth.spec
@@ -39,6 +39,8 @@ Summary: Django authentication backend for OpenStack Keystone
%{?python_provide:%python_provide python2-django-openstack-auth}
BuildRequires: python2-devel
BuildRequires: python-setuptools
+BuildRequires: python2-pip
+BuildRequires: python2-wheel
BuildRequires: python-sphinx
BuildRequires: python-keystoneclient
BuildRequires: python-iso8601
@@ -135,6 +137,7 @@ find . -name "django.po" -exec rm -f '{}' \;
%{__python} setup.py build
+%py2_build_wheel
%if 0%{?with_python3}
%{__python3} setup.py build
@@ -145,6 +148,8 @@ find . -name "django.po" -exec rm -f '{}' \;
%install
%{__python2} setup.py install --skip-build --root %{buildroot}
+mkdir -p $RPM_BUILD_ROOT/wheels
+install -m 644 dist/*.whl $RPM_BUILD_ROOT/wheels/
cp -r openstack_auth/locale %{buildroot}/%{python_sitelib}/openstack_auth
@@ -189,6 +194,15 @@ rm -rf %{buildroot}/%{python3_sitelib}/openstack_auth/tests
%{python3_sitelib}/%{pypi_name}-*.egg-info
%endif
+%package wheels
+Summary: %{name} wheels
+
+%description wheels
+Contains python wheels for %{name}
+
+%files wheels
+/wheels/*
+
%changelog
* Tue Jun 12 2018 RDO <dev@lists.rdoproject.org> 3.6.1-1
- Update to 3.6.1
--
1.8.3.1

View File

@ -1,8 +0,0 @@
0001-Update-package-versioning-for-TIS-format.patch
0002-remove-rpm-build-time-TOX-tests.patch
0003-meta-roll-in-TIS-patches.patch
0004-meta-disable-token-validation-per-auth-req.patch
0005-meta-cache-authorized-tenants-in-cookie-to-improve-performance.patch
0006-meta-Distributed-Keystone.patch
0007-meta-patch-for-distributed-keystone-fix.patch
0008-Build-python-wheel.patch

View File

@ -1,495 +0,0 @@
From b2e9d78e5385ad7c67b4ce2ef33b64206e5ccf6d Mon Sep 17 00:00:00 2001
From: Kam Nasim <kam.nasim@windriver.com>
Date: Wed, 25 Jan 2017 11:58:56 -0500
Subject: [PATCH] Pike rebase for openstack auth
Squashes in the following Titanium patches (some patches have been
upstreamed and not mentioned here):
- User lockout feature (Author: Aly Nathoo)
- Add client ip to login / lockout activies and logging for user lockout
(Author: David Balme)
- Optimize keystone authentication requests during user lockout
(Author: Kam Nasim)
- Stop user lockout increment when Keystone is unavailable
(Author: David Balme)
- Change default region for openstack auth to local Horizon's region
(Author: Tyler Smith)
- Refactor user lockout for multiple browser sessions, and fix horizon
session timeout issue (Author: Giao Le)
- Validate token before initiating session to prevent invalid token
issues (Author: Giao Le)
---
openstack_auth/backend.py | 4 +
openstack_auth/forms.py | 35 ++++--
openstack_auth/plugin/base.py | 7 +-
openstack_auth/user.py | 15 +++
openstack_auth/utils.py | 242 +++++++++++++++++++++++++++++++++++++++++-
openstack_auth/views.py | 12 ++-
6 files changed, 302 insertions(+), 13 deletions(-)
diff --git a/openstack_auth/backend.py b/openstack_auth/backend.py
index dae603a..cd15ca8 100644
--- a/openstack_auth/backend.py
+++ b/openstack_auth/backend.py
@@ -170,6 +170,10 @@ class KeystoneBackend(object):
region_name = id_endpoint['region']
break
+ local_region = getattr(settings, 'REGION_NAME', None)
+ if local_region:
+ region_name = local_region
+
interface = getattr(settings, 'OPENSTACK_ENDPOINT_TYPE', 'public')
endpoint, url_fixed = utils.fix_auth_url_version_prefix(
diff --git a/openstack_auth/forms.py b/openstack_auth/forms.py
index c7d0c51..90e281b 100644
--- a/openstack_auth/forms.py
+++ b/openstack_auth/forms.py
@@ -24,7 +24,6 @@ from django.views.decorators.debug import sensitive_variables
from openstack_auth import exceptions
from openstack_auth import utils
-
LOG = logging.getLogger(__name__)
@@ -118,6 +117,7 @@ class Login(django_auth_forms.AuthenticationForm):
@sensitive_variables()
def clean(self):
+ global failedUserLogins
default_domain = getattr(settings,
'OPENSTACK_KEYSTONE_DEFAULT_DOMAIN',
'Default')
@@ -131,6 +131,14 @@ class Login(django_auth_forms.AuthenticationForm):
return self.cleaned_data
try:
+ # assess the lockout status for this user.
+ # If this user is already locked out then
+ # do not attempt to authenticate as that is
+ # a redundant hit on Keystone and web proxy.
+ lockedout = utils.check_user_lockout(username)
+ if lockedout:
+ raise forms.ValidationError("user currently locked out.")
+
self.user_cache = authenticate(request=self.request,
username=username,
password=password,
@@ -142,14 +150,27 @@ class Login(django_auth_forms.AuthenticationForm):
'remote_ip': utils.get_client_ip(self.request)
}
LOG.info(msg)
+
+ # since this user logged in successfully, clear its
+ # lockout status
+ utils.clear_user_lockout(username)
+
+ # handle user login
+ utils.handle_user_login(username, password)
+
except exceptions.KeystoneAuthException as exc:
- msg = 'Login failed for user "%(username)s", remote address '\
- '%(remote_ip)s.' % {
- 'username': username,
- 'remote_ip': utils.get_client_ip(self.request)
- }
- LOG.warning(msg)
+ if getattr(exc,"invalidCredentials", False):
+ msg = 'Login failed for user "%(username)s", remote address '\
+ '%(remote_ip)s.' % {
+ 'username': username,
+ 'remote_ip': utils.get_client_ip(self.request)
+ }
+ LOG.warning(msg)
+ utils.add_user_lockout(username)
+ LOG.warning("Invalid password entered for User %s "
+ "in web service." % username)
raise forms.ValidationError(exc)
+
if hasattr(self, 'check_for_test_cookie'): # Dropped in django 1.7
self.check_for_test_cookie()
return self.cleaned_data
diff --git a/openstack_auth/plugin/base.py b/openstack_auth/plugin/base.py
index f1aff52..bbdaddc 100644
--- a/openstack_auth/plugin/base.py
+++ b/openstack_auth/plugin/base.py
@@ -95,7 +95,7 @@ class BasePlugin(object):
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure):
- msg = _('Unable to retrieve authorized projects.')
+ msg = 'Unable to retrieve authorized projects.'
raise exceptions.KeystoneAuthException(msg)
def list_domains(self, session, auth_plugin, auth_ref=None):
@@ -132,7 +132,10 @@ class BasePlugin(object):
keystone_exceptions.Forbidden,
keystone_exceptions.NotFound) as exc:
LOG.debug(str(exc))
- raise exceptions.KeystoneAuthException(_('Invalid credentials.'))
+ authException = exceptions.KeystoneAuthException(
+ _('Invalid credentials.'))
+ authException.invalidCredentials = True
+ raise authException
except (keystone_exceptions.ClientException,
keystone_exceptions.AuthorizationFailure) as exc:
msg = _("An error occurred authenticating. "
diff --git a/openstack_auth/user.py b/openstack_auth/user.py
index 063648b..c6f616c 100644
--- a/openstack_auth/user.py
+++ b/openstack_auth/user.py
@@ -253,6 +253,9 @@ class User(models.AbstractBaseUser, models.AnonymousUser):
# Required by AbstractBaseUser
self.password = None
+ # WRS: additional check to validate token prior to using
+ self.validate_token = False
+
def __unicode__(self):
return self.username
@@ -305,6 +308,18 @@ class User(models.AbstractBaseUser, models.AnonymousUser):
A default margin can be set by the TOKEN_TIMEOUT_MARGIN in the
django settings.
"""
+ # WRS: validate token
+ if not self.validate_token:
+ try:
+ utils.validate_token(
+ auth_url=self.endpoint,
+ auth_token=self.unscoped_token,
+ token=self.token)
+ except (keystone_exceptions.ClientException,
+ keystone_exceptions.AuthorizationFailure):
+ self.token.expires = None
+ self.validate_token = True
+
return (self.token is not None and
utils.is_token_valid(self.token, margin))
diff --git a/openstack_auth/utils.py b/openstack_auth/utils.py
index cac0d7a..1b35592 100644
--- a/openstack_auth/utils.py
+++ b/openstack_auth/utils.py
@@ -12,7 +12,13 @@
# limitations under the License.
import datetime
+import errno
+import fcntl
+import keyring
import logging
+import os
+import time
+import time
import re
from django.conf import settings
@@ -25,6 +31,8 @@ from keystoneauth1 import session
from keystoneauth1 import token_endpoint
from keystoneclient.v2_0 import client as client_v2
from keystoneclient.v3 import client as client_v3
+from oslo_concurrency import lockutils
+from oslo_serialization import jsonutils
from six.moves.urllib import parse as urlparse
@@ -357,6 +365,14 @@ def get_token_auth_plugin(auth_url, token, project_id=None, domain_name=None):
reauthenticate=False)
+def validate_token(auth_url, auth_token, token):
+ auth_url, _ = fix_auth_url_version_prefix(auth_url)
+ auth = token_endpoint.Token(auth_url, auth_token)
+ sess = get_session()
+ client = get_keystone_client().Client(session=sess, auth=auth)
+ _ = client.tokens.validate(token)
+
+
def get_project_list(*args, **kwargs):
is_federated = kwargs.get('is_federated', False)
sess = kwargs.get('session') or get_session()
@@ -489,9 +505,10 @@ def get_admin_permissions():
return {get_role_permission(role) for role in get_admin_roles()}
+
def get_client_ip(request):
"""Return client ip address using SECURE_PROXY_ADDR_HEADER variable.
-
+ If not present then consider using HTTP_X_FORWARDED_FOR from.
If not present or not defined on settings then REMOTE_ADDR is used.
:param request: Django http request object.
@@ -508,7 +525,12 @@ def get_client_ip(request):
_SECURE_PROXY_ADDR_HEADER,
request.META.get('REMOTE_ADDR')
)
- return request.META.get('REMOTE_ADDR')
+ else:
+ x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
+ if x_forwarded_for:
+ return (x_forwarded_for.split(',')[0])
+ else:
+ return request.META.get('REMOTE_ADDR')
def store_initial_k2k_session(auth_url, request, scoped_auth_ref,
@@ -560,3 +582,219 @@ def store_initial_k2k_session(auth_url, request, scoped_auth_ref,
request.session['k2k_base_unscoped_token'] =\
unscoped_auth_ref.auth_token
request.session['k2k_auth_url'] = auth_url
+
+
+def __log_cache_error__(op, fn, ex):
+ msg = ("unable to %(op)s cache file %(fn)s due to %(ex)s") %\
+ {'op': op, 'fn': fn, 'ex': ex}
+ LOG.warning(msg)
+
+
+def __lock_cache__(cache_file):
+ try:
+ f = open(cache_file, "r+")
+ except Exception as ex:
+ __log_cache_error__("open", cache_file, ex)
+ raise
+
+ try:
+ fcntl.flock(f.fileno(), fcntl.LOCK_EX)
+ except Exception as ex:
+ __log_cache_error__("lock", f.name, ex)
+ raise
+
+ return f
+
+
+def __write_cache__(f, filedata):
+ try:
+ f.seek(0, 0)
+ f.truncate()
+ f.write(jsonutils.dumps(filedata))
+ except Exception as ex:
+ __log_cache_error__("write", f.name, ex)
+
+
+def __read_cache__(f, default=[]):
+ try:
+ f.seek(0, 0)
+ return jsonutils.loads(f.read())
+ except Exception as ex:
+ __log_cache_error__("read", f.name, ex)
+
+ return default
+
+
+def __create_cache__(fname, default=[]):
+ try:
+ with open(__file__, "r") as l:
+ fcntl.flock(l.fileno(), fcntl.LOCK_EX)
+ if not os.path.exists(fname):
+ with open(fname, "w") as f:
+ __write_cache__(f, default)
+
+ except Exception as ex:
+ __log_cache_error__("create", fname, ex)
+
+
+# Track failed logins
+# Keep an array of failedUserLogins
+# failedUserLogins : username NumFailedLogins LockoutTime
+# if a login fails due to invalid password (username is ok),
+# add username to array and increment NumFailedLogins
+# if a login succeeds
+# look up username in failedUserLogins, if found
+# if NumFailedLogins > 3, check LockoutTime
+# if CurrentTime - LockoutTime < 5min then
+# fail login
+# else
+# remove username from failedUserLogins
+# else
+# remove username from failedUserLogins, let user log in
+
+FAILED_LOGINS_CACHE_FILE = "/tmp/.hacache"
+FAILED_LOGINS_NAME_INDEX = 0
+FAILED_LOGINS_COUNT_INDEX = 1
+FAILED_LOGINS_TIME_INDEX = 2
+
+lockout_tuple = (settings.LOCKOUT_PERIOD_SEC, settings.LOCKOUT_RETRIES_NUM)
+
+if not os.path.exists(FAILED_LOGINS_CACHE_FILE):
+ __create_cache__(FAILED_LOGINS_CACHE_FILE)
+
+
+def check_user_lockout(username):
+ try:
+ with __lock_cache__(FAILED_LOGINS_CACHE_FILE) as f:
+ failedUserLogins = __read_cache__(f)
+ (lockout_period_sec, lockout_retries_num) = lockout_tuple
+ for i, user in enumerate(failedUserLogins):
+ if user[FAILED_LOGINS_NAME_INDEX] != username:
+ continue
+ if user[FAILED_LOGINS_COUNT_INDEX] >= lockout_retries_num:
+ delta = time.time() - user[FAILED_LOGINS_TIME_INDEX]
+ if delta < lockout_period_sec:
+ msg = ("Cannot login/authenticate -"
+ " user \"%(username)s\" locked out." % \
+ {'username': username})
+ LOG.info(msg)
+ return True
+ break
+ except:
+ pass
+
+ return False
+
+
+def add_user_lockout(username):
+ try:
+ with __lock_cache__(FAILED_LOGINS_CACHE_FILE) as f:
+ failedUserLogins = __read_cache__(f)
+ (lockout_period_sec, lockout_retries_num) = lockout_tuple
+ for user in failedUserLogins:
+ if user[FAILED_LOGINS_NAME_INDEX] == username:
+ user[FAILED_LOGINS_COUNT_INDEX] += 1
+ if user[FAILED_LOGINS_COUNT_INDEX] >= lockout_retries_num:
+ # user is now locked out, record the new time
+ user[FAILED_LOGINS_TIME_INDEX] = time.time()
+ LOG.warning("User %s is locked out of web service"
+ "- attempted login." % (username))
+ break
+ else:
+ failedUserLogins.append([username,1,0])
+ __write_cache__(f, failedUserLogins)
+ except:
+ pass
+
+
+def clear_user_lockout(username):
+ try:
+ with __lock_cache__(FAILED_LOGINS_CACHE_FILE) as f:
+ failedUserLogins = __read_cache__(f)
+ for i, user in enumerate(failedUserLogins):
+ if user[FAILED_LOGINS_NAME_INDEX] == username:
+ # clear the entry for this user
+ failedUserLogins[i] = None
+ failedUserLogins = [elem for elem in failedUserLogins if elem]
+ __write_cache__(f, failedUserLogins)
+ break
+ except:
+ pass
+
+
+# Manage user password using keyring service
+# 1. add user password to keyring service once
+# user logs in the first time
+# 2. delete user password from keyring service once
+# user logs out all sessions
+
+USER_LOGINS_CACHE_FILE = '/tmp/.hacache1'
+USER_LOGINS_NAME_INDEX = 0
+USER_LOGINS_COUNT_INDEX = 1
+USER_LOGINS_KEYRING = 'hakeyring'
+
+if not os.path.exists(USER_LOGINS_CACHE_FILE):
+ __create_cache__(USER_LOGINS_CACHE_FILE)
+
+
+def get_user_password(username):
+ # use CGCS for admin
+ service = 'CGCS' if username == 'admin' else USER_LOGINS_KEYRING
+ return keyring.get_password(service, username)
+
+
+def handle_user_login(username, password):
+ if username == 'admin':
+ return
+
+ try:
+ with __lock_cache__(USER_LOGINS_CACHE_FILE) as f:
+ logined = False
+ userLogins = __read_cache__(f)
+ for i, user in enumerate(userLogins):
+ if user[USER_LOGINS_NAME_INDEX] == username:
+ user[USER_LOGINS_COUNT_INDEX] += 1
+ logined = True
+ break
+ try:
+ old = keyring.get_password(USER_LOGINS_KEYRING, username)
+ if old and old != password:
+ keyring.delete_password(USER_LOGINS_KEYRING, username)
+ old = None
+ if not old:
+ keyring.set_password(USER_LOGINS_KEYRING, username,
+ password)
+ except (keyring.errors.PasswordSetError, RuntimeError):
+ LOG.warning("Failed to update keyring passord"
+ " for user %s" % username)
+
+ if not logined:
+ userLogins.append([username, 1])
+ __write_cache__(f, userLogins)
+ except:
+ LOG.warning("Failed to handle login for user %s" % username)
+
+
+def handle_user_logout(username):
+ if username == 'admin':
+ return
+
+ try:
+ with __lock_cache__(USER_LOGINS_CACHE_FILE) as f:
+ userLogins = __read_cache__(f)
+ for i, user in enumerate(userLogins):
+ if user[USER_LOGINS_NAME_INDEX] != username:
+ continue
+ user[USER_LOGINS_COUNT_INDEX] -= 1
+ if user[USER_LOGINS_COUNT_INDEX] == 0:
+ userLogins[i] = None
+ userLogins = [e for e in userLogins if e]
+ try:
+ keyring.delete_password(USER_LOGINS_KEYRING, username)
+ except keyring.errors.PasswordDeleteError:
+ LOG.warning("Failed to delete keyring passowrd"
+ " for user %s" % username)
+ __write_cache__(f, userLogins)
+ break
+ except:
+ LOG.warning("Failed to handle logout for user %s" % username)
diff --git a/openstack_auth/views.py b/openstack_auth/views.py
index 7ae3063..bf4aa99 100644
--- a/openstack_auth/views.py
+++ b/openstack_auth/views.py
@@ -130,6 +130,10 @@ def login(request, template_name=None, extra_context=None, **kwargs):
' in %s minutes') %
expiration_time).replace(':', ' Hours and ')
messages.warning(request, msg)
+
+ # WRS: add login user name to handle HORIZON session timeout
+ utils.set_response_cookie(res, 'login_user',
+ request.user.username)
return res
@@ -167,10 +171,14 @@ def logout(request, login_url=None, **kwargs):
see django.contrib.auth.views.logout_then_login extra parameters.
"""
- msg = 'Logging out user "%(username)s".' % \
- {'username': request.user.username}
+ msg = 'Logging out user "%(username)s", remote address %(remote_ip)s.' % \
+ {'username': request.user.username,
+ 'remote_ip': utils.get_client_ip(request)}
LOG.info(msg)
+ # handle user logout
+ utils.handle_user_logout(request.user.username)
+
""" Securely logs a user out. """
return django_auth_views.logout_then_login(request, login_url=login_url,
**kwargs)
--
1.8.3.1

View File

@ -1,28 +0,0 @@
From 3b6605b547bb27b272345b03797abc94a23469ab Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Mon, 12 Feb 2018 10:59:39 -0500
Subject: [PATCH] disable token validation per auth request
To prevent invalid tokens from being used, each request would previous
attempt a token validation request. This causes 2x AUTH requests to
Keystone which is affecting Host Swact/Lock and VM migration times
---
openstack_auth/user.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/openstack_auth/user.py b/openstack_auth/user.py
index c6f616c..f486bfa 100644
--- a/openstack_auth/user.py
+++ b/openstack_auth/user.py
@@ -254,7 +254,7 @@ class User(models.AbstractBaseUser, models.AnonymousUser):
self.password = None
# WRS: additional check to validate token prior to using
- self.validate_token = False
+ self.validate_token = True
def __unicode__(self):
return self.username
--
1.8.3.1

View File

@ -1,69 +0,0 @@
From b6724faf6f485f08584a7965bcd881d1f3b78f7c Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Wed, 14 Feb 2018 16:55:29 -0500
Subject: [PATCH] cache authorized tenants list in cookie to improve
performance
---
openstack_auth/utils.py | 9 +++++++++
openstack_auth/views.py | 17 +++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/openstack_auth/utils.py b/openstack_auth/utils.py
index 1b35592..9a55790 100644
--- a/openstack_auth/utils.py
+++ b/openstack_auth/utils.py
@@ -438,6 +438,15 @@ def set_response_cookie(response, cookie_name, cookie_value):
response.set_cookie(cookie_name, cookie_value, expires=expire_date)
+def delete_response_cookie(response, cookie_name):
+ """ Common function for deleting a cookie from the response.
+
+ Deletes the cookie of the given cookie_name. Fails silently
+ if cookie name doesn't exist
+ """
+ response.delete_cookie(cookie_name)
+
+
def get_endpoint_region(endpoint):
"""Common function for getting the region from endpoint.
diff --git a/openstack_auth/views.py b/openstack_auth/views.py
index bf4aa99..a9d84df 100644
--- a/openstack_auth/views.py
+++ b/openstack_auth/views.py
@@ -134,6 +134,15 @@ def login(request, template_name=None, extra_context=None, **kwargs):
# WRS: add login user name to handle HORIZON session timeout
utils.set_response_cookie(res, 'login_user',
request.user.username)
+
+ # WRS: Store project list to handle frequent requests to
+ # Keystone. Since the cookie is not removed on logout, we will
+ # do it here.
+ tenants = request.user.authorized_tenants
+ tenants = map(lambda x: x.to_dict(), tenants)
+ utils.delete_response_cookie(res, 'authorized_tenants')
+ utils.set_response_cookie(res, 'authorized_tenants', tenants)
+
return res
@@ -237,6 +246,14 @@ def switch(request, tenant_id, redirect_field_name=auth.REDIRECT_FIELD_NAME):
response = shortcuts.redirect(redirect_to)
utils.set_response_cookie(response, 'recent_project',
request.user.project_id)
+
+ # WRS: Refresh the project list stored in the cookie, along with
+ # the project switch event
+ tenants = request.user.authorized_tenants
+ tenants = map(lambda x: x.to_dict(), tenants)
+ utils.delete_response_cookie(response, 'authorized_tenants')
+ utils.set_response_cookie(response, 'authorized_tenants', tenants)
+
return response
--
1.8.3.1

View File

@ -1,275 +0,0 @@
From 3e528e26f17593bb2c1a148768367f194adfa343 Mon Sep 17 00:00:00 2001
From: Kam Nasim <kam.nasim@windriver.com>
Date: Wed, 30 May 2018 11:01:33 -0400
Subject: [PATCH] Distributed Keystone for Distributed Cloud -
Horizon
In Distributed Cloud, Keystone is now running on each Subcloud.
Switching to Subcloud region now requires Openstack Auth to retrieve an
Unscoped token from the switched Region and reinitialize the django
session and cookie data with token data retrieved from the Subcloud.
Since Subcloud's Keystone doesn't contain the Identity endpoint for the
Central Region, there was no way to go back in Horizon from a subcloud
region to the SystemController region. We achieve this by caching the
SystemController endpoint in the Django Session at the time of login
---
openstack_auth/user.py | 8 ++++-
openstack_auth/utils.py | 47 ++++++++++++++++++++++++-----
openstack_auth/views.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 123 insertions(+), 10 deletions(-)
diff --git a/openstack_auth/user.py b/openstack_auth/user.py
index f486bfa..39e3e34 100644
--- a/openstack_auth/user.py
+++ b/openstack_auth/user.py
@@ -29,6 +29,7 @@ from openstack_auth import utils
LOG = logging.getLogger(__name__)
_TOKEN_HASH_ENABLED = getattr(settings, 'OPENSTACK_TOKEN_HASH_ENABLED', True)
+_DC_MODE = getattr(settings, 'DC_MODE', False)
def set_session_from_user(request, user):
@@ -387,12 +388,17 @@ class User(models.AbstractBaseUser, models.AnonymousUser):
if self.service_catalog:
for service in self.service_catalog:
service_type = service.get('type')
- if service_type is None or service_type == 'identity':
+ if service_type is None:
continue
for endpoint in service.get('endpoints', []):
region = utils.get_endpoint_region(endpoint)
if region not in regions:
regions.append(region)
+ # If we are in Distributed Cloud mode, then ensure that
+ # SystemController region is present in the Region Selection
+ if _DC_MODE and utils.DC_SYSTEMCONTROLLER_REGION not in regions:
+ regions.append(utils.DC_SYSTEMCONTROLLER_REGION)
+
return regions
def save(*args, **kwargs):
diff --git a/openstack_auth/utils.py b/openstack_auth/utils.py
index 9a55790..a2107a0 100644
--- a/openstack_auth/utils.py
+++ b/openstack_auth/utils.py
@@ -18,7 +18,6 @@ import keyring
import logging
import os
import time
-import time
import re
from django.conf import settings
@@ -40,6 +39,10 @@ LOG = logging.getLogger(__name__)
_TOKEN_TIMEOUT_MARGIN = getattr(settings, 'TOKEN_TIMEOUT_MARGIN', 0)
+# Distributed Cloud Region Definitions
+DC_SYSTEMCONTROLLER_REGION = "SystemController"
+DC_LOCAL_REGION = "RegionOne"
+
"""
We need the request object to get the user, so we'll slightly modify the
existing django.contrib.auth.get_user method. To do so we update the
@@ -346,7 +349,8 @@ def clean_up_auth_url(auth_url):
scheme, netloc, re.sub(r'/auth.*', '', path), '', ''))
-def get_token_auth_plugin(auth_url, token, project_id=None, domain_name=None):
+def get_token_auth_plugin(auth_url, token, project_id=None, project_name=None,
+ domain_name=None):
if get_keystone_version() >= 3:
if domain_name:
return v3_auth.Token(auth_url=auth_url,
@@ -354,9 +358,13 @@ def get_token_auth_plugin(auth_url, token, project_id=None, domain_name=None):
domain_name=domain_name,
reauthenticate=False)
else:
+ # If project ID is defined then use that
+ # otherwise we expect the project_name
+ # to be set
return v3_auth.Token(auth_url=auth_url,
token=token,
project_id=project_id,
+ project_name=project_name,
reauthenticate=False)
else:
return v2_auth.Token(auth_url=auth_url,
@@ -440,7 +448,7 @@ def set_response_cookie(response, cookie_name, cookie_value):
def delete_response_cookie(response, cookie_name):
""" Common function for deleting a cookie from the response.
-
+
Deletes the cookie of the given cookie_name. Fails silently
if cookie name doesn't exist
"""
@@ -459,6 +467,30 @@ def get_endpoint_region(endpoint):
return endpoint.get('region_id') or endpoint.get('region')
+def get_internal_identity_endpoints(service_catalog, region_filter=""):
+ """Retrieve Internal Identity endpoints organized by region
+ """
+ endpoint_dict = {}
+ for service in service_catalog:
+ service_type = service.get('type')
+ if service_type is None or service_type != 'identity':
+ continue
+ for endpoint in service.get('endpoints', []):
+ # only retrieve internal endpoints
+ if endpoint['interface'] != 'internal':
+ continue
+ region = get_endpoint_region(endpoint)
+ # If Region Filter is set then only retrieve
+ # that specific region
+ if region_filter and region != region_filter:
+ continue
+ if region not in endpoint_dict:
+ endpoint_dict[region] = endpoint['url']
+ if region_filter:
+ break
+ return endpoint_dict
+
+
def using_cookie_backed_sessions():
engine = getattr(settings, 'SESSION_ENGINE', '')
return "signed_cookies" in engine
@@ -514,7 +546,6 @@ def get_admin_permissions():
return {get_role_permission(role) for role in get_admin_roles()}
-
def get_client_ip(request):
"""Return client ip address using SECURE_PROXY_ADDR_HEADER variable.
If not present then consider using HTTP_X_FORWARDED_FOR from.
@@ -535,10 +566,10 @@ def get_client_ip(request):
request.META.get('REMOTE_ADDR')
)
else:
- x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
- if x_forwarded_for:
- return (x_forwarded_for.split(',')[0])
- else:
+ x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
+ if x_forwarded_for:
+ return (x_forwarded_for.split(',')[0])
+ else:
return request.META.get('REMOTE_ADDR')
diff --git a/openstack_auth/views.py b/openstack_auth/views.py
index a9d84df..ad339c4 100644
--- a/openstack_auth/views.py
+++ b/openstack_auth/views.py
@@ -48,6 +48,8 @@ except AttributeError:
LOG = logging.getLogger(__name__)
+_DC_MODE = getattr(settings, 'DC_MODE', False)
+
@sensitive_post_parameters()
@csrf_protect
@@ -130,7 +132,14 @@ def login(request, template_name=None, extra_context=None, **kwargs):
' in %s minutes') %
expiration_time).replace(':', ' Hours and ')
messages.warning(request, msg)
-
+
+ # If we are in Distributed Cloud mode, and System Controller
+ # region, then also store the Region Endpoint, as this will
+ # be used by Subcloud Region Selector (switch_region()) to go
+ # back to the Central Region
+ if _DC_MODE:
+ request.session['SystemController_endpoint'] = login_region
+
# WRS: add login user name to handle HORIZON session timeout
utils.set_response_cookie(res, 'login_user',
request.user.username)
@@ -270,6 +279,60 @@ def switch_region(request, region_name,
LOG.debug('Switching services region to %s for user "%s".'
% (region_name, request.user.username))
+ # If this is a Distributed Cloud deployment then the Region may
+ # correspond to a Subcloud, and we need to invalidate the existing
+ # token as it will no longer be valid in this Subcloud
+ if _DC_MODE:
+ region_auth_url = None
+ request.session['region_name'] = region_name
+ request.session['login_region'] = region_name
+ endpoint_dict = utils.get_internal_identity_endpoints(
+ request.user.service_catalog, region_filter=region_name)
+
+ try:
+ region_auth_url = endpoint_dict[region_name]
+ except KeyError as e:
+ # If we were on a subcloud, then the SystemController Identity
+ # endpoint will not be available, therefore retrieve it from
+ # the session (cached at login)
+ if region_name == utils.DC_SYSTEMCONTROLLER_REGION:
+ region_auth_url = request.session.get(
+ 'SystemController_endpoint', None)
+
+ if not region_auth_url:
+ msg = _('Cannot switch to subcloud %s, no Identity available '
+ 'for subcloud with the provided credentials(%s)' %
+ (region_name, request.user.username))
+ raise exceptions.KeystoneAuthException(msg)
+
+ passwordPlugin = plugin.PasswordPlugin()
+ unscoped_auth = passwordPlugin.get_plugin(
+ auth_url=region_auth_url,
+ username=request.user.username,
+ password=utils.get_user_password(request.user.username),
+ user_domain_name=request.user.user_domain_name)
+ if not unscoped_auth:
+ msg = _('Cannot switch to subcloud %s authentication backend %s '
+ 'with the provided credentials(%s)' %
+ (region_name, region_auth_url, request.user.username))
+ raise exceptions.KeystoneAuthException(msg)
+ unscoped_auth_ref = passwordPlugin.get_access_info(unscoped_auth)
+ try:
+ request.user = auth.authenticate(
+ request=request, auth_url=unscoped_auth.auth_url,
+ token=unscoped_auth_ref.auth_token)
+ except exceptions.KeystoneAuthException as exc:
+ msg = 'Switching to Subcloud failed: %s' % six.text_type(exc)
+ res = django_http.HttpResponseRedirect(settings.LOGIN_URL)
+ res.set_cookie('logout_reason', msg, max_age=10)
+ return res
+ auth_user.set_session_from_user(request, request.user)
+ request.session['_auth_user_id'] = request.user.id
+ message = (
+ _('Switch to Subcloud "%(region_name)s"'
+ 'successful.') % {'region_name': region_name})
+ messages.success(request, message)
+
redirect_to = request.GET.get(redirect_field_name, '')
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = settings.LOGIN_REDIRECT_URL
@@ -277,6 +340,19 @@ def switch_region(request, region_name,
response = shortcuts.redirect(redirect_to)
utils.set_response_cookie(response, 'services_region',
request.session['services_region'])
+
+ # If we were in Distributed Cloud mode then we need to refresh the
+ # Project list as well since Identity Service provider has changed
+ if _DC_MODE:
+ # Refresh the project list stored in the cookie, along with
+ # the project switch event
+ utils.set_response_cookie(response, 'recent_project',
+ request.user.project_id)
+ tenants = request.user.authorized_tenants
+ tenants = map(lambda x: x.to_dict(), tenants)
+ utils.delete_response_cookie(response, 'authorized_tenants')
+ utils.set_response_cookie(response, 'authorized_tenants', tenants)
+
return response
--
1.8.3.1

View File

@ -1,100 +0,0 @@
From d7f75aa87d7b476509b21f9c29162763a73a65af Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Fri, 29 Jun 2018 19:51:32 -0500
Subject: [PATCH 1/1] Horizon Distributed Cloud subcloud switching
is broken
-Fixed switching from RegionOne to SystemController
-Fixed tenant list not being displayed on login
---
openstack_auth/backend.py | 2 +-
openstack_auth/forms.py | 15 ++++++++++++++-
openstack_auth/views.py | 21 ++++++++++++---------
3 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/openstack_auth/backend.py b/openstack_auth/backend.py
index cd15ca8..4fa7129 100644
--- a/openstack_auth/backend.py
+++ b/openstack_auth/backend.py
@@ -162,7 +162,7 @@ class KeystoneBackend(object):
# We want to try to use the same region we just logged into
# which may or may not be the default depending upon the order
# keystone uses
- region_name = None
+ region_name = kwargs.get('force_region', None)
id_endpoints = scoped_auth_ref.service_catalog.\
get_endpoints(service_type='identity')
for id_endpoint in [cat for cat in id_endpoints['identity']]:
diff --git a/openstack_auth/forms.py b/openstack_auth/forms.py
index 4834ab2..49b8d8b 100644
--- a/openstack_auth/forms.py
+++ b/openstack_auth/forms.py
@@ -139,11 +139,24 @@ class Login(django_auth_forms.AuthenticationForm):
if lockedout:
raise forms.ValidationError("user currently locked out.")
+ # when logging in in DC mode we will force the region to
+ # be system controller since authenticate can't map our
+ # hostname to an endpoint/regionname. Changing the hostname
+ # in settings to ip will work but will break region switching
+ # from RegionOne to SystemController since SystemController
+ # region maps back to RegionOne (same keystone)
+ force_region = None
+ if getattr(settings, 'DC_MODE', False) and \
+ region == getattr(settings, 'OPENSTACK_KEYSTONE_URL', None):
+ force_region = utils.DC_SYSTEMCONTROLLER_REGION
+
self.user_cache = authenticate(request=self.request,
username=username,
password=password,
user_domain_name=domain,
- auth_url=region)
+ auth_url=region,
+ force_region=force_region)
+
msg = 'Login successful for user "%(username)s", remote address '\
'%(remote_ip)s.' % {
'username': username,
diff --git a/openstack_auth/views.py b/openstack_auth/views.py
index a680abf..0b1351d 100644
--- a/openstack_auth/views.py
+++ b/openstack_auth/views.py
@@ -289,15 +289,17 @@ def switch_region(request, region_name,
endpoint_dict = utils.get_internal_identity_endpoints(
request.user.service_catalog, region_filter=region_name)
- try:
+ # If we were on a subcloud, then the SystemController Identity
+ # endpoint will not be functional, therefore retrieve the
+ # RegionOne endpoint from the session (cached at login)
+ force_region = None
+ if region_name == utils.DC_SYSTEMCONTROLLER_REGION:
+ force_region = utils.DC_SYSTEMCONTROLLER_REGION
+ region_auth_url = request.session.get(
+ 'SystemController_endpoint', None)
+ else:
region_auth_url = endpoint_dict[region_name]
- except KeyError as e:
- # If we were on a subcloud, then the SystemController Identity
- # endpoint will not be available, therefore retrieve it from
- # the session (cached at login)
- if region_name == utils.DC_SYSTEMCONTROLLER_REGION:
- region_auth_url = request.session.get(
- 'SystemController_endpoint', None)
+
if not region_auth_url:
msg = _('Cannot switch to subcloud %s, no Identity available '
@@ -320,7 +322,8 @@ def switch_region(request, region_name,
try:
request.user = auth.authenticate(
request=request, auth_url=unscoped_auth.auth_url,
- token=unscoped_auth_ref.auth_token)
+ token=unscoped_auth_ref.auth_token,
+ force_region=force_region)
except exceptions.KeystoneAuthException as exc:
msg = 'Switching to Subcloud failed: %s' % six.text_type(exc)
res = django_http.HttpResponseRedirect(settings.LOGIN_URL)
--
1.8.3.1

View File

@ -1 +0,0 @@
mirror:Source/python-django-openstack-auth-3.6.1-1.el7.src.rpm

View File

@ -1,5 +1,5 @@
TAR_NAME=horizon
SRC_DIR="$CGCS_BASE/git/horizon"
COPY_LIST="$FILES_BASE/*"
TIS_BASE_SRCREV=79a529593f84e4ea0762dc4a72ca167a1c5d0c3d
TIS_PATCH_VER=GITREVCOUNT
TIS_BASE_SRCREV=a8df389822aaeaa29aded7e8c6614b51748ab914
TIS_PATCH_VER=1

View File

@ -1,70 +0,0 @@
diff --git a/openstack_dashboard/api/nova.py b/openstack_dashboard/api/nova.py
index 39a7684..e6798e9 100755
--- a/openstack_dashboard/api/nova.py
+++ b/openstack_dashboard/api/nova.py
@@ -38,10 +38,6 @@ from novaclient.v2 import instance_action as nova_instance_action
from novaclient.v2 import list_extensions as nova_list_extensions
from novaclient.v2 import servers as nova_servers
-# Todo (ediardo): move all wrs* and func wrappers into stx-gui
-from novaclient.v2 import wrs_pci
-from novaclient.v2 import wrs_providernets
-
from horizon import exceptions
from horizon import exceptions as horizon_exceptions
from horizon.utils import functions as utils
@@ -1123,54 +1119,6 @@ def requires_keypair():
return features.get('requires_keypair', False)
-# WRS: Nova extension for provider network.
-@profiler.trace
-def provider_network_get(request, providernet_id):
- return wrs_providernets.ProviderNetsManager(novaclient(request)).get(
- providernet_id)
-
-
-# WRS: Nova extension for device usage
-@profiler.trace
-class DeviceUsage(base.APIResourceWrapper):
- """Wrapper for Inventory Device Usage"""
- _attrs = ['device_name', 'device_id', 'vendor_id', 'class_id',
- 'pci_vfs_configured', 'pci_vfs_used',
- 'pci_pfs_configured', 'pci_pfs_used']
-
-
-@profiler.trace
-def get_device_usage_list(request):
- usages = wrs_pci.PciDevicesManager(novaclient(request)).list()
- return [DeviceUsage(n) for n in usages]
-
-
-@profiler.trace
-def get_device_usage(request, device_id):
- if device_id is None:
- raise nova_exceptions.ResourceNotFound
-
- usage = wrs_pci.PciDevicesManager(novaclient(request)).list(
- device=device_id)
- return DeviceUsage(usage[0])
-
-
-# WRS: Nova extension for detail device usage
-@profiler.trace
-class DetailUsage(base.APIResourceWrapper):
- """Wrapper for Inventory Device Usage"""
- _attrs = ['host',
- 'pci_vfs_configured', 'pci_vfs_used',
- 'pci_pfs_configured', 'pci_pfs_used']
-
-
-@profiler.trace
-def get_detail_usage(request, device_id):
- usages = wrs_pci.PciDevicesManager(novaclient(request)).get(
- device_id)
- return [DetailUsage(n) for n in usages]
-
-
def can_set_quotas():
features = getattr(settings, 'OPENSTACK_HYPERVISOR_FEATURES', {})
return features.get('enable_quotas', True)

View File

@ -4,7 +4,7 @@ Name: python-django-horizon
# Liberty semver reset
# https://review.openstack.org/#/q/I6a35fa0dda798fad93b804d00a46af80f08d475c,n,z
Epoch: 1
Version: 12.0.0
Version: 14.0.0
Release: 2%{?_tis_dist}.%{tis_patch_ver}
Summary: Django application for talking to Openstack
@ -30,8 +30,6 @@ Source12: horizon-region-exclusions.csv
Source13: guni_config.py
Source14: horizon-assets-compress
Patch1: 0001-Remove-WRS-imports-from-novaclient.patch
#
# BuildArch needs to be located below patches in the spec file. Don't ask!
#
@ -46,7 +44,7 @@ BuildRequires: cgts-client
Requires: cgts-client
Requires: pytz
Requires: python-six >= 1.9.0
Requires: python-six >= 1.10.0
Requires: python-pbr
BuildRequires: python2-devel
@ -55,24 +53,31 @@ BuildRequires: python2-pip
BuildRequires: python2-wheel
BuildRequires: python-pbr >= 2.0.0
BuildRequires: git
BuildRequires: python-six >= 1.9.0
BuildRequires: python-six >= 1.10.0
BuildRequires: gettext
# for checks:
%if 0%{?rhel} == 0
BuildRequires: python-django-nose >= 1.2
BuildRequires: python-coverage
BuildRequires: python-django-nose
BuildRequires: python-mox3
BuildRequires: python-nose-exclude
BuildRequires: python-nose
BuildRequires: python-selenium
%endif
BuildRequires: python-osprofiler
BuildRequires: python-netaddr
BuildRequires: python-anyjson
BuildRequires: python-iso8601
BuildRequires: python-pep8
# additional provides to be consistent with other django packages
Provides: django-horizon = %{epoch}:%{version}-%{release}
Obsoletes: python-django-openstack-auth < 4.0.0-1
Obsoletes: python2-django-openstack-auth < 4.0.0-1
# (TODO) remove following provides once the requirements have been fixed
# in all dashboard plugins
Provides: python-django-openstack-auth = %{epoch}:%{version}-%{release}
Provides: python2-django-openstack-auth = %{epoch}:%{version}-%{release}
%description
Horizon is a Django application for providing Openstack UI components.
@ -89,66 +94,68 @@ Group: Applications/System
Requires: httpd
Requires: mod_wsgi
Requires: %{name} = %{epoch}:%{version}-%{release}
Requires: python-django-openstack-auth >= 3.5.0
Requires: python-django-compressor >= 2.0
Requires: python2-django-compressor >= 2.0
Requires: python-django-appconf
Requires: python-django-babel
Requires: python-lesscpy
Requires: python-iso8601
Requires: python-glanceclient
Requires: python-keystoneclient >= 1:3.8.0
Requires: python-novaclient
Requires: python-neutronclient
Requires: python-cinderclient
Requires: python-swiftclient >= 3.2.0
Requires: python-heatclient >= 1.6.1
Requires: python-netaddr
Requires: python-osprofiler >= 1.4.0
Requires: openstack-dashboard-theme >= %{epoch}:%{version}-%{release}
Requires: python2-iso8601
Requires: python2-glanceclient >= 1:2.8.0
Requires: python2-keystoneclient >= 1:3.15.0
Requires: python2-keystoneauth1 >= 3.4.0
Requires: python2-novaclient >= 1:9.1.0
Requires: python2-neutronclient >= 6.7.0
Requires: python2-cinderclient >= 3.3.0
Requires: python2-swiftclient >= 3.2.0
Requires: python2-netaddr
Requires: python2-osprofiler >= 2.3.0
Requires: python-pymongo >= 3.0.2
Requires: python-django-pyscss >= 2.0.2
Requires: python2-django-pyscss >= 2.0.2
Requires: python-semantic_version
Requires: python-XStatic
Requires: python2-XStatic
Requires: python-XStatic-jQuery
Requires: python-XStatic-Angular >= 1:1.3.7
Requires: python-XStatic-Angular-Bootstrap
Requires: python-XStatic-Angular-Schema-Form
Requires: python-XStatic-D3 >= 3.5.17.0
Requires: python-XStatic-Font-Awesome >= 4.7.0
Requires: python2-XStatic-Angular >= 1:1.5.8.0
Requires: python2-XStatic-Angular-Bootstrap
Requires: python2-XStatic-Angular-Schema-Form
Requires: python2-XStatic-D3
Requires: python2-XStatic-Font-Awesome
Requires: python-XStatic-Hogan
Requires: python-XStatic-JQuery-Migrate
Requires: python-XStatic-JQuery-TableSorter
Requires: python-XStatic-JQuery-quicksearch
Requires: python-XStatic-JSEncrypt >= 2.3.1.1
Requires: python-XStatic-Jasmine >= 2.4.1.1
Requires: python2-XStatic-JSEncrypt
Requires: python2-XStatic-Jasmine
Requires: python-XStatic-Rickshaw
Requires: python-XStatic-Spin
Requires: python-XStatic-jquery-ui
Requires: python-XStatic-Bootstrap-Datepicker
Requires: python-XStatic-Bootstrap-SCSS >= 3.3.7.1
Requires: python-XStatic-termjs >= 0.0.7.0
Requires: python-XStatic-smart-table
Requires: python2-XStatic-Bootstrap-SCSS >= 3.3.7.1
Requires: python2-XStatic-termjs
Requires: python2-XStatic-smart-table
Requires: python-XStatic-Angular-lrdragndrop
Requires: python-XStatic-Angular-Gettext
Requires: python-XStatic-Angular-FileUpload
Requires: python2-XStatic-Angular-Gettext
Requires: python2-XStatic-Angular-FileUpload
Requires: python-XStatic-Magic-Search
Requires: python-XStatic-bootswatch
Requires: python-XStatic-roboto-fontface >= 0.5.0.0
Requires: python-XStatic-mdi
Requires: python-XStatic-objectpath
Requires: python-XStatic-tv4
Requires: python2-XStatic-bootswatch
Requires: python2-XStatic-roboto-fontface >= 0.5.0.0
Requires: python2-XStatic-mdi
Requires: python2-XStatic-objectpath
Requires: python2-XStatic-tv4
Requires: python2-django-debreach
Requires: python-scss >= 1.3.4
Requires: python2-scss >= 1.3.4
Requires: fontawesome-fonts-web >= 4.1.0
Requires: python-oslo-concurrency >= 3.8.0
Requires: python-oslo-config >= 2:4.0.0
Requires: python-oslo-i18n >= 2.1.0
Requires: python-oslo-serialization >= 1.10.0
Requires: python-oslo-utils >= 3.20.0
Requires: python-oslo-policy >= 1.23.0
Requires: python-babel
Requires: python-futurist
Requires: python2-oslo-concurrency >= 3.26.0
Requires: python2-oslo-config >= 2:5.2.0
Requires: python2-oslo-i18n >= 3.15.3
Requires: python2-oslo-serialization >= 2.18.0
Requires: python2-oslo-utils >= 3.33.0
Requires: python2-oslo-policy >= 1.30.0
Requires: python2-babel
Requires: python2-futurist
Requires: python-pint
Requires: openssl
@ -156,51 +163,50 @@ Requires: logrotate
Requires: PyYAML >= 3.10
BuildRequires: python-django-openstack-auth >= 3.5.0
BuildRequires: python-django-compressor >= 2.0
BuildRequires: python2-django-compressor >= 2.0
BuildRequires: python-django-appconf
BuildRequires: python-lesscpy
BuildRequires: python-semantic_version
BuildRequires: python-django-pyscss >= 2.0.2
BuildRequires: python-XStatic
BuildRequires: python2-django-pyscss >= 2.0.2
BuildRequires: python2-XStatic
BuildRequires: python-XStatic-jQuery
BuildRequires: python-XStatic-Angular >= 1:1.3.7
BuildRequires: python-XStatic-Angular-Bootstrap
BuildRequires: python-XStatic-Angular-Schema-Form
BuildRequires: python-XStatic-D3
BuildRequires: python-XStatic-Font-Awesome
BuildRequires: python2-XStatic-Angular >= 1:1.5.8.0
BuildRequires: python2-XStatic-Angular-Bootstrap
BuildRequires: python2-XStatic-Angular-Schema-Form
BuildRequires: python2-XStatic-D3
BuildRequires: python2-XStatic-Font-Awesome
BuildRequires: python-XStatic-Hogan
BuildRequires: python-XStatic-JQuery-Migrate
BuildRequires: python-XStatic-JQuery-TableSorter
BuildRequires: python-XStatic-JQuery-quicksearch
BuildRequires: python-XStatic-JSEncrypt >= 2.3.1.1
BuildRequires: python-XStatic-Jasmine
BuildRequires: python2-XStatic-JSEncrypt
BuildRequires: python2-XStatic-Jasmine
BuildRequires: python-XStatic-Rickshaw
BuildRequires: python-XStatic-Spin
BuildRequires: python-XStatic-jquery-ui
BuildRequires: python-XStatic-Bootstrap-Datepicker
BuildRequires: python-XStatic-Bootstrap-SCSS >= 3.3.7.1
BuildRequires: python-XStatic-termjs
BuildRequires: python-XStatic-smart-table
BuildRequires: python2-XStatic-Bootstrap-SCSS
BuildRequires: python2-XStatic-termjs
BuildRequires: python2-XStatic-smart-table
BuildRequires: python-XStatic-Angular-lrdragndrop
BuildRequires: python-XStatic-Angular-FileUpload
BuildRequires: python2-XStatic-Angular-FileUpload
BuildRequires: python-XStatic-Magic-Search
BuildRequires: python-XStatic-Angular-Gettext
BuildRequires: python-XStatic-bootswatch
BuildRequires: python-XStatic-roboto-fontface
BuildRequires: python-XStatic-mdi
BuildRequires: python-XStatic-objectpath
BuildRequires: python-XStatic-tv4
BuildRequires: python2-XStatic-Angular-Gettext
BuildRequires: python2-XStatic-bootswatch
BuildRequires: python2-XStatic-roboto-fontface
BuildRequires: python2-XStatic-mdi
BuildRequires: python2-XStatic-objectpath
BuildRequires: python2-XStatic-tv4
# bootstrap-scss requires at least python-scss >= 1.2.1
BuildRequires: python-scss >= 1.3.4
BuildRequires: python2-scss >= 1.3.4
BuildRequires: fontawesome-fonts-web >= 4.1.0
BuildRequires: python-oslo-concurrency
BuildRequires: python-oslo-config
BuildRequires: python-oslo-i18n
BuildRequires: python-oslo-serialization
BuildRequires: python-oslo-utils
BuildRequires: python-oslo-policy
BuildRequires: python-babel
BuildRequires: python2-oslo-concurrency
BuildRequires: python2-oslo-config
BuildRequires: python2-oslo-i18n
BuildRequires: python2-oslo-serialization
BuildRequires: python2-oslo-utils
BuildRequires: python2-oslo-policy
BuildRequires: python2-babel
BuildRequires: python-pint
BuildRequires: pytz
@ -226,14 +232,13 @@ Requires: %{name} = %{epoch}:%{version}-%{release}
BuildRequires: python-sphinx >= 1.1.3
# Doc building basically means we have to mirror Requires:
BuildRequires: python-openstackdocstheme
BuildRequires: python-glanceclient
BuildRequires: python-keystoneclient
BuildRequires: python-novaclient >= 1:6.0.0
BuildRequires: python-neutronclient
BuildRequires: python-cinderclient
BuildRequires: python-swiftclient
BuildRequires: python-heatclient
BuildRequires: python2-openstackdocstheme
BuildRequires: python2-glanceclient
BuildRequires: python2-keystoneclient
BuildRequires: python2-novaclient >= 1:9.1.0
BuildRequires: python2-neutronclient
BuildRequires: python2-cinderclient
BuildRequires: python2-swiftclient
%description doc
Documentation for the Django Horizon application for talking with Openstack
@ -249,7 +254,6 @@ Customization module for OpenStack Dashboard to provide a branded logo.
%prep
%autosetup -n horizon-%{upstream_version} -S git
# autosetup automatically applies the patches
# STX remove troublesome files introduced by tox
rm -f openstack_dashboard/test/.secret_key_store
@ -368,6 +372,9 @@ mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/local/local_s
#ln -s ../../../../../%{_sysconfdir}/openstack-dashboard/local_settings %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/local/local_settings.py
mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/conf/*.json %{buildroot}%{_sysconfdir}/openstack-dashboard
mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/conf/cinder_policy.d %{buildroot}%{_sysconfdir}/openstack-dashboard
mv %{buildroot}%{_datadir}/openstack-dashboard/openstack_dashboard/conf/nova_policy.d %{buildroot}%{_sysconfdir}/openstack-dashboard
%find_lang django --all-name
@ -387,15 +394,14 @@ mkdir -p %{buildroot}%{_sharedstatedir}/openstack-dashboard
# create /var/log/horizon and own it
mkdir -p %{buildroot}%{_var}/log/horizon
# place logrotate config
# place logrotate config:
mkdir -p %{buildroot}%{_sysconfdir}/logrotate.d
cp -a %{SOURCE5} %{buildroot}%{_sysconfdir}/logrotate.d/openstack-dashboard
%check
# don't run tests on rhel
%if 0%{?rhel} == 0
# since rawhide has django-1.7 now, tests fail
#./run_tests.sh -N -P
%{__python2} manage.py test horizon --settings=horizon.test.settings
%endif
%post -n openstack-dashboard
@ -430,6 +436,7 @@ systemctl daemon-reload >/dev/null 2>&1 || :
%{python_sitelib}/horizon/workflows
%{python_sitelib}/horizon/karma.conf.js
%{python_sitelib}/horizon/middleware
%{python_sitelib}/openstack_auth
%{python_sitelib}/*.egg-info
%files -n openstack-dashboard -f dashboard.lang
@ -445,7 +452,6 @@ systemctl daemon-reload >/dev/null 2>&1 || :
%{_datadir}/openstack-dashboard/openstack_dashboard/dashboards/identity
%{_datadir}/openstack-dashboard/openstack_dashboard/dashboards/project
%{_datadir}/openstack-dashboard/openstack_dashboard/dashboards/settings
# STX
%{_datadir}/openstack-dashboard/openstack_dashboard/dashboards/__init__.py*
%{_datadir}/openstack-dashboard/openstack_dashboard/django_pyscss_fix
%{_datadir}/openstack-dashboard/openstack_dashboard/enabled
@ -469,6 +475,7 @@ systemctl daemon-reload >/dev/null 2>&1 || :
%{_datadir}/openstack-dashboard/openstack_dashboard/.eslintrc
%dir %attr(0750, root, apache) %{_sysconfdir}/openstack-dashboard
%dir %attr(0750, root, apache) %{_sysconfdir}/openstack-dashboard/cinder_policy.d/
%dir %attr(0750, apache, apache) %{_sharedstatedir}/openstack-dashboard
%dir %attr(0750, apache, apache) %{_var}/log/horizon
%config(noreplace) %{_sysconfdir}/httpd/conf.d/openstack-dashboard.conf
@ -478,8 +485,9 @@ systemctl daemon-reload >/dev/null 2>&1 || :
%config(noreplace) %attr(0640, root, apache) %{_sysconfdir}/openstack-dashboard/nova_policy.json
%config(noreplace) %attr(0640, root, apache) %{_sysconfdir}/openstack-dashboard/glance_policy.json
%config(noreplace) %attr(0640, root, apache) %{_sysconfdir}/openstack-dashboard/neutron_policy.json
%config(noreplace) %attr(0640, root, apache) %{_sysconfdir}/openstack-dashboard/heat_policy.json
%config(noreplace) %{_sysconfdir}/logrotate.d/openstack-dashboard
%config(noreplace) %attr(0640, root, apache) %{_sysconfdir}/openstack-dashboard/cinder_policy.d/consistencygroup.yaml
%config(noreplace) %attr(0640, root, apache) %{_sysconfdir}/openstack-dashboard/nova_policy.d/api-extensions.yaml
%config(noreplace) %attr(0644, root, root) %{_sysconfdir}/logrotate.d/openstack-dashboard
%attr(755,root,root) %dir %{_unitdir}/httpd.service.d
%config(noreplace) %{_unitdir}/httpd.service.d/openstack-dashboard.conf
@ -515,19 +523,19 @@ Contains python wheels for %{name}
/wheels/*
%changelog
* Mon Oct 04 2017 Radomir Dopieralski <rdopiera@redhat.com> 1:12.0.0-2
- Require at least 3.3.7.1 version of XStatic-bootstrap-SCSS package
* Mon Dec 03 2018 RDO <dev@lists.rdoproject.org> 1:14.0.2-1
- Update to 14.0.2
* Wed Aug 30 2017 rdo-trunk <javier.pena@redhat.com> 1:12.0.0-1
- Update to 12.0.0
* Mon Oct 22 2018 RDO <dev@lists.rdoproject.org> 1:14.0.1-1
- Update to 14.0.1
* Mon Aug 28 2017 rdo-trunk <javier.pena@redhat.com> 1:12.0.0-0.3.0rc3
- Update to 12.0.0.0rc3
* Thu Aug 30 2018 RDO <dev@lists.rdoproject.org> 1:14.0.0-1
- Update to 14.0.0
* Fri Aug 25 2017 Alfredo Moralejo <amoralej@redhat.com> 1:12.0.0-0.2.0rc2
- Update to 12.0.0.0rc2
* Wed Aug 22 2018 RDO <dev@lists.rdoproject.org> 1:14.0.0-0.2.0rc1
- Update to 14.0.0.0rc2
* Mon Aug 21 2017 Alfredo Moralejo <amoralej@redhat.com> 1:12.0.0-0.1.0rc1
- Update to 12.0.0.0rc1
* Mon Aug 20 2018 RDO <dev@lists.rdoproject.org> 1:14.0.0-0.1.0rc1
- Update to 14.0.0.0rc1

View File

@ -1 +0,0 @@
TIS_PATCH_VER=2

View File

@ -1,2 +0,0 @@
update-package-versioning-for-TIS-format.patch
spec-add-fair-lock.patch

View File

@ -1,15 +0,0 @@
diff --git a/SPECS/python-oslo-concurrency.spec b/SPECS/python-oslo-concurrency.spec
index a4a3883..cc9e799 100644
--- a/SPECS/python-oslo-concurrency.spec
+++ b/SPECS/python-oslo-concurrency.spec
@@ -16,6 +16,10 @@ Summary: OpenStack Oslo concurrency library
License: ASL 2.0
URL: https://launchpad.net/oslo
Source0: https://tarballs.openstack.org/%{pypi_name}/%{pypi_name}-%{upstream_version}.tar.gz
+
+# WRS
+Patch0001: add-fair-lock.patch
+
BuildArch: noarch
%description

View File

@ -1,13 +0,0 @@
diff --git a/SPECS/python-oslo-concurrency.spec b/SPECS/python-oslo-concurrency.spec
index dee2b71..a4a3883 100644
--- a/SPECS/python-oslo-concurrency.spec
+++ b/SPECS/python-oslo-concurrency.spec
@@ -10,7 +10,7 @@
Name: python-oslo-concurrency
Version: 3.21.1
-Release: 1%{?dist}
+Release: 1.el7%{?_tis_dist}.%{tis_patch_ver}
Summary: OpenStack Oslo concurrency library
License: ASL 2.0

View File

@ -1,106 +0,0 @@
diff --git a/oslo_concurrency/lockutils.py b/oslo_concurrency/lockutils.py
index ea67571..4519463 100644
--- a/oslo_concurrency/lockutils.py
+++ b/oslo_concurrency/lockutils.py
@@ -87,6 +87,43 @@ ReaderWriterLock = fasteners.ReaderWriterLock
"""
+class FairLocks(object):
+ """A garbage collected container of fair locks.
+
+ This collection internally uses a weak value dictionary so that when a
+ lock is no longer in use (by any threads) it will automatically be
+ removed from this container by the garbage collector.
+ """
+
+ def __init__(self):
+ self._locks = weakref.WeakValueDictionary()
+ self._lock = threading.Lock()
+
+ def get(self, name):
+ """Gets (or creates) a lock with a given name.
+
+ :param name: The lock name to get/create (used to associate
+ previously created names with the same lock).
+
+ Returns an newly constructed lock (or an existing one if it was
+ already created for the given name).
+ """
+ with self._lock:
+ try:
+ return self._locks[name]
+ except KeyError:
+ rwlock = ReaderWriterLock()
+ self._locks[name] = rwlock
+ return rwlock
+
+
+fair_locks = FairLocks()
+
+
+def internal_fair_lock(name):
+ return fair_locks.get(name)
+
+
class Semaphores(object):
"""A garbage collected container of semaphores.
@@ -170,7 +207,7 @@ def internal_lock(name, semaphores=None):
@contextlib.contextmanager
def lock(name, lock_file_prefix=None, external=False, lock_path=None,
- do_log=True, semaphores=None, delay=0.01):
+ do_log=True, semaphores=None, delay=0.01, fair=False):
"""Context based lock
This function yields a `threading.Semaphore` instance (if we don't use
@@ -200,16 +237,22 @@ def lock(name, lock_file_prefix=None, external=False, lock_path=None,
:param delay: Delay between acquisition attempts (in seconds).
+ :param fair: Whether or not we want a "fair" lock where contending lockers
+ will get the lock in the order in which they tried to acquire it.
+
.. versionchanged:: 0.2
Added *do_log* optional parameter.
.. versionchanged:: 0.3
Added *delay* and *semaphores* optional parameters.
"""
- int_lock = internal_lock(name, semaphores=semaphores)
+ if fair:
+ int_lock = internal_fair_lock(name).write_lock()
+ else:
+ int_lock = internal_lock(name, semaphores=semaphores)
with int_lock:
if do_log:
- LOG.debug('Acquired semaphore "%(lock)s"', {'lock': name})
+ LOG.debug('Acquired lock "%(lock)s"', {'lock': name})
try:
if external and not CONF.oslo_concurrency.disable_process_locking:
ext_lock = external_lock(name, lock_file_prefix, lock_path)
@@ -222,11 +265,11 @@ def lock(name, lock_file_prefix=None, external=False, lock_path=None,
yield int_lock
finally:
if do_log:
- LOG.debug('Releasing semaphore "%(lock)s"', {'lock': name})
+ LOG.debug('Releasing lock "%(lock)s"', {'lock': name})
def synchronized(name, lock_file_prefix=None, external=False, lock_path=None,
- semaphores=None, delay=0.01):
+ semaphores=None, delay=0.01, fair=False):
"""Synchronization decorator.
Decorating a method like so::
@@ -261,7 +304,8 @@ def synchronized(name, lock_file_prefix=None, external=False, lock_path=None,
t2 = None
try:
with lock(name, lock_file_prefix, external, lock_path,
- do_log=False, semaphores=semaphores, delay=delay):
+ do_log=False, semaphores=semaphores, delay=delay,
+ fair=fair):
t2 = timeutils.now()
LOG.debug('Lock "%(name)s" acquired by "%(function)s" :: '
'waited %(wait_secs)0.3fs',

View File

@ -1 +0,0 @@
mirror:Source/python-oslo-concurrency-3.21.1-1.el7.src.rpm