Skip to content
This repository was archived by the owner on Jun 27, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ django-netjsongraph

.. image:: https://badge.fury.io/py/django-netjsongraph.svg
:target: http://badge.fury.io/py/django-netjsongraph

.. image:: https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square
:target: https://gitter.im/openwisp/general

Expand Down Expand Up @@ -276,6 +276,20 @@ Setting this to ``False`` will disable this feature.
Path of the visualizer css file. Allows customization of css according to user's
preferences.

``NETJSONGRAPH_NODE_EXPIRATION``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

+--------------+--------------------------------+
| **type**: | ``int`` |
+--------------+--------------------------------+
| **default**: | ``False`` |
+--------------+--------------------------------+

If a node has not been modified since the days specified and if it has no links,
it will be deleted by the ``update_topology`` management command. This depends on
``NETJSONGRAPH_LINK_EXPIRATION`` being enabled.
Replace ``False`` with an integer to enable the feature.

Overriding visualizer templates
-------------------------------

Expand Down
23 changes: 23 additions & 0 deletions django_netjsongraph/base/node.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import json
from collections import OrderedDict
from datetime import timedelta

from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.functional import cached_property
from django.utils.timezone import now
from jsonfield import JSONField
from rest_framework.utils.encoders import JSONEncoder

from .. import settings
from ..utils import print_info
from .base import TimeStampedEditableModel


Expand Down Expand Up @@ -122,3 +126,22 @@ def count_address(cls, address, topology):
address = '{0};'.format(address)
return cls.objects.filter(topology=topology,
addresses__contains=address).count()

@classmethod
def delete_expired_nodes(cls):
"""
deletes nodes that have not been connected to the network
for more than ``NETJSONGRAPH__EXPIRATION`` days
"""
NODE_EXPIRATION = settings.NODE_EXPIRATION
LINK_EXPIRATION = settings.LINK_EXPIRATION
if NODE_EXPIRATION not in [False, None] and LINK_EXPIRATION not in [False, None]:
expiration_date = now() - timedelta(days=int(NODE_EXPIRATION))
expired_nodes = cls.objects.filter(modified__lt=expiration_date,
source_link_set__isnull=True,
target_link_set__isnull=True)
expired_nodes_length = len(expired_nodes)
if expired_nodes_length:
print_info('Deleting {0} expired nodes'.format(expired_nodes_length))
for node in expired_nodes:
node.delete()
1 change: 1 addition & 0 deletions django_netjsongraph/base/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ def update_all(cls, label=None):
with log_failure('update', topology):
topology.update()
cls().link_model.delete_expired_links()
cls().node_model.delete_expired_nodes()

@classmethod
def save_snapshot_all(cls, label=None):
Expand Down
1 change: 1 addition & 0 deletions django_netjsongraph/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
SIGNALS = getattr(settings, 'NETJSONGRAPH_SIGNALS', None)
TIMEOUT = getattr(settings, 'NETJSONGRAPH_TIMEOUT', 8)
LINK_EXPIRATION = getattr(settings, 'NETJSONGRAPH_LINK_EXPIRATION', 60)
NODE_EXPIRATION = getattr(settings, 'NETJSONGRAPH_NODE_EXPIRATION', False)
VISUALIZER_CSS = getattr(settings, 'NETJSONGRAPH_VISUALIZER_CSS', 'netjsongraph/css/style.css')
45 changes: 45 additions & 0 deletions django_netjsongraph/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,51 @@ def test_delete_expired_links(self):
self.assertEqual(self.node_model.objects.count(), 2)
self.assertEqual(self.link_model.objects.count(), 0)

@responses.activate
def test_delete_expired_nodes(self):
NODE_EXPIRATION = getattr(settings, 'NODE_EXPIRATION')
# Test with the default value(False)
# Should not delete
setattr(settings, 'NODE_EXPIRATION', False)
t = self.topology_model.objects.first()
t.parser = 'netdiff.NetJsonParser'
t.save()
expired_date = now() - timedelta(days=60)
n1 = self.node_model.objects.all()[0]
n2 = self.node_model.objects.all()[1]
self.node_model.objects.filter(pk=n1.pk).update(created=expired_date,
modified=expired_date)
self.node_model.objects.filter(pk=n2.pk).update(created=expired_date,
modified=expired_date)
empty_topology = json.dumps({
"type": "NetworkGraph",
"protocol": "OLSR",
"version": "0.8",
"metric": "ETX",
"nodes": [],
"links": []
})
responses.add(responses.GET,
'http://127.0.0.1:9090',
body=empty_topology,
content_type='application/json')
self.topology_model.update_all('testnetwork')
self.assertEqual(self.node_model.objects.count(), 2)

# Test with a custom value
# Should delete
setattr(settings, 'NODE_EXPIRATION', 60)
expired_date = now() - timedelta(days=settings.NODE_EXPIRATION+10)
self.node_model.objects.filter(pk=n1.pk).update(created=expired_date,
modified=expired_date)
self.node_model.objects.filter(pk=n2.pk).update(created=expired_date,
modified=expired_date)
self.topology_model.update_all('testnetwork')
self.assertEqual(self.node_model.objects.count(), 0)
self.assertEqual(self.link_model.objects.count(), 0)
# Set the setting to it's original value
setattr(settings, 'NODE_EXPIRATION', NODE_EXPIRATION)

@responses.activate
def test_delete_expired_disabled(self):
t = self.topology_model.objects.first()
Expand Down