Skip to content

Commit 4aa5e9e

Browse files
Merge branch 'master' into openwrt-firewall
2 parents 4c134bc + 3d53e14 commit 4aa5e9e

11 files changed

Lines changed: 267 additions & 42 deletions

File tree

CHANGES.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Change log
22
==========
33

4-
Version 0.9.0 [unreleased]
4+
Version 0.9.0 [2020-11-18]
55
--------------------------
66

77
- [change] **Potentially backward incompatible**:
@@ -10,6 +10,7 @@ Version 0.9.0 [unreleased]
1010
This change is backward incompatible if the same type of configuration
1111
was achieved using a workaround, in these cases the configuration
1212
will have to be upgraded to use the new format.
13+
- [feature] Added support for modem manager interfaces
1314

1415
Version 0.8.2 [2020-08-17]
1516
--------------------------

docs/source/backends/openwrt.rst

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ There are 4 main types of interfaces:
294294
* **wireless interfaces**: must be of type ``wireless``
295295
* **bridge interfaces**: must be of type ``bridge``
296296
* **dialup interfaces**: must be of type ``dialup``
297+
* **modem manager interfaces**: must be of type ``modem-manager``
297298

298299
Interface object extensions
299300
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1252,12 +1253,89 @@ Will be rendered as follows::
12521253

12531254
package network
12541255

1255-
config interface 'xdsl'
1256+
config interface 'xdsl'
12561257
option ifname 'dsl0'
1257-
option proto 'pppoe'
1258-
option username 'dsluser'
1258+
option proto 'pppoe'
1259+
option username 'dsluser'
12591260
option password 'jf93nf82o023$'
1260-
option mtu '1448'
1261+
option mtu '1448'
1262+
1263+
Modem Manager settings
1264+
----------------------
1265+
1266+
Interfaces of type ``modem-manager`` contain a few options
1267+
that are specific to modem-manager interfaces (2G, 3G, 4G, LTE, etc).
1268+
1269+
These are the ``OpenWrt`` backend NetJSON extensions for Modem Manager interfaces:
1270+
1271+
+--------------+---------+-----------------+--------------------------------------------+
1272+
| key name | type | default | allowed values |
1273+
+==============+=========+=================+============================================+
1274+
| ``proto`` | string | ``modemanager`` | ``modemanager`` |
1275+
+--------------+---------+-----------------+--------------------------------------------+
1276+
| ``apn`` | string | empty | APN, can be left blank |
1277+
+--------------+---------+-----------------+--------------------------------------------+
1278+
| ``pin`` | string | empty | PIN code, can be left blank |
1279+
+--------------+---------+-----------------+--------------------------------------------+
1280+
| ``device`` | string | empty | path to device (see note below) |
1281+
+--------------+---------+-----------------+--------------------------------------------+
1282+
| ``password`` | string | empty | password, can be left blank |
1283+
+--------------+---------+-----------------+--------------------------------------------+
1284+
| ``username`` | string | empty | username, can be left blank |
1285+
+--------------+---------+-----------------+--------------------------------------------+
1286+
| ``metric`` | integer | ``50`` | metric, can be left blank |
1287+
+--------------+---------+-----------------+--------------------------------------------+
1288+
| ``iptype`` | string | ``ipv4`` | One of ``ipv4``, ``ipv6``, ``ipv4v6`` |
1289+
+--------------+---------+-----------------+--------------------------------------------+
1290+
| ``lowpower`` | boolean | ``False`` | low power mode |
1291+
+--------------+---------+-----------------+--------------------------------------------+
1292+
1293+
.. note::
1294+
``device`` is a required property but can be left empty so that
1295+
the default value supplied by the hardware itself and already
1296+
present on the device can be left untouched by merging the
1297+
configuration generated with netjsonconfig
1298+
(instead of fully overwriting it).
1299+
1300+
Modem Manager interface example
1301+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1302+
1303+
The following *configuration dictionary*:
1304+
1305+
.. code-block:: python
1306+
1307+
{
1308+
"interfaces": [
1309+
{
1310+
"type": "modem-manager",
1311+
"apn": "apn.operator.com",
1312+
"pin": "1234",
1313+
"device": "/sys/devices/platform/ahb/1b000000.usb/usb1/1-1",
1314+
"username": "user123",
1315+
"password": "pwd123456",
1316+
"metric": 50,
1317+
"lowpower": False,
1318+
"name": "modem0",
1319+
"mtu": 1500
1320+
}
1321+
]
1322+
}
1323+
1324+
Will be rendered as follows::
1325+
1326+
package network
1327+
1328+
config interface 'modem0'
1329+
option apn 'apn.operator.com'
1330+
option device '/sys/devices/platform/ahb/1b000000.usb/usb1/1-1'
1331+
option ifname 'wwan0'
1332+
option lowpower '0'
1333+
option metric '50'
1334+
option mtu '1500'
1335+
option password 'pwd123456'
1336+
option pincode '1234'
1337+
option proto 'modemmanager'
1338+
option username 'user123'
12611339

