def save_object(self, obj_type, obj_id, values={}): """ Save cache data for an object in the database. """ # If the ACL object exists if len(ACLObjects.get_values(obj_type)) > 0: try: # If supplied, values argument must be a dictionary if values and not isinstance(values, dict): self.log.error('Failed to cache object <%s> of type <%s>, values keyword must contain a dictionary' % (obj_id, obj_type)) return False # Get the ACL object definition acl_object = ACLObjects.get(type=obj_type) # Get an instance of the object class obj_mod = importlib.import_module(getattr(acl_object, 'obj_mod')) obj_class = getattr(obj_mod, getattr(acl_object, 'obj_cls')) obj_key = getattr(acl_object, 'obj_key') # Create the object filter obj_filter = {} obj_filter[obj_key] = obj_id # Define the cache object filter cache_filter = { 'object_type': obj_type, 'object_id': obj_id } # If the object doesn't exist anymore if not obj_class.objects.filter(**obj_filter).count(): # If an expired cache entry exists if DBClusterCache.objects.filter(**cache_filter).count(): self.log.info('Base object <%s> of type <%s> no longer exists, flushing cached entry' % (obj_id, obj_type)) # Flush the old cache entry DBClusterCache.objects.filter(**cache_filter).delete() # Expired cache object cleared return True # Get the object details obj_details = base64.encodestring(json.dumps(list(obj_class.objects.filter(**obj_filter).values(**values))[0], cls=DjangoJSONEncoder)) obj_size = sys.getsizeof(obj_details) obj_hash = hashlib.md5(obj_details).hexdigest() # If the object already has a cache entry if DBClusterCache.objects.filter(**cache_filter).count(): # Get the current cache entry cache_row = list(DBClusterCache.objects.filter(**cache_filter).values())[0] # If the cached data hasn't changed if cache_row['object_hash'] == obj_hash: return self.log.info('Cached data unchanged for object <%s> of type <%s>' % (obj_id, obj_type)) # Update the cached data DBClusterCache.objects.filter(**cache_filter).update(object_data=obj_details, object_size=obj_size) # Create a new cache entry else: # Create the cache entry DBClusterCache( object_type = acl_object, object_id = obj_id, object_data = obj_details, object_hash = obj_hash, object_size = obj_size ).save() # Object successfull cached self.log.info('Cached data for object <%s> of type <%s>: bytes_cached=%s, hash=%s' % (obj_id, obj_type, str(obj_size), obj_hash)) # Critical error when caching object except Exception as e: self.log.exception('Failed to cache object <%s> of type <%s>: %s' % (obj_id, obj_type, str(e))) # ACL object does not exist else: self.log.error('Cannot cache object <%s> of type <%s>, ACL object type not found' % (obj_id, obj_type))
def _get_from_model(self, obj_type, obj_id, values={}, filters={}): """ Retrieve object details directly from the model. @param obj_type: The type of object to retrieve @type obj_type: str @param obj_id: The ID of the object to retrieve @type obj_id: str @param values: Extra parameters to pass to the values QuerySet method @type values: dict @param filters: Extra filter parameters @type filters: dict """ self.log.info('Retrieving object data from model: type=%s, id=%s' % (obj_type, repr(obj_id))) # Get the ACL object definition acl_object = ACLObjects.get(obj_type) # Get an instance of the object class obj_mod = importlib.import_module(getattr(acl_object, 'obj_mod')) obj_class = getattr(obj_mod, getattr(acl_object, 'obj_cls')) obj_key = getattr(acl_object, 'obj_key') # Create the object filter obj_filter = {} # If retrieving a single object if obj_id: obj_filter[obj_key] = obj_id # Create the query object query_obj = obj_class.objects # If an object filter is defined if obj_filter: self.log.info('Applying object filters: %s' % json.dumps(obj_filter)) query_obj = query_obj.filter(**obj_filter) # If a values filter is defined if filters: self.log.info('Applying value filters: %s' % json.dumps(filters)) query_obj = query_obj.filter(**filters) # If no filters were defined if not obj_filter and not filters: self.log.info('No filters defined, retrieving all objects') query_obj = query_obj.all() # Log the constructed query object self.log.info('Constructed object query: %s' % str(query_obj)) # Attempt to retrieve the object obj_details = list(query_obj.values()) # Log the retrieved details log_data = json.dumps(obj_details, cls=DjangoJSONEncoder) self.log.info('Retrieved object details: length=%s, data=%s' % (len(log_data), (log_data[:75] + '...') if len(log_data) > 75 else log_data)) # If the object doesn't exist if len(obj_details) == 0: return None # Return the object details if not obj_id: return obj_details return obj_details[0]