diff --git a/README.rst b/README.rst index b94cfbf..1f5ab87 100644 --- a/README.rst +++ b/README.rst @@ -1,817 +1,61 @@ -============= openwisp-ipam ============= .. image:: https://github.com/openwisp/openwisp-ipam/actions/workflows/ci.yml/badge.svg?branch=master - :target: https://github.com/openwisp/openwisp-ipam/actions/workflows/ci.yml?query=workflow%3AOpenWISP+Ipam+CI+Build%22 - :alt: CI Build status + :target: https://github.com/openwisp/openwisp-ipam/actions/workflows/ci.yml?query=workflow%3AOpenWISP+Ipam+CI+Build%22 + :alt: CI Build status .. image:: https://coveralls.io/repos/openwisp/openwisp-ipam/badge.svg - :target: https://coveralls.io/r/openwisp/openwisp-ipam - :alt: Coverage + :target: https://coveralls.io/r/openwisp/openwisp-ipam + :alt: Coverage .. image:: https://img.shields.io/pypi/v/openwisp-ipam - :target: https://pypi.org/project/openwisp-ipam - :alt: PyPI + :target: https://pypi.org/project/openwisp-ipam + :alt: PyPI .. image:: https://img.shields.io/librariesio/release/github/openwisp/openwisp-ipam - :target: https://libraries.io/github/openwisp/openwisp-ipam#dependencies - :alt: Dependency monitoring + :target: https://libraries.io/github/openwisp/openwisp-ipam#dependencies + :alt: Dependency monitoring .. image:: https://github.com/openwisp/openwisp-ipam/raw/docs/docs/subnet_demo.gif - :alt: Feature Highlights - -.. contents:: **Table of Contents**: - :backlinks: none - :depth: 2 - -Available Features -****************** - -* IPv4 and IPv6 IP address management -* IPv4 and IPv6 Subnet management -* Automatic free space display for all subnets -* Visual display for a specific subnet -* IP request module -* REST API for CRUD operations and main features -* Possibility to search for an IP or subnet -* CSV Import and Export of subnets and their IPs - -Project Goals -************* - -* provide basic features of IP Address management as a reusable django app -* integrate this module in the rest of the OpenWISP ecosystem -* allow standalone usage (without the rest of OpenWISP) -* provide ways to extended the core features in order to create derivatives - -Dependencies -************ - -* Python 3.8 or higher -* Django 3.2 or higher (except 4.0) -* Django REST Framework (for the REST API) -* openwisp-users -* swapper - -Install stable version -********************** - -.. code-block:: shell - - pip install openwisp-ipam - -Install development version -*************************** - -Install tarball: - -.. code-block:: shell - - pip install https://github.com/openwisp/openwisp-ipam/tarball/master - -Alternatively you can install via pip using git: - -.. code-block:: shell - - pip install -e git+git://github.com/openwisp/openwisp-ipam#egg=openwisp-ipam - -Installation for development -**************************** - -Install ``openwisp-ipam`` for development using following commands: - -.. code-block:: shell - - git clone https://github.com/openwisp/openwisp-ipam.git - cd openwisp-ipam - pip install -e . - pip install -r requirements-test.txt - -Launch the development sever: - -.. code-block:: shell - - cd tests/ - ./manage.py migrate - ./manage.py createsuperuser - ./manage.py runserver - -You can access the admin interface at `http://127.0.0.1:8000/admin/`. - -Run Tests -========= - -Install test requirements: - -.. code-block:: shell - - pip install -r requirements-test.txt - -Then run the test suite: - -.. code-block:: shell - - # options "--keepdb" & "--parallel" are optional but - # improve time required for running tests. - ./runtests.py --keepdb --parallel - # Run tests for the sample_app - SAMPLE_APP=1 ./runtests.py --keepdb --parallel - -Visual Display of subnets -************************* - -openwisp-ipam provides a graphical representation of a subnet which shows the available free space under any subnet. - -.. image:: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/visual-display.png - -REST API -******** - -Live documentation -================== - -.. image:: https://github.com/openwisp/openwisp-ipam/raw/docs/docs/api-docs.png - -A general live API documentation (following the OpenAPI specification) is available at ``/api/v1/docs/``. - -Browsable web interface -======================= - -.. image:: https://github.com/openwisp/openwisp-ipam/raw/docs/docs/api-ui.png - -Additionally, opening any of the endpoints `listed below <#list-of-endpoints>`_ -directly in the browser will show the `browsable API interface of Django-REST-Framework -`_, -which makes it even easier to find out the details of each endpoint. - -Authentication -============== - -See openwisp-users: `authenticating with the user token -`_. - -When browsing the API via the `Live documentation <#live-documentation>`_ -or the `Browsable web page <#browsable-web-interface>`_, you can also use -the session authentication by logging in the django admin. - -Pagination -========== - -All *list* endpoints support the ``page_size`` parameter that allows paginating -the results in conjunction with the ``page`` parameter. - -.. code-block:: text - - GET /api/v1//?page_size=10 - GET /api/v1//?page_size=10&page=2 - -List of endpoints -================= - -Since the detailed explanation is contained in the `Live documentation <#live-documentation>`_ -and in the `Browsable web page <#browsable-web-interface>`_ of each endpoint, -here we'll provide just a list of the available endpoints, -for further information please open the URL of the endpoint in your browser. - -API Throttling -============== - -To override the default API throttling settings, add the following to your ``settings.py`` file: - -.. code-block:: python - - REST_FRAMEWORK = { - 'DEFAULT_THROTTLE_RATES': { - 'ipam': '100/hour', - } - } - -The rate descriptions used in ``DEFAULT_THROTTLE_RATES`` may include -``second``, ``minute``, ``hour`` or ``day`` as the throttle period. - -Get Next Available IP -===================== - -A model method to fetch the next available IP address under a specific subnet. This method can also be accessed via a REST API: `openwisp_ipam/base/models.py `_ - -GET ---- - -Returns the next available IP address under a subnet. - -.. code-block:: text - - /api/v1/ipam/subnet//get-next-available-ip/ - -Request IP -^^^^^^^^^^ - -A model method to create and fetch the next available IP address record under a subnet. - -POST ----- - -Creates a record for next available IP address and returns JSON data of that record. - -.. code-block:: text - - POST /api/v1/ipam/subnet//request-ip/ - -=========== ======================================== -Param Description -=========== ======================================== -description Optional description for the IP address -=========== ======================================== - -Response -^^^^^^^^ - -.. code-block:: json - - - { - "ip_address": "ip_address", - "subnet": "subnet_uuid", - "description": "optional description" - } - - -IpAddress-Subnet List and Create View -===================================== - -An api endpoint to retrieve or create IP addresses under a specific subnet. - -GET ---- - -Returns the list of IP addresses under a particular subnet. - -.. code-block:: text - - /api/v1/ipam/subnet//ip-address/ - -POST ----- - -Create a new ``IP Address``. - -.. code-block:: text - - /api/v1/ipam/subnet//ip-address/ - -=========== ======================================== -Param Description -=========== ======================================== -ip_address IPv6/IPv4 address value -subnet Subnet UUID -description Optional description for the IP address -=========== ======================================== - -Subnet List/Create View -======================= - -An api endpoint to create or retrieve the list of subnet instances. - -GET ---- - -Returns the list of ``Subnet`` instances. - -.. code-block:: text - - /api/v1/ipam/subnet/ - -POST ----- - -Create a new ``Subnet``. - -.. code-block:: text - - /api/v1/ipam/subnet/ - -============= ======================================== -Param Description -============= ======================================== -subnet Subnet value in CIDR format -master_subnet Master Subnet UUID -description Optional description for the IP address -============= ======================================== - -Subnet View -=========== - -An api endpoint for retrieving, updating or deleting a subnet instance. - -GET ---- - -Get details of a ``Subnet`` instance - -.. code-block:: text - - /api/v1/ipam/subnet// - -DELETE ------- - -Delete a ``Subnet`` instance - -.. code-block:: text - - /api/v1/ipam/subnet// - -PUT ---- - -Update details of a ``Subnet`` instance. - -.. code-block:: text - - /api/v1/ipam/subnet// - -============= ======================================== -Param Description -============= ======================================== -subnet Subnet value in CIDR format -master_subnet Master Subnet UUID -description Optional description for the IP address -============= ======================================== - -IP Address View -=============== - -An api endpoint for retrieving, updating or deleting a IP address instance. - -GET ---- - -Get details of an ``IP address`` instance. - -.. code-block:: text - - /api/v1/ipam/ip-address// - -DELETE ------- - -Delete an ``IP address`` instance. - -.. code-block:: text - - /api/v1/ipam/ip-address// - -PUT ---- - -Update details of an ``IP address`` instance. - -.. code-block:: text - - /api/v1/ipam/ip-address// - -=========== ======================================== -Param Description -=========== ======================================== -ip_address IPv6/IPv4 value -subnet Subnet UUID -description Optional description for the IP address -=========== ======================================== - -Export Subnet View -================== + :alt: Feature Highlights -View to export subnet data. +For a complete overview of features, refer to the `IPAM: Features +`_ section of the +OpenWISP documentation. -POST ----- +Documentation +------------- -.. code-block:: text +- `Developer documentation + `_ +- `User documentation `_ - /api/v1/ipam/subnet//export/ - -Import Subnet View -================== - -View to import subnet data. - -POST ----- - -.. code-block:: text - - /api/v1/ipam/import-subnet/ - - -Exporting and Importing Subnet -============================== - -One can easily import and export `Subnet` data and it's Ip Addresses using `openwisp-ipam`. -This works for both IPv4 and IPv6 types of networks. - -Exporting +Changelog --------- -Data can be exported via the admin interface or by using a management command. The exported data is in `.csv` file format. - -From management command -^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./manage.py export_subnet +See `Change log +`__. -This would export the subnet if it exists on the database. +Contributing +------------ -From admin interface -^^^^^^^^^^^^^^^^^^^^ +Please refer to the `OpenWISP contributing guidelines +`_. -Data can be exported from the admin interface by just clicking on the export button on the subnet's admin change view. +Support +------- -.. image:: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/export.png +See `OpenWISP Support Channels `_. -Importing +Changelog --------- -Data can be imported via the admin interface or by using a management command. -The imported data file can be in `.csv` and `.xlsx` format. While importing -data for ip addresses, the system checks if the subnet specified in the import file exists or not. -If the subnet does not exists it will be created while importing data. - -From management command -^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: shell - - ./manage.py import_subnet --file= - -From admin interface -^^^^^^^^^^^^^^^^^^^^ - -Data can be imported from the admin interface by just clicking on the import button on the subnet view. - -.. image:: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/import.png - -CSV file format -=============== - -Follow the following structure while creating `csv` file to import data. - -.. code-block:: text - - Subnet Name - Subnet Value - Organization Slug - - ip_address,description - , - , - , - -Setup (integrate in an existing Django project) -*********************************************** - -The ``settings.py`` of your project should contain the following: - -.. code-block:: python - - INSTALLED_APPS = [ - # openwisp2 modules - 'openwisp_users', - 'openwisp_ipam', - # admin - 'admin_auto_filters', - 'django.contrib.admin', - # rest framework - 'rest_framework', - 'drf_yasg', - ] - - AUTH_USER_MODEL = 'openwisp_users.User' - -Add the URLs to your main ``urls.py``: - -.. code-block:: python - - from django.contrib import admin - from django.urls import include, path - from openwisp_users.api.urls import get_api_urls as get_users_api_urls - - urlpatterns = [ - # admin URLs - path('admin/', admin.site.urls), - # IPAM API - path('', include('openwisp_ipam.urls')), - # OpenAPI docs - path('api/v1/', include('openwisp_utils.api.urls')), - # Bearer Authentication API URL - path('api/v1/', include((get_users_api_urls(), 'users'), namespace='users')), - ] - - -Then run: - -.. code-block:: shell - - ./manage.py migrate - -Extending openwisp-ipam -*********************** - -One of the core values of the OpenWISP project is `Software Reusability `_, -for this reason *openwisp-ipam* provides a set of base classes -which can be imported, extended and reused to create derivative apps. - -In order to implement your custom version of *openwisp-ipam*, -you need to perform the steps described in this section. - -When in doubt, the code in the `test project `_ and -the `sample app `_ -will serve you as source of truth: -just replicate and adapt that code to get a basic derivative of -*openwisp-ipam* working. - -If you want to add new users fields, please follow the `tutorial to extend the -openwisp-users `_. -As an example, we have extended *openwisp-users* to *sample_users* app and -added a field ``social_security_number`` in the `sample_users/models.py -`_. - -**Premise**: if you plan on using a customized version of this module, -we suggest to start with it since the beginning, because migrating your data -from the default module to your extended version may be time consuming. - -1. Initialize your custom module -================================ - -The first thing you need to do is to create a new django app which will -contain your custom version of *openwisp-ipam*. - -A django app is nothing more than a -`python package `_ -(a directory of python scripts), in the following examples we'll call this django app -``myipam``, but you can name it how you want:: - - django-admin startapp myipam - -Keep in mind that the command mentioned above must be called from a directory -which is available in your `PYTHON_PATH `_ -so that you can then import the result into your project. - -Now you need to add ``myipam`` to ``INSTALLED_APPS`` in your ``settings.py``, -ensuring also that ``openwisp_ipam`` has been removed: - -.. code-block:: python - - INSTALLED_APPS = [ - # ... other apps ... - 'openwisp_utils.admin_theme', - # all-auth - 'django.contrib.sites', - 'allauth', - 'allauth.account', - 'allauth.socialaccount', - # openwisp2 modules - 'openwisp_users', - # 'myipam', <-- replace without your app-name here - # admin - 'admin_auto_filters', - 'django.contrib.admin', - # rest framework - 'rest_framework', - # Other dependencies - 'reversion', - ] - -For more information about how to work with django projects and django apps, -please refer to the `django documentation `_. - -2. Install ``openwisp-ipam`` -============================ - -Install (and add to the requirement of your project) openwisp-ipam:: - - pip install openwisp-ipam - -3. Add ``EXTENDED_APPS`` -======================== - -Add the following to your ``settings.py``: - -.. code-block:: python - - EXTENDED_APPS = ('openwisp_ipam',) - -4. Add ``openwisp_utils.staticfiles.DependencyFinder`` -====================================================== - -Add ``openwisp_utils.staticfiles.DependencyFinder`` to -``STATICFILES_FINDERS`` in your ``settings.py``: - -.. code-block:: python - - STATICFILES_FINDERS = [ - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', - 'openwisp_utils.staticfiles.DependencyFinder', - ] - -5. Add ``openwisp_utils.loaders.DependencyLoader`` -================================================== - -Add ``openwisp_utils.loaders.DependencyLoader`` to ``TEMPLATES`` -in your ``settings.py``, but ensure it comes before -``django.template.loaders.app_directories.Loader``: - -.. code-block:: python - - TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'OPTIONS': { - 'loaders': [ - 'django.template.loaders.filesystem.Loader', - 'openwisp_utils.loaders.DependencyLoader', - 'django.template.loaders.app_directories.Loader', - ], - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - ], - }, - } - ] - -6. Inherit the AppConfig class -============================== - -Please refer to the following files in the sample app of the test project: - -- `sample_ipam/__init__.py `_. -- `sample_ipam/apps.py `_. - -You have to replicate and adapt that code in your project. - -For more information regarding the concept of ``AppConfig`` please refer to -the `"Applications" section in the django documentation `_. - -7. Create your custom models -============================ - -For the purpose of showing an example, we added a simple "details" field to the -`models of the sample app in the test project `_. - -You can add fields in a similar way in your ``models.py`` file. - -**Note**: for doubts regarding how to use, extend or develop models please refer to -the `"Models" section in the django documentation `_. - -8. Add swapper configurations -============================= - -Once you have created the models, add the following to your ``settings.py``: - -.. code-block:: python - - # Setting models for swapper module - OPENWISP_IPAM_IPADDRESS_MODEL = 'myipam.IpAddress' - OPENWISP_IPAM_SUBNET_MODEL = 'myipam.Subnet' - -Substitute ``myipam`` with the name you chose in step 1. - -9. Create database migrations -============================= - -Create and apply database migrations:: - - ./manage.py makemigrations - ./manage.py migrate - -For more information, refer to the -`"Migrations" section in the django documentation `_. - - -10. Create the admin -==================== - -Refer to the `admin.py file of the sample app `_. - -To introduce changes to the admin, you can do it in two main ways which are described below. - -**Note**: for more information regarding how the django admin works, or how it can be customized, -please refer to `"The django admin site" section in the django documentation `_. - -1. Monkey patching ------------------- - -If the changes you need to add are relatively small, you can resort to monkey patching. - -For example: - -.. code-block:: python - - from openwisp_ipam.admin import IpAddressAdmin, SubnetAdmin - - SubnetAdmin.app_label = 'sample_ipam' - - -2. Inheriting admin classes ---------------------------- - -If you need to introduce significant changes and/or you don't want to resort to -monkey patching, you can proceed as follows: - -.. code-block:: python - - from django.contrib import admin - from openwisp_ipam.admin import ( - IpAddressAdmin as BaseIpAddressAdmin, - SubnetAdmin as BaseSubnetAdmin, - ) - from swapper import load_model - - IpAddress = load_model('openwisp_ipam', 'IpAddress') - Subnet = load_model('openwisp_ipam', 'Subnet') - - admin.site.unregister(IpAddress) - admin.site.unregister(Subnet) - - @admin.register(IpAddress) - class IpAddressAdmin(BaseIpAddressAdmin): - # add your changes here - - @admin.register(Subnet) - class SubnetAdmin(BaseSubnetAdmin): - app_label = 'myipam' - # add your changes here - -Substitute ``myipam`` with the name you chose in step 1. - -11. Create root URL configuration -================================= - -.. code-block:: python - - from .sample_ipam import views as api_views - from openwisp_ipam.urls import get_urls - - urlpatterns = [ - # ... other urls in your project ... - # openwisp-ipam urls - # path('', include(get_urls(api_views))) <-- Use only when changing API views (dicussed below) - path('', include('openwisp_ipam.urls')), - ] - -For more information about URL configuration in django, please refer to the -`"URL dispatcher" section in the django documentation `_. - -12. Import the automated tests -============================== - -When developing a custom application based on this module, it's a good -idea to import and run the base tests too, so that you can be sure the changes -you're introducing are not breaking some of the existing features of *openwisp-ipam*. - -In case you need to add breaking changes, you can overwrite the tests defined -in the base classes to test your own behavior. - -See the `tests of the sample app `_ -to find out how to do this. - -You can then run tests with:: - - # the --parallel flag is optional - ./manage.py test --parallel myipam - -Substitute ``myipam`` with the name you chose in step 1. - -For more information about automated tests in django, please refer to -`"Testing in Django" `_. - -Other base classes that can be inherited and extended -===================================================== - -The following steps are not required and are intended for more advanced customization. - -1. Extending the API Views --------------------------- - -The API view classes can be extended into other django applications as well. Note -that it is not required for extending openwisp-ipam to your app and this change -is required only if you plan to make changes to the API views. - -Create a view file as done in `views.py `_. - -For more information about django views, please refer to the `views section in the django documentation `_. - -Contributing -************ +See `CHANGES +`_. -Please refer to the `OpenWISP contributing guidelines `_. +License +------- -`Support channels `_ | -`Issue Tracker `_ | -`License `_ +See `LICENSE +`_. diff --git a/docs/developer/extending.rst b/docs/developer/extending.rst new file mode 100644 index 0000000..3257d6a --- /dev/null +++ b/docs/developer/extending.rst @@ -0,0 +1,332 @@ +Extending OpenWISP IPAM +======================= + +.. include:: ../partials/developer-docs.rst + +One of the core values of the OpenWISP project is :ref:`Software +Reusability `, for this reason +*openwisp-ipam* provides a set of base classes which can be imported, +extended and reused to create derivative apps. + +In order to implement your custom version of *openwisp-ipam*, you need to +perform the steps described in this section. + +When in doubt, the code in the `test project +`_ +and the `sample app +`_ +will serve you as source of truth: just replicate and adapt that code to +get a basic derivative of *openwisp-ipam* working. + +If you want to add new users fields, please follow the :doc:`tutorial to +extend the openwisp-users `. As an example, we +have extended *openwisp-users* to *sample_users* app and added a field +``social_security_number`` in the `sample_users/models.py +`_. + +.. important:: + + If you plan on using a customized version of this module, we suggest + to start with it since the beginning, because migrating your data from + the default module to your extended version may be time consuming. + +.. contents:: **Table of Contents**: + :depth: 2 + :local: + +1. Initialize your Custom Module +-------------------------------- + +The first thing you need to do is to create a new django app which will +contain your custom version of *openwisp-ipam*. + +A django app is nothing more than a `python package +`_ (a directory +of python scripts), in the following examples we'll call this django app +``myipam``, but you can name it how you want: + +.. code-block:: + + django-admin startapp myipam + +Keep in mind that the command mentioned above must be called from a +directory which is available in your `PYTHON_PATH +`_ so that +you can then import the result into your project. + +Now you need to add ``myipam`` to ``INSTALLED_APPS`` in your +``settings.py``, ensuring also that ``openwisp_ipam`` has been removed: + +.. code-block:: python + + INSTALLED_APPS = [ + # ... other apps ... + "openwisp_utils.admin_theme", + # all-auth + "django.contrib.sites", + "allauth", + "allauth.account", + "allauth.socialaccount", + # openwisp2 modules + "openwisp_users", + # 'myipam', <-- replace without your app-name here + # admin + "admin_auto_filters", + "django.contrib.admin", + # rest framework + "rest_framework", + # Other dependencies + "reversion", + ] + +For more information about how to work with django projects and django +apps, please refer to the `django documentation +`_. + +2. Install ``openwisp-ipam`` +---------------------------- + +Install (and add to the requirement of your project) openwisp-ipam: + +.. code-block:: + + pip install openwisp-ipam + +3. Add ``EXTENDED_APPS`` +------------------------ + +Add the following to your ``settings.py``: + +.. code-block:: python + + EXTENDED_APPS = ("openwisp_ipam",) + +4. Add ``openwisp_utils.staticfiles.DependencyFinder`` +------------------------------------------------------ + +Add ``openwisp_utils.staticfiles.DependencyFinder`` to +``STATICFILES_FINDERS`` in your ``settings.py``: + +.. code-block:: python + + STATICFILES_FINDERS = [ + "django.contrib.staticfiles.finders.FileSystemFinder", + "django.contrib.staticfiles.finders.AppDirectoriesFinder", + "openwisp_utils.staticfiles.DependencyFinder", + ] + +5. Add ``openwisp_utils.loaders.DependencyLoader`` +-------------------------------------------------- + +Add ``openwisp_utils.loaders.DependencyLoader`` to ``TEMPLATES`` in your +``settings.py``, but ensure it comes before +``django.template.loaders.app_directories.Loader``: + +.. code-block:: python + + TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "OPTIONS": { + "loaders": [ + "django.template.loaders.filesystem.Loader", + "openwisp_utils.loaders.DependencyLoader", + "django.template.loaders.app_directories.Loader", + ], + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + ], + }, + } + ] + +6. Inherit the AppConfig Class +------------------------------ + +Please refer to the following files in the sample app of the test project: + +- `sample_ipam/__init__.py + `_. +- `sample_ipam/apps.py + `_. + +You have to replicate and adapt that code in your project. + +For more information regarding the concept of ``AppConfig`` please refer +to the `"Applications" section in the django documentation +`_. + +7. Create your Custom Models +---------------------------- + +For the purpose of showing an example, we added a simple "details" field +to the `models of the sample app in the test project +`_. + +You can add fields in a similar way in your ``models.py`` file. + +**Note**: for doubts regarding how to use, extend or develop models please +refer to the `"Models" section in the django documentation +`_. + +8. Add Swapper Configurations +----------------------------- + +Once you have created the models, add the following to your +``settings.py``: + +.. code-block:: python + + # Setting models for swapper module + OPENWISP_IPAM_IPADDRESS_MODEL = "myipam.IpAddress" + OPENWISP_IPAM_SUBNET_MODEL = "myipam.Subnet" + +Substitute ``myipam`` with the name you chose in step 1. + +9. Create Database Migrations +----------------------------- + +Create and apply database migrations: + +.. code-block:: + + ./manage.py makemigrations + ./manage.py migrate + +For more information, refer to the `"Migrations" section in the django +documentation +`_. + +10. Create the Admin +-------------------- + +Refer to the `admin.py file of the sample app +`_. + +To introduce changes to the admin, you can do it in two main ways which +are described below. + +**Note**: for more information regarding how the django admin works, or +how it can be customized, please refer to `"The django admin site" section +in the django documentation +`_. + +1. Monkey Patching +~~~~~~~~~~~~~~~~~~ + +If the changes you need to add are relatively small, you can resort to +monkey patching. + +For example: + +.. code-block:: python + + from openwisp_ipam.admin import IpAddressAdmin, SubnetAdmin + + SubnetAdmin.app_label = "sample_ipam" + +2. Inheriting Admin Classes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you need to introduce significant changes and/or you don't want to +resort to monkey patching, you can proceed as follows: + +.. code-block:: python + + from django.contrib import admin + from openwisp_ipam.admin import ( + IpAddressAdmin as BaseIpAddressAdmin, + SubnetAdmin as BaseSubnetAdmin, + ) + from swapper import load_model + + IpAddress = load_model("openwisp_ipam", "IpAddress") + Subnet = load_model("openwisp_ipam", "Subnet") + + admin.site.unregister(IpAddress) + admin.site.unregister(Subnet) + + + @admin.register(IpAddress) + class IpAddressAdmin(BaseIpAddressAdmin): + # add your changes here + pass + + + @admin.register(Subnet) + class SubnetAdmin(BaseSubnetAdmin): + app_label = "myipam" + # add your changes here + +Substitute ``myipam`` with the name you chose in step 1. + +11. Create Root URL Configuration +--------------------------------- + +.. code-block:: python + + from .sample_ipam import views as api_views + from openwisp_ipam.urls import get_urls + + urlpatterns = [ + # ... other urls in your project ... + # openwisp-ipam urls + # path('', include(get_urls(api_views))) <-- Use only when changing API views (dicussed below) + path("", include("openwisp_ipam.urls")), + ] + +For more information about URL configuration in django, please refer to +the `"URL dispatcher" section in the django documentation +`_. + +12. Import the Automated Tests +------------------------------ + +When developing a custom application based on this module, it's a good +idea to import and run the base tests too, so that you can be sure the +changes you're introducing are not breaking some of the existing features +of *openwisp-ipam*. + +In case you need to add breaking changes, you can overwrite the tests +defined in the base classes to test your own behavior. + +See the `tests of the sample app +`_ +to find out how to do this. + +You can then run tests with: + +.. code-block:: + + # the --parallel flag is optional + ./manage.py test --parallel myipam + +Substitute ``myipam`` with the name you chose in step 1. + +For more information about automated tests in django, please refer to +`"Testing in Django" +`_. + +Other Base Classes That Can be Inherited and Extended +----------------------------------------------------- + +The following steps are not required and are intended for more advanced +customization. + +1. Extending the API Views +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The API view classes can be extended into other django applications as +well. Note that it is not required for extending openwisp-ipam to your app +and this change is required only if you plan to make changes to the API +views. + +Create a view file as done in `views.py +`_. + +For more information about django views, please refer to the `views +section in the django documentation +`_. diff --git a/docs/developer/index.rst b/docs/developer/index.rst new file mode 100644 index 0000000..e84b7ae --- /dev/null +++ b/docs/developer/index.rst @@ -0,0 +1,14 @@ +Developer Docs +============== + +.. include:: ../partials/developer-docs.rst + +.. toctree:: + :maxdepth: 2 + + ./installation.rst + ./extending.rst + +Other useful resources: + + - :doc:`../user/rest-api` diff --git a/docs/developer/installation.rst b/docs/developer/installation.rst new file mode 100644 index 0000000..a97a8d8 --- /dev/null +++ b/docs/developer/installation.rst @@ -0,0 +1,81 @@ +Developer Installation Instructions +=================================== + +.. include:: ../partials/developer-docs.rst + +.. contents:: **Table of contents**: + :depth: 2 + :local: + +Installing for Development +-------------------------- + +Install sqlite: + +.. code-block:: shell + + sudo apt-get install sqlite3 libsqlite3-dev openssl libssl-dev + +Install your forked repo: + +.. code-block:: shell + + git clone git://github.com//openwisp-ipam + cd openwisp-ipam/ + pip install -e . + +Install test requirements: + +.. code-block:: shell + + pip install -r requirements-test.txt + +Create database: + +.. code-block:: shell + + cd tests/ + ./manage.py migrate + ./manage.py createsuperuser + +Launch development server: + +.. code-block:: shell + + ./manage.py runserver + +You can access the admin interface at ``http://127.0.0.1:8000/admin/``. + +Run tests with: + +.. code-block:: shell + + # --parallel and --keepdb are optional but help to speed up the operation + ./runtests.py --parallel --keepdb + +Alternative Sources +------------------- + +Pypi +~~~~ + +To install the latest stable version from PyPI: + +.. code-block:: shell + + pip install openwisp-ipam + +Github +~~~~~~ + +To install the latest development version tarball via HTTPs: + +.. code-block:: shell + + pip install https://github.com/openwisp/openwisp-ipam/tarball/master + +Alternatively you can use the git protocol: + +.. code-block:: shell + + pip install -e git+git://github.com/openwisp/openwisp-ipam#egg=openwisp_ipam diff --git a/docs/images/architecture-v2-openwisp-ipam.png b/docs/images/architecture-v2-openwisp-ipam.png new file mode 100644 index 0000000..3b9847a Binary files /dev/null and b/docs/images/architecture-v2-openwisp-ipam.png differ diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..8db6bdf --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,56 @@ +IPAM +==== + +.. seealso:: + + **Source code**: `github.com/openwisp/openwisp-ipam + `_. + +.. image:: https://github.com/openwisp/openwisp-ipam/raw/docs/docs/subnet_demo.gif + :target: https://github.com/openwisp/openwisp-ipam/raw/docs/docs/subnet_demo.gif + :alt: Feature Highlights + +OpenWISP IPAM provides IP Address Management (IPAM) features, refer to +:doc:`user/intro` for a complete overview. As a core dependency of the +:doc:`OpenWISP Controller `, it facilitates the +automatic provisioning of IP addresses for VPNs such as :doc:`Wireguard +` and :doc:`Zerotier +`, and allows to implement the :doc:`Subnet +Division Rules feature `. + +In addition to its integration with the OpenWISP ecosystem, OpenWISP IPAM +can be used as a standalone Django app: developers proficient in Python +and Django can leverage this module independently to enhance their +projects, for more details on this subject please refer to the +:doc:`developer documentation `. + +The following diagram illustrates the role of the IPAM module within the +OpenWISP architecture. + +.. figure:: images/architecture-v2-openwisp-ipam.png + :target: ../_images/architecture-v2-openwisp-ipam.png + :align: center + :alt: OpenWISP Architecture: IPAM module + + **OpenWISP Architecture: highlighted IPAM module** + +.. important:: + + For an enhanced viewing experience, open the image above in a new + browser tab. + + Refer to :doc:`/general/architecture` for more information. + +.. toctree:: + :caption: IPAM Usage Docs + :maxdepth: 1 + + ./user/intro.rst + ./user/import-export-subnets.rst + ./user/rest-api.rst + +.. toctree:: + :caption: IPAM Developer Docs + :maxdepth: 2 + + Developer Docs Index diff --git a/docs/partials/developer-docs.rst b/docs/partials/developer-docs.rst new file mode 100644 index 0000000..26fe9fa --- /dev/null +++ b/docs/partials/developer-docs.rst @@ -0,0 +1,12 @@ +.. note:: + + This documentation page is aimed at developers who want to customize, + change or extend the code of OpenWISP IPAM in order to modify its + behavior (eg: for personal or commercial purposes or to fix a bug, + implement a new feature or contribute to the project in general). + + If you aren't a developer and you are looking for information on how + to use OpenWISP, please refer to: + + - :doc:`General OpenWISP Quickstart ` + - :doc:`OpenWISP IPAM Docs ` diff --git a/docs/user/import-export-subnets.rst b/docs/user/import-export-subnets.rst new file mode 100644 index 0000000..c70bca1 --- /dev/null +++ b/docs/user/import-export-subnets.rst @@ -0,0 +1,72 @@ +Exporting and Importing Subnet +============================== + +One can easily import and export `Subnet` data and it's Ip Addresses using +`openwisp-ipam`. This works for both IPv4 and IPv6 types of networks. + +.. contents:: **Table of contents**: + :depth: 2 + :local: + +Exporting +--------- + +Data can be exported via the admin interface or by using a management +command. The exported data is in `.csv` file format. + +From Management Command +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: shell + + ./manage.py export_subnet + +This would export the subnet if it exists on the database. + +From Admin Interface +~~~~~~~~~~~~~~~~~~~~ + +Data can be exported from the admin interface by just clicking on the +export button on the subnet's admin change view. + +.. image:: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/export.png + +Importing +--------- + +Data can be imported via the admin interface or by using a management +command. The imported data file can be in `.csv` and `.xlsx` format. While +importing data for ip addresses, the system checks if the subnet specified +in the import file exists or not. If the subnet does not exists it will be +created while importing data. + +From Management Command +~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: shell + + ./manage.py import_subnet --file= + +From Admin Interface +~~~~~~~~~~~~~~~~~~~~ + +Data can be imported from the admin interface by just clicking on the +import button on the subnet view. + +.. image:: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/import.png + +CSV File Format +=============== + +Follow the following structure while creating `csv` file to import data. + +.. code-block:: text + + Subnet Name + Subnet Value + Organization Slug + + ip_address,description + , + , + , diff --git a/docs/user/intro.rst b/docs/user/intro.rst new file mode 100644 index 0000000..552a828 --- /dev/null +++ b/docs/user/intro.rst @@ -0,0 +1,17 @@ +IPAM: Features +============== + +OpenWISP IPAM provides the following capabilities: + +- IPv4 and IPv6 IP address management +- IPv4 and IPv6 Subnet management +- :doc:`CSV Import and Export of subnets ` and + their IPs +- Automatic free space display for all subnets +- IP request module +- :doc:`REST API ` for CRUD operations and main features +- Possibility to search for an IP or subnet +- Visual display for a specific subnet + + .. image:: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/visual-display.png + :target: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/visual-display.png diff --git a/docs/user/rest-api.rst b/docs/user/rest-api.rst new file mode 100644 index 0000000..544f7dd --- /dev/null +++ b/docs/user/rest-api.rst @@ -0,0 +1,294 @@ +REST API +======== + +.. contents:: **Table of contents**: + :depth: 1 + :local: + +.. _ipam_live_documentation: + +Live Documentation +------------------ + +.. image:: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/api-docs.png + :target: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/api-docs.png + +A general live API documentation (following the OpenAPI specification) is +available at ``/api/v1/docs/``. + +.. _ipam_browsable_web_interface: + +Browsable Web Interface +----------------------- + +.. image:: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/api-ui.png + :target: https://raw.githubusercontent.com/openwisp/openwisp-ipam/docs/docs/api-ui.png + +Additionally, opening any of the endpoints :ref:`ipam_list_endpoints` +directly in the browser will show the `browsable API interface of +Django-REST-Framework +`_, which +makes it even easier to find out the details of each endpoint. + +Authentication +-------------- + +See openwisp-users: :ref:`authenticating_rest_api`. + +When browsing the API via the :ref:`ipam_live_documentation` or the +:ref:`ipam_browsable_web_interface`, you can also use the session +authentication by logging in the django admin. + +API Throttling +-------------- + +To override the default API throttling settings, add the following to your +``settings.py`` file: + +.. code-block:: python + + REST_FRAMEWORK = { + "DEFAULT_THROTTLE_RATES": { + "ipam": "100/hour", + } + } + +The rate descriptions used in ``DEFAULT_THROTTLE_RATES`` may include +``second``, ``minute``, ``hour`` or ``day`` as the throttle period. + +Pagination +---------- + +All *list* endpoints support the ``page_size`` parameter that allows +paginating the results in conjunction with the ``page`` parameter. + +.. code-block:: text + + GET /api/v1//?page_size=10 + GET /api/v1//?page_size=10&page=2 + +.. _ipam_list_endpoints: + +List of Endpoints +----------------- + +Since the detailed explanation is contained in the +:ref:`ipam_live_documentation` and in the +:ref:`ipam_browsable_web_interface` of each endpoint, here we'll provide +just a list of the available endpoints, for further information please +open the URL of the endpoint in your browser. + +Get Next Available IP +~~~~~~~~~~~~~~~~~~~~~ + +Fetch the next available IP address under a specific subnet. + +GET ++++ + +Returns the next available IP address under a subnet. + +.. code-block:: text + + /api/v1/ipam/subnet//get-next-available-ip/ + +Request IP +~~~~~~~~~~ + +A model method to create and fetch the next available IP address record +under a subnet. + +POST +++++ + +Creates a record for next available IP address and returns JSON data of +that record. + +.. code-block:: text + + POST /api/v1/ipam/subnet//request-ip/ + +=========== ======================================= +Param Description +=========== ======================================= +description Optional description for the IP address +=========== ======================================= + +Response +++++++++ + +.. code-block:: json + + { + "ip_address": "ip_address", + "subnet": "subnet_uuid", + "description": "optional description" + } + +Subnet IP Address List/Create +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An api endpoint to retrieve or create IP addresses under a specific +subnet. + +GET ++++ + +Returns the list of IP addresses under a particular subnet. + +.. code-block:: text + + /api/v1/ipam/subnet//ip-address/ + +POST +++++ + +Create a new ``IP Address``. + +.. code-block:: text + + /api/v1/ipam/subnet//ip-address/ + +=========== ======================================= +Param Description +=========== ======================================= +ip_address IPv6/IPv4 address value +subnet Subnet UUID +description Optional description for the IP address +=========== ======================================= + +Subnet List/Create +~~~~~~~~~~~~~~~~~~ + +An api endpoint to create or retrieve the list of subnet instances. + +GET ++++ + +Returns the list of ``Subnet`` instances. + +.. code-block:: text + + /api/v1/ipam/subnet/ + +POST +++++ + +Create a new ``Subnet``. + +.. code-block:: text + + /api/v1/ipam/subnet/ + +============= ======================================= +Param Description +============= ======================================= +subnet Subnet value in CIDR format +master_subnet Master Subnet UUID +description Optional description for the IP address +============= ======================================= + +Subnet Detail +~~~~~~~~~~~~~ + +An api endpoint for retrieving, updating or deleting a subnet instance. + +GET ++++ + +Get details of a ``Subnet`` instance + +.. code-block:: text + + /api/v1/ipam/subnet// + +DELETE +++++++ + +Delete a ``Subnet`` instance + +.. code-block:: text + + /api/v1/ipam/subnet// + +PUT ++++ + +Update details of a ``Subnet`` instance. + +.. code-block:: text + + /api/v1/ipam/subnet// + +============= ======================================= +Param Description +============= ======================================= +subnet Subnet value in CIDR format +master_subnet Master Subnet UUID +description Optional description for the IP address +============= ======================================= + +IP Address Detail +~~~~~~~~~~~~~~~~~ + +An api endpoint for retrieving, updating or deleting a IP address +instance. + +GET ++++ + +Get details of an ``IP address`` instance. + +.. code-block:: text + + /api/v1/ipam/ip-address// + +DELETE +++++++ + +Delete an ``IP address`` instance. + +.. code-block:: text + + /api/v1/ipam/ip-address// + +PUT ++++ + +Update details of an ``IP address`` instance. + +.. code-block:: text + + /api/v1/ipam/ip-address// + +=========== ======================================= +Param Description +=========== ======================================= +ip_address IPv6/IPv4 value +subnet Subnet UUID +description Optional description for the IP address +=========== ======================================= + +Export Subnet +~~~~~~~~~~~~~ + +View to export subnet data. + +POST +++++ + +.. code-block:: text + + /api/v1/ipam/subnet//export/ + +Import Subnet +~~~~~~~~~~~~~ + +View to import subnet data. + +POST +++++ + +.. code-block:: text + + /api/v1/ipam/import-subnet/ diff --git a/pyproject.toml b/pyproject.toml index 892de1a..bab7ac1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ omit = [ ] [tool.docstrfmt] -extend_exclude = ["**/*.py", "README.rst"] +extend_exclude = ["**/*.py"] [tool.isort] known_third_party = ["django"]