Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from deepdiff import DeepDiff 

2from django.db.models.signals import pre_save, post_save 

3from django.dispatch import receiver 

4 

5from infra.models import Machine 

6from infra.models import Event 

7 

8import logging 

9logger = logging.getLogger('mars') 

10 

11 

12def machine_diff(m1, m2): 

13 exclusions = [ 

14 # Django-specific field 

15 '_state', 

16 # Auto generated, not to be depended on! 

17 'full_name', 

18 # Not interesting changes 

19 'last_updated', 'first_seen', 'id', 

20 ] 

21 

22 exclude_paths = [] 

23 for excl in exclusions: 

24 exclude_paths.append('root.' + excl) 

25 return DeepDiff(m1, m2, exclude_paths=exclude_paths) 

26 

27 

28def dispatch_events_for_diff(diff, machine): 

29 # You can not add a foreign key relation to something that isn't 

30 # saved, the error that comes when you do is very weird, so fail 

31 # now! 

32 assert machine.pk is not None 

33 

34 serialized_diff = diff.to_json() 

35 changes = diff.get('values_changed', {}) 

36 

37 if 'root.is_retired' in changes: 

38 before, after = changes['root.is_retired']['old_value'], \ 

39 changes['root.is_retired']['new_value'] 

40 if not before and after: 

41 logger.debug(f"{machine} has been retired, generating a retirement event...") 

42 return Event.objects.create( 

43 category=Event.CATEGORY_MACHINE_RETIRED, 

44 machine=machine, 

45 diff=serialized_diff) 

46 logger.debug(f"{machine} has been updated") 

47 return Event.objects.create( 

48 category=Event.CATEGORY_MACHINE_UPDATED, 

49 machine=machine, 

50 diff=serialized_diff) 

51 

52 

53@receiver(pre_save, sender=Machine) 

54def machine_pre_save_callback(sender, instance, **kwargs): 

55 new = instance 

56 try: 

57 old = sender.objects.get(pk=new.pk) 

58 except sender.DoesNotExist: 

59 instance.__mars_diff__ = '{}' 

60 else: 

61 diff = machine_diff(old, new) 

62 instance.__mars_diff__ = diff 

63 

64 

65@receiver(post_save, sender=Machine) 

66def machine_post_save_callback(sender, instance, created, **kwargs): 

67 assert hasattr(instance, '__mars_diff__') 

68 diff = instance.__mars_diff__ 

69 if created: 

70 logger.debug(f"{instance} has been created") 

71 return Event.objects.create( 

72 category=Event.CATEGORY_MACHINE_CREATED, 

73 machine=instance, 

74 diff=diff) 

75 else: 

76 dispatch_events_for_diff(diff, instance)