Git Product home page Git Product logo

openwisp / openwisp-network-topology Goto Github PK

View Code? Open in Web Editor NEW
150.0 17.0 65.0 39.39 MB

Network topology collector and visualizer. Collects network topology data from dynamic mesh routing protocols or other popular networking software like OpenVPN, allows to visualize the network graph, save daily snapshots that can be viewed in the future and more.

Home Page: http://openwisp.org

License: BSD 3-Clause "New" or "Revised" License

Python 94.09% HTML 2.86% Shell 0.14% CSS 1.96% JavaScript 0.95%
mesh-networks netjson openwisp network-graph django topology network-visualization hacktoberfest

openwisp-network-topology's Issues

[admin] Integrate topology visualizer in admin

Integrate topology visualizer in the admin in some way. A good way would be a button that displays an overlay like we do in openwisp-controller for the preview feature, but you may take a shortcut and just link the visualizer in the frontend: it depends from how much you want to learn:

  1. just adding a link to the visualizer in the frontend is a shortcut that will be fast to implement and won't teach you much
  2. visualizer in overlay will take a few days longer but will teach you stuff you probably don't know about django's internals

You may also consider to do both in a very agile way, first you quickly implement 1 and then you go ahead and implement 2, this approach can help you learn more about incremental development and fast iteration!

The choice is up to you @rohithasrk.

[bug] object has no attribute 'label' when receiving topology data

I got two exceptions which seem related. I'm not sure how to replicate this.

AttributeError: 'int' object has no attribute 'label'

AttributeError: 'int' object has no attribute 'label'
  File "django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "rest_framework/views.py", line 505, in dispatch
    response = self.handle_exception(exc)
  File "rest_framework/views.py", line 465, in handle_exception
    self.raise_uncaught_exception(exc)
  File "rest_framework/views.py", line 476, in raise_uncaught_exception
    raise exc
  File "rest_framework/views.py", line 502, in dispatch
    response = handler(request, *args, **kwargs)
  File "openwisp_network_topology/api/views.py", line 70, in post
    topology.receive(request.data)
  File "openwisp_network_topology/base/topology.py", line 352, in receive
    self.update(data)
  File "openwisp_network_topology/base/topology.py", line 287, in update
    self._update_added_items(diff['added'])
  File "openwisp_network_topology/base/topology.py", line 193, in _update_added_items
    self._update_node_properties(node, node_dict, section='added')
  File "openwisp_network_topology/base/topology.py", line 230, in _update_node_properties
    if node.label != node_dict['label']:

AttributeError: 'NoneType' object has no attribute 'label'

AttributeError: 'NoneType' object has no attribute 'label'
  File "django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "rest_framework/views.py", line 505, in dispatch
    response = self.handle_exception(exc)
  File "rest_framework/views.py", line 465, in handle_exception
    self.raise_uncaught_exception(exc)
  File "rest_framework/views.py", line 476, in raise_uncaught_exception
    raise exc
  File "rest_framework/views.py", line 502, in dispatch
    response = handler(request, *args, **kwargs)
  File "openwisp_network_topology/api/views.py", line 70, in post
    topology.receive(request.data)
  File "openwisp_network_topology/base/topology.py", line 352, in receive
    self.update(data)
  File "openwisp_network_topology/base/topology.py", line 289, in update
    self._update_changed_items(diff['changed'])
  File "openwisp_network_topology/base/topology.py", line 270, in _update_changed_items
    self._update_node_properties(node, node_dict, section=section)
  File "openwisp_network_topology/base/topology.py", line 230, in _update_node_properties
    if node.label != node_dict['label']:

[bug] Receive API broken

The receive API resource doesn't work because the organization for new nodes and links is not set.

[change] Add set of properties meant to be manipulated by the user in Node and Link

Right now, properties of nodes and links are editable by users, but get mixed with properties which are automatically determined from the topology data, which is confusing for the user.

Here's what I think it would be best:

  • add a user_properties field on Node and Link, ensure this field uses the django-flat-json-widget in the admin, place the new field after properties, label it something like user defined properties, the help_text could be "If you need to add additional data to this node | link (word depends on model) use this field"
  • make the old properties field readonly, and show it in the UI as a list of keys and values
  • in the model, make sure the new user properties are added to the other properties when generating the json data, but make sure these user generated properties are not shown when the original argument is passed as True
  • ensure there's a test which checks the user properties are displayed in the json data, one test for node and one test for link

[test] Avoid error logging to print noisy output during tests

The test suite logs error to the console which is not ideal. We should capture these logs like we did in other modules.

 $ ./runtests.py 
Found 143 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
................Failed to perform update topology admin action on <Topology: TestNetwork - NetJSON NetworkGraph>: TopologyRetrievalError
See error log for more information

..................................................................................Failed to perform add on <Node: 192.168.0.1>: IntegrityError
See error log for more information