12621340
Radio settings
12631341
--------------

docs/source/general/contributing.rst

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,13 @@ Follow these guidelines to speed up the process.
1212
:backlinks: none
1313
:depth: 3
1414

15-
Reach out before you start
16-
--------------------------
15+
General contributing guidelines of OpenWISP
16+
-------------------------------------------
1717

18-
Before opening a new issue, try the following steps:
19-
20-
- look if somebody else has already started working on the same issue
21-
by looking in the `github issues <https://github.com/openwisp/netjsonconfig/issues>`_
22-
and `pull requests <https://github.com/openwisp/netjsonconfig/pulls>`_
23-
- look also in the `OpenWISP mailing list <https://groups.google.com/d/forum/openwisp/join>`_
24-
- announce your intentions by opening a new issue
25-
- present yourself on the mailing list
18+
We highly recommend reading the general
19+
`OpenWISP Contributing Guidelines <https://openwisp.io/docs/developer/contributing.html>`_
20+
to find out the conventions we use to maintain consistency and quality standards
21+
across the different OpenWISP modules.
2622

2723
Create a virtual environment
2824
----------------------------
@@ -69,8 +65,8 @@ When you introduce changes, ensure test coverage is not decreased with:
6965
7066
nose2 --with-coverage --coverage netjsonconfig
7167
72-
Follow style conventions (PEP8, isort)
73-
--------------------------------------
68+
Follow the coding style conventions and run the QA checks
69+
---------------------------------------------------------
7470

7571
First of all, install the test requirements:
7672

@@ -79,17 +75,18 @@ First of all, install the test requirements:
7975
workon netjsonconfig # activate virtualenv
8076
pip install -r requirements-test.txt
8177
82-
Before committing your work check that your changes are not breaking the style conventions with:
78+
Before committing your work, run ``openwisp-qa-format`` to format the code according
79+
to our `python code conventions <https://openwisp.io/docs/developer/contributing.html#python-code-conventions>`_:
8380

8481
.. code-block:: shell
8582
86-
flake8
87-
isort --check-only --recursive .
83+
openwisp-qa-format
8884
89-
For more information, please see:
85+
Then, you can run the QA checks with:
86+
87+
.. code-block:: shell
9088
91-
- `PEP8: Style Guide for Python Code <https://www.python.org/dev/peps/pep-0008/>`_
92-
- `isort: a python utility / library to sort imports <https://github.com/timothycrosley/isort>`_
89+
./run-qa-checks
9390
9491
Update the documentation
9592
------------------------

