From d614cc8472417ee79a941bf6f993569b01476bd1 Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Fri, 9 May 2014 15:34:57 -0400 Subject: [PATCH] Integrate memcached support for some host fields Conflicts: setup/roles/packages_el/vars/default.yml setup/roles/packages_ubuntu/tasks/main.yml --- awx/api/serializers.py | 7 ++----- awx/main/models/inventory.py | 37 ++++++++++++++++++++++++++++++++---- awx/settings/defaults.py | 9 +++++++++ 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 6d6d18ebe6..35a8610638 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -23,6 +23,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.db.models.fields import BLANK_CHOICE_DASH from django.utils.datastructures import SortedDict from django.utils.translation import ugettext_lazy as _ +from django.core.cache import cache # Django REST Framework from rest_framework.compat import get_concrete_model @@ -755,11 +756,7 @@ class HostSerializer(BaseSerializerWithVariables): d['last_job']['job_template_name'] = obj.last_job.job_template.name except (KeyError, AttributeError): pass - # TODO: This is slow - d['all_groups'] = [{'id': g.id, 'name': g.name} for g in obj.all_groups.all()] - d['groups'] = [{'id': g.id, 'name': g.name} for g in obj.groups.all()] - d['recent_jobs'] = [{'id': j.job.id, 'name': j.job.job_template.name, 'status': j.job.status, 'finished': j.job.finished} \ - for j in obj.job_host_summaries.all().order_by('-created')[:5]] + d.update(obj.get_cached_summary_values()) return d def _get_host_port_from_name(self, name): diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index b853537a90..786fbeb51e 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -27,6 +27,7 @@ from django.core.exceptions import ValidationError, NON_FIELD_ERRORS from django.core.urlresolvers import reverse from django.contrib.auth.models import User from django.utils.timezone import now, make_aware, get_default_timezone +from django.core.cache import cache # AWX from awx.main.fields import AutoOneToOneField @@ -238,6 +239,7 @@ class Host(CommonModelNameNotUnique): ''' super(Host, self).mark_inactive(save=save) self.inventory_sources.clear() + self.clear_cached_values() def update_computed_fields(self, update_inventory=True, update_groups=True): ''' @@ -267,7 +269,8 @@ class Host(CommonModelNameNotUnique): if update_inventory: self.inventory.update_computed_fields(update_groups=False, update_hosts=False) - + # Rebuild summary fields cache + self.update_cached_values() variables_dict = VarsDictProperty('variables') @property @@ -281,6 +284,32 @@ class Host(CommonModelNameNotUnique): qs = qs | group.all_parents return qs + def update_cached_values(self): + cacheable_data = {"%s_all_groups" % self.id: [{'id': g.id, 'name': g.name} for g in self.all_groups.all()], + "%s_groups" % self.id: [{'id': g.id, 'name': g.name} for g in self.groups.all()], + "%s_recent_jobs" % self.id: [{'id': j.job.id, 'name': j.job.job_template.name, 'status': j.job.status, 'finished': j.job.finished} \ + for j in self.job_host_summaries.all().order_by('-created')[:5]]} + cache.set_many(cacheable_data) + return cacheable_data + + def get_cached_summary_values(self): + summary_data = cache.get_many(['%s_all_groups' % self.id, '%s_groups' % self.id, '%s_recent_jobs' % self.id]) + + rebuild_cache = False + for key in summary_data: + if summary_data[key] is None: + rebuild_cache = True + break + if rebuild_cache: + summary_data = self.update_cached_values() + summary_data_actual = dict(all_groups=summary_data['%s_all_groups' % self.id], + groups=summary_data['%s_groups' % self.id], + recent_jobs=summary_data['%s_recent_jobs' % self.id]) + return summary_data_actual + + def clear_cached_values(self): + cache.delete_many(["%s_all_groups" % self.id, "%s_groups" % self.id, "%s_recent_jobs" % self.id]) + # Use .job_host_summaries.all() to get jobs affecting this host. # Use .job_events.all() to get events affecting this host. @@ -374,10 +403,10 @@ class Group(CommonModelNameNotUnique): continue for host in group.hosts.all(): host.groups.remove(group) - host_inv_sources = host.inventory_sources - for inv_source in group.inventory_sources: + host_inv_sources = host.inventory_sources.all() + for inv_source in group.inventory_sources.all(): if inv_source in host_inv_sources: - host_inv_sources.remove(inv_source) + host.inventory_sources.remove(inv_source) if host.groups.count() < 1: marked_hosts.append(host) for childgroup in group.children.all(): diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 7d98320716..cff8ef8f27 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -223,6 +223,15 @@ EMAIL_HOST_USER = '' EMAIL_HOST_PASSWORD = '' EMAIL_USE_TLS = False +# Memcached django cache configuration +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', + 'LOCATION': '127.0.0.1:11211', + 'TIMEOUT': 864000, + } +} + # Use Django-Debug-Toolbar if installed. try: import debug_toolbar