blob: ced785eb0d9477a44fa61c67feea0d8fbac4be9d [file] [log] [blame]
from django.db.models.signals import post_save
from django.dispatch import receiver
import pdb
from dependency_walker import *
import model_policies
from util.logger import logger
from datetime import datetime
import time
from core.models import *
from django.db import reset_queries
from django.db.transaction import atomic
from django.db.models import F, Q
modelPolicyEnabled = True
bad_instances=[]
def EnableModelPolicy(x):
global modelPolicyEnabled
modelPolicyEnabled = x
def update_wp(d, o):
try:
save_fields = []
if (d.write_protect != o.write_protect):
d.write_protect = o.write_protect
save_fields.append('write_protect')
if (save_fields):
d.save(update_fields=save_fields)
except AttributeError,e:
raise e
def update_dep(d, o):
try:
print 'Trying to update %s'%d
save_fields = []
if (d.updated < o.updated):
save_fields = ['updated']
if (save_fields):
d.save(update_fields=save_fields)
except AttributeError,e:
raise e
except Exception,e:
logger.info('Could not save %r. Exception: %r'%(d,e))
def delete_if_inactive(d, o):
try:
d.delete()
print "Deleted %s (%s)"%(d,d.__class__.__name__)
except:
pass
return
@atomic
def execute_model_policy(instance, deleted):
# Automatic dirtying
if (instance in bad_instances):
return
# These are the models whose children get deleted when they are
delete_policy_models = ['Slice','Instance','Network']
sender_name = instance.__class__.__name__
policy_name = 'model_policy_%s'%sender_name
noargs = False
if (not deleted):
walk_inv_deps(update_dep, instance)
walk_deps(update_wp, instance)
elif (sender_name in delete_policy_models):
walk_inv_deps(delete_if_inactive, instance)
try:
policy_handler = getattr(model_policies, policy_name, None)
logger.error("POLICY HANDLER: %s %s" % (policy_name, policy_handler))
if policy_handler is not None:
if (deleted):
try:
policy_handler.handle_delete(instance)
except AttributeError:
pass
else:
policy_handler.handle(instance)
except:
logger.log_exc("Model Policy Error:")
try:
instance.policed=datetime.now()
instance.save(update_fields=['policed'])
except:
logging.error('Object %r is defective'%instance)
bad_instances.append(instance)
def noop(o,p):
pass
def run_policy():
while (True):
start = time.time()
run_policy_once()
if (time.time()-start<1):
time.sleep(1)
def run_policy_once():
from core.models import Instance,Slice,Controller,Network,User,SlicePrivilege,Site,SitePrivilege,Image,ControllerSlice,ControllerUser,ControllerSite
models = [Instance,Slice, Controller, Network, User, SlicePrivilege, Site, SitePrivilege, Image, ControllerSlice, ControllerSite, ControllerUser]
objects = []
deleted_objects = []
for m in models:
res = m.objects.filter(Q(policed__lt=F('updated')) | Q(policed=None))
objects.extend(res)
res = m.deleted_objects.filter(Q(policed__lt=F('updated')) | Q(policed=None))
deleted_objects.extend(res)
for o in objects:
execute_model_policy(o, o.deleted)
for o in deleted_objects:
execute_model_policy(o, True)
# Reap non-sync'd models here
reaped = [Slice]
for m in reaped:
dobjs = m.deleted_objects.all()
for d in dobjs:
deps = walk_inv_deps(noop, d)
if (not deps):
print 'Purging object %r'%d
d.delete(purge=True)
try:
reset_queries()
except:
# this shouldn't happen, but in case it does, catch it...
logger.log_exc("exception in reset_queries")