netjsonconfig/backends/openvpn/openvpn.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ def auto_client(
110110
'cert',
111111
'key',
112112
'pkcs12',
113-
'mtu_disc',
114113
'mtu_test',
115114
'fragment',
116115
'mssfix',

netjsonconfig/backends/openwrt/converters/interfaces.py

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from copy import deepcopy
33
from ipaddress import ip_address, ip_interface
44

5+
from ..schema import schema
56
from .base import OpenWrtConverter
67

78

@@ -109,6 +110,16 @@ def __intermediate_interface(self, interface, uci_name):
109110
del interface['wireless']
110111
if 'addresses' in interface:
111112
del interface['addresses']
113+
# specific transformation
114+
type_ = self._get_uci_name(interface["type"])
115+
method = getattr(self, f'_intermediate_{type_}', None)
116+
if method:
117+
interface = method(interface)
118+
return interface
119+
120+
def _intermediate_modem_manager(self, interface):
121+
interface['proto'] = 'modemmanager'
122+
interface['pincode'] = interface.pop('pin', None)
112123
return interface
113124

114125
_address_keys = ['address', 'mask', 'family', 'gateway']
@@ -225,6 +236,10 @@ def __netjson_interface(self, interface):
225236
interface['mac'] = interface.pop('macaddr')
226237
if interface['network'] == self._get_uci_name(interface['name']):
227238
del interface['network']
239+
# specific transformation
240+
method = getattr(self, f'_netjson_{interface.get("proto")}', None)
241+
if method:
242+
interface = method(interface)
228243
return interface
229244

230245
def __netjson_type(self, interface):
@@ -243,13 +258,17 @@ def __netjson_type(self, interface):
243258
return 'ethernet'
244259

245260
def __netjson_addresses(self, interface):
246-
proto = interface.pop('proto', 'none')
261+
proto = interface.get('proto', 'none')
262+
address_protos = ['static', 'dhcp', 'dhcpv6', 'none']
263+
if 'proto' in interface and proto in address_protos:
264+
del interface['proto']
247265
if 'ipaddr' not in interface and 'ip6addr' not in interface and proto == 'none':
248266
return interface
249-
if proto not in ['static', 'dhcp', 'dhcpv6', 'none']:
250-
interface['proto'] = proto
251-
interface['type'] = self.__get_special_interface_type(interface)
267+
if proto not in address_protos:
268+
interface['type'] = 'other'
269+
return self._add_netjson_addresses(interface, proto)
252270

271+
def _add_netjson_addresses(self, interface, proto):
253272
addresses = []
254273
ipv4 = interface.pop('ipaddr', [])
255274
ipv6 = interface.pop('ip6addr', [])
@@ -273,14 +292,19 @@ def __netjson_addresses(self, interface):
273292
interface['addresses'] = addresses
274293
return interface
275294

276-
def __get_special_interface_type(self, interface):
277-
username = interface.get('username', False)
278-
password = interface.get('password', False)
295+
def _netjson_dialup(self, interface):
296+
interface['type'] = 'dialup'
297+
return interface
298+
299+
_modem_manager_schema = schema['definitions']['modemmanager_interface']
279300

280-
if username and password:
281-
return 'dialup'
301+
def _netjson_modem_manager(self, interface):
302+
del interface['proto']
303+
interface['type'] = 'modem-manager'
304+
interface['pin'] = interface.pop('pincode', None)
305+
return self.type_cast(interface, schema=self._modem_manager_schema)
282306

283-
return 'other'
307+
_netjson_modemmanager = _netjson_modem_manager
284308

285309
def __netjson_address(self, address, interface):
286310
ip = ip_interface(address)
@@ -308,7 +332,7 @@ def __netjson_parse_ip(self, ip, netmask=32):
308332
if ip and netmask:
309333
return '{0}/{1}'.format(ip, netmask)
310334
else:
311-
None
335+
return None
312336

313337
def __netjson_dns(self, interface, result):
314338
key_mapping = {'dns': 'dns_servers', 'dns_search': 'dns_search'}
@@ -320,3 +344,19 @@ def __netjson_dns(self, interface, result):
320344
items = items.split()
321345
result.setdefault(netjson_key, [])
322346
result[netjson_key] += items
347+
348+
349+
for proto in [
350+
'3g',
351+
'6in4',
352+
'aiccu',
353+
'l2tp',
354+
'ncm',
355+
'ppp',
356+
'pppoa',
357+
'pppoe',
358+
'pptp',
359+
'qmi',
360+
'wwan',
361+
]:
362+
setattr(Interfaces, f'_netjson_{proto}', Interfaces._netjson_dialup)

netjsonconfig/backends/openwrt/schema.py

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
from .timezones import timezones
88

99
default_radio_driver = "mac80211"
10+
_interface_properties = default_schema["definitions"]["interface_settings"][
11+
"properties"
12+
]
1013

1114
# The following regex will match against a single valid port, or a port range e.g. 1234-5000
1215
port_range_regex = "^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(-([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$" # noqa
@@ -151,6 +154,7 @@
151154
},
152155
"proto": {
153156
"type": "string",
157+
"title": "protocol",
154158
"enum": [
155159
"3g",
156160
"6in4",
@@ -165,7 +169,7 @@
165169
"wwan",
166170
],
167171
"default": "pppoe",
168-
"propertyOrder": 8,
172+
"propertyOrder": 1.1,
169173
},
170174
"username": {
171175
"type": "string",
@@ -182,7 +186,53 @@
182186
{"$ref": "#/definitions/interface_settings"},
183187
],
184188
},
185-
"base_radio_settings": { # Overrides default schema
189+
"modemmanager_interface": {
190+
"type": "object",
191+
"title": "Modem manager interface",
192+
"required": ["name", "device"],
193+
"properties": {
194+
"name": _interface_properties["name"],
195+
"mtu": _interface_properties["mtu"],
196+
"autostart": _interface_properties["autostart"],
197+
"disabled": _interface_properties["disabled"],
198+
"type": {
199+
"type": "string",
200+
"enum": ["modem-manager"],
201+
"default": "dialup",
202+
"propertyOrder": 1,
203+
},
204+
"apn": {"type": "string", "title": "APN", "propertyOrder": 1.1},
205+
"pin": {
206+
"type": "string",
207+
"title": "PIN code",
208+
"propertyOrder": 1.2,
209+
},
210+
"device": {
211+
"type": "string",
212+
"description": "Leave blank to use the hardware default",
213+
"propertyOrder": 1.3,
214+
},
215+
"username": {"type": "string", "propertyOrder": 1.4},
216+
"password": {"type": "string", "propertyOrder": 1.5},
217+
"metric": {"type": "integer", "default": 50, "propertyOrder": 1.6},
218+
"iptype": {
219+
"type": "string",
220+
"title": "IP type",
221+
"default": "ipv4",
222+
"enum": ["ipv4", "ipv6", "ipv4v6"],
223+
"options": {"enum_titles": ["IPv4", "IPv6", "IPv4 and IPv6"]},
224+
"propertyOrder": 1.7,
225+
},
226+
"lowpower": {
227+
"type": "boolean",
228+
"title": "Low power mode",
229+
"format": "checkbox",
230+
"default": False,
231+
"propertyOrder": 1.8,
232+
},
233+
},
234+
},
235+
"base_radio_settings": {
186236
"properties": {
187237
"driver": {
188238
"type": "string",
@@ -236,7 +286,12 @@
236286
}
237287
},
238288
"interfaces": {
239-
"items": {"oneOf": [{"$ref": "#/definitions/dialup_interface"}]}
289+
"items": {
290+
"oneOf": [
291+
{"$ref": "#/definitions/dialup_interface"},
292+
{"$ref": "#/definitions/modemmanager_interface"},
293+
]
294+
}
240295
},
241296
"routes": {
242297
"items": {

0 commit comments

Comments
 (0)