From b344877bdf24985dea5342060c989a9d06fe0964 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Fri, 25 Feb 2011 13:01:32 -0800 Subject: add a caching layer to the has_role call to increase performance --- nova/api/ec2/__init__.py | 6 ++--- nova/auth/manager.py | 58 +++++++++++++++++++++++++++++++++++------------- nova/flags.py | 2 ++ 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 5adc2c075..7a9c4f957 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -46,8 +46,6 @@ flags.DEFINE_integer('lockout_minutes', 15, 'Number of minutes to lockout if triggered.') flags.DEFINE_integer('lockout_window', 15, 'Number of minutes for lockout window.') -flags.DEFINE_list('lockout_memcached_servers', None, - 'Memcached servers or None for in process cache.') class RequestLogging(wsgi.Middleware): @@ -104,11 +102,11 @@ class Lockout(wsgi.Middleware): def __init__(self, application): """middleware can use fake for testing.""" - if FLAGS.lockout_memcached_servers: + if FLAGS.memcached_servers: import memcache else: from nova import fakememcache as memcache - self.mc = memcache.Client(FLAGS.lockout_memcached_servers, + self.mc = memcache.Client(FLAGS.memcached_servers, debug=0) super(Lockout, self).__init__(application) diff --git a/nova/auth/manager.py b/nova/auth/manager.py index 450ab803a..906734799 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -214,6 +214,13 @@ class AuthManager(object): if driver or not getattr(self, 'driver', None): self.driver = utils.import_class(driver or FLAGS.auth_driver) + if FLAGS.memcached_servers: + import memcache + else: + from nova import fakememcache as memcache + self.mc = memcache.Client(FLAGS.memcached_servers, + debug=0) + def authenticate(self, access, signature, params, verb='GET', server_string='127.0.0.1:8773', path='/', check_type='ec2', headers=None): @@ -351,6 +358,25 @@ class AuthManager(object): if self.has_role(user, role): return True + def _build_mc_key(self, user, role, project=None): + return "rolecache-%s-%s-%s" % (User.safe_id(user), role, + (Project.safe_id(project) if project else 'None')) + + def _clear_mc_key(self, user, role, project=None): + # (anthony) it would be better to delete the key + self.mc.set(self._build_mc_key(user, role, project), None) + + def _has_role(self, user, role, project=None): + with self.driver() as drv: + mc_key = self._build_mc_key(user, role, project) + rslt = self.mc.get(mc_key) + if rslt == None: + rslt = drv.has_role(user, role, project) + self.mc.set(mc_key, rslt) + return rslt + else: + return rslt + def has_role(self, user, role, project=None): """Checks existence of role for user @@ -374,24 +400,24 @@ class AuthManager(object): @rtype: bool @return: True if the user has the role. """ - with self.driver() as drv: - if role == 'projectmanager': - if not project: - raise exception.Error(_("Must specify project")) - return self.is_project_manager(user, project) + if role == 'projectmanager': + if not project: + raise exception.Error(_("Must specify project")) + return self.is_project_manager(user, project) + + global_role = self._has_role(User.safe_id(user), + role, + None) - global_role = drv.has_role(User.safe_id(user), - role, - None) - if not global_role: - return global_role + if not global_role: + return global_role - if not project or role in FLAGS.global_roles: - return global_role + if not project or role in FLAGS.global_roles: + return global_role - return drv.has_role(User.safe_id(user), - role, - Project.safe_id(project)) + return self._has_role(User.safe_id(user), + role, + Project.safe_id(project)) def add_role(self, user, role, project=None): """Adds role for user @@ -423,6 +449,7 @@ class AuthManager(object): LOG.audit(_("Adding sitewide role %(role)s to user %(uid)s") % locals()) with self.driver() as drv: + self._clear_mc_key(uid, role, pid) drv.add_role(uid, role, pid) def remove_role(self, user, role, project=None): @@ -451,6 +478,7 @@ class AuthManager(object): LOG.audit(_("Removing sitewide role %(role)s" " from user %(uid)s") % locals()) with self.driver() as drv: + self._clear_mc_key(uid, role, pid) drv.remove_role(uid, role, pid) @staticmethod diff --git a/nova/flags.py b/nova/flags.py index 8cf199b2f..f885de293 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -354,3 +354,5 @@ DEFINE_string('host', socket.gethostname(), DEFINE_string('node_availability_zone', 'nova', 'availability zone of this node') +DEFINE_list('memcached_servers', None, + 'Memcached servers or None for in process cache.') -- cgit From 47c312bb659d0ad49a678c8213093827e6067f31 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Fri, 25 Feb 2011 16:41:48 -0800 Subject: only create auth connection if cache misses --- nova/auth/manager.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/nova/auth/manager.py b/nova/auth/manager.py index 906734799..511bc3a64 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -367,15 +367,15 @@ class AuthManager(object): self.mc.set(self._build_mc_key(user, role, project), None) def _has_role(self, user, role, project=None): - with self.driver() as drv: - mc_key = self._build_mc_key(user, role, project) - rslt = self.mc.get(mc_key) - if rslt == None: + mc_key = self._build_mc_key(user, role, project) + rslt = self.mc.get(mc_key) + if rslt == None: + with self.driver() as drv: rslt = drv.has_role(user, role, project) self.mc.set(mc_key, rslt) return rslt - else: - return rslt + else: + return rslt def has_role(self, user, role, project=None): """Checks existence of role for user -- cgit From e0ba72946011b67a218e3c619b3105529bb43e53 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Fri, 25 Feb 2011 17:18:41 -0800 Subject: force memcache key to be str --- nova/auth/manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/auth/manager.py b/nova/auth/manager.py index 511bc3a64..84c8a6cb2 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -359,8 +359,8 @@ class AuthManager(object): return True def _build_mc_key(self, user, role, project=None): - return "rolecache-%s-%s-%s" % (User.safe_id(user), role, - (Project.safe_id(project) if project else 'None')) + return str("rolecache-%s-%s-%s" % (User.safe_id(user), role, + (Project.safe_id(project) if project else 'None'))) def _clear_mc_key(self, user, role, project=None): # (anthony) it would be better to delete the key -- cgit From 4a8a08790803d574ecd1dce4b3765cbce7e1043a Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Apr 2011 12:56:25 -0700 Subject: fixed comment --- nova/auth/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/auth/manager.py b/nova/auth/manager.py index 12ded1207..f2451702c 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -372,7 +372,7 @@ class AuthManager(object): (Project.safe_id(project) if project else 'None'))) def _clear_mc_key(self, user, role, project=None): - # (anthony) it would be better to delete the key + # NOTE(anthony): it would be better to delete the key self.mc.set(self._build_mc_key(user, role, project), None) def _has_role(self, user, role, project=None): -- cgit From 36857e5091234940e3ac68d154c019fbd5d28af5 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 5 Apr 2011 15:58:19 -0700 Subject: remove -None for user roles --- nova/auth/manager.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nova/auth/manager.py b/nova/auth/manager.py index f2451702c..3de2ceffe 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -368,8 +368,10 @@ class AuthManager(object): return True def _build_mc_key(self, user, role, project=None): - return str("rolecache-%s-%s-%s" % (User.safe_id(user), role, - (Project.safe_id(project) if project else 'None'))) + role_key = str("rolecache-%s-%s" % (User.safe_id(user), role)) + if project: + return "%s-%s" % (role_key, Project.safe_id(project)) + return role_key def _clear_mc_key(self, user, role, project=None): # NOTE(anthony): it would be better to delete the key -- cgit From dc4beede6bda3b7db5ca5963cc6c48052d2b7c62 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 21 Apr 2011 23:45:02 -0700 Subject: Fixes per review --- nova/auth/manager.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nova/auth/manager.py b/nova/auth/manager.py index 3de2ceffe..4d4bdbce9 100644 --- a/nova/auth/manager.py +++ b/nova/auth/manager.py @@ -368,10 +368,10 @@ class AuthManager(object): return True def _build_mc_key(self, user, role, project=None): - role_key = str("rolecache-%s-%s" % (User.safe_id(user), role)) + key_parts = ['rolecache', User.safe_id(user), str(role)] if project: - return "%s-%s" % (role_key, Project.safe_id(project)) - return role_key + key_parts.append(Project.safe_id(project)) + return '-'.join(key_parts) def _clear_mc_key(self, user, role, project=None): # NOTE(anthony): it would be better to delete the key @@ -380,7 +380,7 @@ class AuthManager(object): def _has_role(self, user, role, project=None): mc_key = self._build_mc_key(user, role, project) rslt = self.mc.get(mc_key) - if rslt == None: + if rslt is None: with self.driver() as drv: rslt = drv.has_role(user, role, project) self.mc.set(mc_key, rslt) -- cgit