Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Dynamic DNS Client configuration to the OpenWRT backend #111

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
135 changes: 135 additions & 0 deletions docs/source/backends/openwrt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2446,6 +2446,141 @@ Will be rendered as follows::
option sysfs 'tp-link:blue:wlan2g'
option trigger 'phy0tpt'

DDNS settings
-------------

The ddns settings reside in the ``ddns`` key of the *configuration dictionary*,
which is a custom NetJSON extension not present in the original NetJSON RFC.

The ``ddns`` key must contain a dictionary, the allowed keys are:

+---------------------+---------+
| key name | type |
+=====================+=========+
| ``upd_privateip`` | boolean |
+---------------------+---------+
| ``ddns_dateformat`` | string |
+---------------------+---------+
| ``ddns_rundir`` | string |
+---------------------+---------+
| ``ddns_logdir`` | string |
+---------------------+---------+
| ``ddns_loglines`` | integer |
+---------------------+---------+
| ``use_curl`` | boolean |
+---------------------+---------+
| ``providers`` | list |
+---------------------+---------+

The ``providers`` key itself contains a list of dictionaries, the allowed keys are:

+---------------------+---------+
| key name | type |
+=====================+=========+
| ``enabled`` | boolean |
+---------------------+---------+
| ``interface`` | string |
+---------------------+---------+
| ``ip_source`` | string |
+---------------------+---------+
| ``lookup_host`` | string |
+---------------------+---------+
| ``domain`` | string |
+---------------------+---------+
| ``username`` | string |
+---------------------+---------+
| ``password`` | string |
+---------------------+---------+
| ``service_name`` | string |
+---------------------+---------+
| ``update_url`` | string |
+---------------------+---------+
| ``update_script`` | string |
+---------------------+---------+
| ``ip_network`` | string |
+---------------------+---------+
| ``ip_url`` | string |
+---------------------+---------+
| ``ip_interface`` | string |
+---------------------+---------+
| ``ip_script`` | string |
+---------------------+---------+
| ``use_syslog`` | integer |
+---------------------+---------+
| ``use_logfile`` | boolean |
+---------------------+---------+

The required keys are:

* ``enabled``
* ``interface``
* ``ip_source``
* ``lookup_host``
* ``domain``
* ``username``
* ``password``

For the function and meaning of each key consult the relevant
`OpenWrt documentation about ddns directives <https://openwrt.org/docs/guide-user/base-system/ddns>`_.

DDNS settings example
~~~~~~~~~~~~~~~~~~~~~

The following *configuration dictionary*:

.. code-block:: python

{
"ddns": {
"ddns_logdir": "/var/log/ddns",
"ddns_rundir": "/var/run/ddns",
"use_curl": False,
"upd_privateip": False,
"ddns_dateformat": "%F %R",
"ddns_loglines": 250,
"providers": [
{
"enabled": True,
"lookup_host": "myhost.dyndns.org",
"service_name": "dyndns.org",
"domain": "myhost.dyndns.org",
"username": "myuser",
"password": "mypassword",
"use_logfile": True,
"ip_source": "interface",
"ip_interface": "pppoe-xdsl",
"use_syslog": 2,
"interface": "xdsl"
}
],
}
}

Will be rendered as follows::

package ddns

config ddns 'global'
option ddns_logdir '/var/log/ddns'
option ddns_rundir '/var/run/ddns'
option use_curl '0'
option upd_privateip '0'
option ddns_dateformat '%F %R'
option ddns_loglines '250'

config service 'myhost_dyndns_org'
option enabled '1'
option lookup_host 'myhost.dyndns.org'
option service_name 'dyndns.org'
option domain 'myhost.dyndns.org'
option username 'myuser'
option password 'mypassword'
option use_logfile '1'
option ip_source 'interface'
option ip_interface 'pppoe-xdsl'
option use_syslog '2'
option interface 'xdsl'

Including custom options
------------------------

Expand Down
2 changes: 2 additions & 0 deletions netjsonconfig/backends/openwrt/converters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .ddns import Ddns
from .default import Default
from .general import General
from .interfaces import Interfaces
Expand All @@ -24,4 +25,5 @@
'Switch',
'WireguardPeers',
'Wireless',
'Ddns',
]
56 changes: 56 additions & 0 deletions netjsonconfig/backends/openwrt/converters/ddns.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from collections import OrderedDict

from ..schema import schema
from .base import OpenWrtConverter


class Ddns(OpenWrtConverter):
netjson_key = 'ddns'
intermediate_key = 'ddns'
_uci_types = ['ddns', 'service']
_schema = schema['properties']['ddns']

def to_intermediate_loop(self, block, result, index=None):
if block:
provider_list = self.__intermediate_providers(block.pop('providers', {}))
block.update({'.type': 'ddns', '.name': block.pop('id', 'global')})
result.setdefault('ddns', [])
result['ddns'] = [self.sorted_dict(block)] + provider_list

return result

def __intermediate_providers(self, providers):
"""
converts NetJSON provider to
UCI intermediate data structure
"""
result = []

for provider in providers:
uci_name = self._get_uci_name(provider['lookup_host'])
resultdict = OrderedDict((('.name', uci_name), ('.type', 'service')))
resultdict.update(provider)
result.append(resultdict)

return result

def to_netjson_loop(self, block, result, index):
result.setdefault(self.netjson_key, {})

if block['.type'] == 'service':
result[self.netjson_key].setdefault('providers', [])
result[self.netjson_key]['providers'].append(self.__netjson_ddns(block))
else:
result['ddns'] = self.__netjson_ddns(block)

return result

def __netjson_ddns(self, ddns):
_type = ddns.pop('.type')
del ddns['.name']

if _type == 'service':
ddns_schema = self._schema.get('properties').get('providers').get('items')
return self.type_cast(ddns, schema=ddns_schema)

return self.type_cast(ddns)
1 change: 1 addition & 0 deletions netjsonconfig/backends/openwrt/openwrt.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class OpenWrt(BaseBackend):
converters.Wireless,
converters.OpenVpn,
converters.WireguardPeers,
converters.Ddns,
converters.Default,
]
parser = OpenWrtParser
Expand Down
Loading