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
5from infra.models import Machine
6from infra.models import Event
8import logging
9logger = logging.getLogger('mars')
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 ]
22 exclude_paths = []
23 for excl in exclusions:
24 exclude_paths.append('root.' + excl)
25 return DeepDiff(m1, m2, exclude_paths=exclude_paths)
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
34 serialized_diff = diff.to_json()
35 changes = diff.get('values_changed', {})
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)
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
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)