Improved model policies. Handles deletions explicitly, support for custom delete policies.
diff --git a/xos/model_policy.py b/xos/model_policy.py
index 3fa7218..9333adc 100644
--- a/xos/model_policy.py
+++ b/xos/model_policy.py
@@ -11,62 +11,105 @@
 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:
-		if (d.updated < o.updated):
-			d.save(update_fields=['updated'])
-	except AttributeError,e:
-		raise e
-	
+    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
+
 def delete_if_inactive(d, o):
-	#print "Deleting %s (%s)"%(d,d.__class__.__name__)
-	# d.delete()	
-	return
+    try:
+        d.delete()
+        print "Deleted %s (%s)"%(d,d.__class__.__name__)
+    except:
+        pass
+    return
+
 
 @atomic
 def execute_model_policy(instance, deleted):
-	# Automatic dirtying
-	walk_inv_deps(update_dep, instance)
+    # Automatic dirtying
+    if (instance in bad_instances):
+        return
 
-	sender_name = instance.__class__.__name__
-	policy_name = 'model_policy_%s'%sender_name
-	noargs = False
+    # These are the models whose children get deleted when they are
+    delete_policy_models = ['Slice','Sliver','Network']
+    sender_name = instance.__class__.__name__
+    policy_name = 'model_policy_%s'%sender_name
+    noargs = False
 
-	if deleted:
-		walk_inv_deps(delete_if_inactive, instance)
-	else:
-		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:
-				policy_handler.handle(instance)
-		except:
-			logger.log_exc("Model Policy Error:") 
-			print "Policy Exceution Error"
+    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)
 
-	instance.policed=datetime.now()
+
+
+    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 run_policy():
-        from core.models import Sliver,Slice,Controller,Network,User,SlicePrivilege,Site,SitePrivilege,Image,ControllerSlice,ControllerUser,ControllerSite
-	while (True):
-		start = time.time()
-		models = [Sliver,Slice, Controller, Network, User, SlicePrivilege, Site, SitePrivilege, Image, ControllerSlice, ControllerSite, ControllerUser]
-		objects = []
-		
-		for m in models:
-        		res = m.objects.filter(Q(policed__lt=F('updated')) | Q(policed=None))
-			objects.extend(res)	
+    from core.models import Sliver,Slice,Controller,Network,User,SlicePrivilege,Site,SitePrivilege,Image,ControllerSlice,ControllerUser,ControllerSite
+    while (True):
+        start = time.time()
+        models = [Sliver,Slice, Controller, Network, User, SlicePrivilege, Site, SitePrivilege, Image, ControllerSlice, ControllerSite, ControllerUser]
+        objects = []
+        deleted_objects = []
 
-		for o in objects:
-			print "Working on %r"%o
-			execute_model_policy(o, False)
-		
-		
-		if (time.time()-start<1):
-			time.sleep(1)	
+        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)
+
+
+        if (time.time()-start<1):
+            time.sleep(1)