................................/home/pandafy/openwisp/venv-network-topology/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1409: RuntimeWarning: DateTimeField Ca.validity_start received a naive datetime (2022-02-02 00:00:00) while time zone support is active.
  warnings.warn("DateTimeField %s received a naive datetime (%s)"
/home/pandafy/openwisp/venv-network-topology/lib/python3.8/site-packages/django/db/models/fields/__init__.py:1409: RuntimeWarning: DateTimeField Cert.validity_start received a naive datetime (2022-02-02 00:00:00) while time zone support is active.
  warnings.warn("DateTimeField %s received a naive datetime (%s)"
........

Checkout the following functions:


Take reference from openwisp/openwisp-controller#366

[requirements] Update dependencies & drop python 2 support

Python2 is very close to the end of it's lifecycle, it's time we drop the support for Python 2.

To do that,

  1. We need to update all the dependencies to python3.
  2. Remove code that exists for python 2 support.
  3. Remove python2 from README & any documentation.

[bug] Link and Node should belong to same topologies

It is possible to create link in a topology with nodes belonging to different topology.

This can be seen in the following setUp method of a tes class

def setUp(self):
org = self._create_org()
t = self._create_topology(organization=org)
topology, device, cert = self._create_test_env(parser='netdiff.OpenvpnParser')
node1 = self._init_test_node(topology, common_name=cert.common_name)
node2 = self._init_test_node(topology, addresses=['netjson_id2'], label='test2')
link = Link(
source=node1,
target=node2,
topology=topology,
organization=topology.organization,
cost=1,
)
link.full_clean()
link.save()
self._create_link(topology=t, source=node1, target=node2)
self.client.force_login(self.user_model.objects.get(username='admin'))

On line 327, the node belongs to topology object while the link is getting created with t object.

We need to add a validation test in AbstractLink class.

[release] Release new minor version

Release until openwisp-notifications 0.3 and openwisp-controller 0.8 are released, clean up .travis.yml and replace markdown in requirements-tests.txt with openwisp-notifications.

[feature] Integration with openwisp-controller and openwisp-monitoring

  • allow creating relationships between topology nodes and controller devices
  • add support for automatically determining the device to node relationship with openvpn (using the common name attribute)
  • when a link changes its status, update the management IP and then trigger the device checks if openwisp-monitoring is installed
  • find a way to show the device name as node label in the visualizer

[change] Remove redundant code for checking view permissions

class HasGetMethodPermission(BasePermission):
def has_permission(self, request, view):
return self.check_permission(request)
def has_object_permission(self, request, view, obj):
return self.check_permission(request)
def check_permission(self, request):
user = request.user
app_label = Topology._meta.app_label.lower()
model = Topology._meta.object_name.lower()
change_perm = f'{app_label}.change_{model}'
view_perm = f'{app_label}.view_{model}'
if user.is_authenticated:
if user.is_superuser or request.method != 'GET':
return True
if request.method == 'GET' and (
user.has_permission(change_perm) or user.has_permission(view_perm)
):
return True
return False

I guess, this portion of code does the same thing as what we did recently in this PR openwisp/openwisp-users#251

So, will it not better if we simply import it from there?

Revise django-model-utils’s version constraint to remove the potential dependency conflicts

Hi, as shown in the following full dependency graph of openwisp-network-topology, direct dependency django-netjsongraph(required: >=0.4.2,<0.5.0, installed 0.4.3) depends on django-model-utils (no version constraint), while the installed version of openwisp-utils(0.2.2) requires django-model-utils>=3.1.2,<3.3.0.

According to Pip's “first found wins” installation strategy, django-model-utils 3.2.0 is the actually installed version.

Although the first found package version django-model-utils 3.2.0 just satisfies the later dependency constraint (django-model-utils>=3.1.2,<3.3.0), it will lead to a build failure once developers release a appdirs whose version number is greater than 3.3.0.

Dependency tree--------

openwisp-network-topology -0.2.1
| +-django-netjsongraph(version range:>=0.4.2,<0.5.0)
| | +-django(version range:>=1.11,<2.1)
| | +-djangorestframework(version range:>=3.3,<3.8)
| | +-django-model-utils(version range:*)
| | +-netdiff(version range:>=0.6.0,<0.7)
| | +-openwisp-utils(version range:>=0.2,<0.3)
| | | +-django-model-utils(version range:>=3.1.2,<3.3.0)
| | +-jsonfield(version range:*)
| | +-six(version range:*)
| +-openwisp-users(version range:>=0.1.8,<0.2)
| | +-django-organizations(version range:>=1.0.0,<1.2.0)
| | +-django-extensions(version range:>=1.7.5,<2.2)
| | +-django-allauth(version range:>=0.35.0,<0.37.0)
| +-openwisp-utils(version range:>=0.2,<0.3)
| | +-django-model-utils(version range:>=3.1.2,<3.3.0)

Thanks for your attention.
Best,
Neolith

[gsoc2020] Merge django-netjsongraph into openwisp-network-topology

  • Merge django-netjsongraph into openwisp-network-topology
  • Migrate the django settings of each module so that the naming is consistent. (eg: NETJSONCONFIG_[SETTING_NAME] -> OPENWISP_CONTROLLER_[SETTING_NAME])
  • Keep backward compatibility for setting names but log a warning to encourage the users to upgrade the name of the setting to the new name.
  • Implement as easy as possible extensibility of Django modules.
  • Add sample_app for testing extensibility with some changes.
  • Update documentation

Fix unusual fails of travis builds

We see that a test by the name,
test_multiple_receive_remove(openwisp_network_topology.tests.test_topology.TestTopology) fails unusually in the travis builds. There is a need to investigate and fix it.

[API] Create API endpoints for `network-topology` module

Implement a RESTfull API for openwisp-network-topology module, the API will allow to perform CRUD(Create, Retrieve, Update, Destroy) operations on these Model's:-

  • Topology
  • Node
  • Link

Endpoints:-

  • Topology
    • GET api/v1/topology/ (List topologies)
    • PUT/PATCH/DELETE api/v1/topology/{pk}/ (Change topology detail)
  • Node
    • GET api/v1/node/ (List nodes)
    • PUT/PATCH/DELETE api/v1/node/{pk}/ (Change node detail)
  • Link
    • GET api/v1/links/ (List links)
    • PUT/PATCH/DELETE api/v1/links/{pk}/ (Change link detail)

All of the above API endpoints:-

  • Will have to respect multi-tenancy which can be achieved by various serializer classes present FilterSerializerByOrgMembership, FilterSerializerByOrgManaged, and FilterSerializerByOrgOwned in the openwisp-users module.
  • Must be paginated.
  • Respect django-permission system and also it may be required to inherit the custom permission and authentication classes from the openwisp-users module to restrict API usage for security reasons. Some of the important custom permission classes are IsOrganizationMember, IsOrganizationManager, IsOrganizationOwner,DjangoModelPermissions, IsAuthenticated, and many more.
  • Add authentication classes in every endpoint to allow only the authenticated users to get access to all the available endpoints. BearerAuthentication and SessionAuthentication can be added to achieve this.
  • All the serializer classes should be validated by the class ValidatedModelSerializer inheriting it from openwisp-utils.
  • All the validation of the model should be preserved, also more validation methods may be introduced.
  • Use transaction method wherever necessary when the database operation is taking place.
  • Shall be taken care of proper query optimization to not slow down the API and reduce the number of queries performed while fetching data from the database.
  • Add proper tests for all the endpoints and make sure the coverage doesn't decrease.
  • Handle errors gracefully and return HTTP response codes that indicate what kind of error occurred to eliminate confusion for API users.
  • Follow Django REST Framework proper coding practices and RESTful principles for building all the API’s.
  • Add proper documentation for all the endpoints both in the README and OpenAPI (DRF Yasg).

[release] 0.4.0

  • release netdiff
  • update minimum netdiff version
  • ensure change log is up to date
  • tag
  • publish on pypi

[change] Allow shared topologies

Sometimes a single management VPN is used for an openwisp instance having multiple organizations.

In this case having a topology object which can be flagged as shared would be useful, also for the purpose of the integration with ow-controller and ow-monitoring.

Therefore we should:

  • allow Topology objects to be shareable
  • update the controller integration to work when the topology is shared (we need to create a test for this use cases and ensure DeviceNode objects are created correctly)

[network-topology] Replace DeviceNode data migration with management command

When using the integration with openwisp-controller, instead of using a data migration to create the initial DeviceNode objects, we should use a management command, because the logic to create the initial DeviceNode objects is in a method which cannot be used during a migration because concrete models cannot be used during data migrations without risking future issues when adding/removing fields.

We'll also need to add a few lines in the readme regarding this command (when to use it and an example).

[change] Require authentication for views

Right now the views (visualizer and API) are available to anyone.
This was done mainly because this module was used by community owned mesh network.

But now this module is also used to monitor private networks and we need to close it by default.
In the API we can use IsAuthenticated, DjangoPermissions and we should check the organization as well.
In the visualizer views we should use an equivalent mechanism

It should still be possible to disable auth via settings, eg: OPENWISP_NETWORK_TOPOLOGY_API_AUTH_REQUIRED.

[bug] Fix failing test

tests are failing because of the absence of openwisp_notifications as one of the installed apps in TestMonitoringIntegration

Detect changes in nodes and links

Once openwisp/netdiff#88 is merged, add support for it here, ensuring changes in nodes and links are detected (write a test for it).

Once the build passes and the PR is ready to be merged, we can release a new version of netdiff and increase the minimum version required here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.