Skip to content

Commit

Permalink
[change] Added data migration for changing "hwmode" to "band"
Browse files Browse the repository at this point in the history
OpenWrt 21 introduced new property "band" for radio configuration
that deprecates the "hwmode" property.

Related to openwisp/netjsonconfig#236
  • Loading branch information
pandafy authored Jul 12, 2023
1 parent 4eec323 commit 89a501d
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Generated by Django 3.2.20 on 2023-07-10 13:26

from django.core.exceptions import ImproperlyConfigured
from django.db import migrations
from netjsonconfig import channels


def hwmode_to_band(radio):
"""
This function is adapted from
netjsonconfig.backends.openwrt.converters.radios.Radio.__intermediate_band.
If the configuration defines "band", then no operation is performed.
If the configuration defines "hwmode", then the value for "band"
is inferred from "hwmode".
If both "band" and "hwmode" are absent, then value for "band"
is inferred from "protocal" or "channel".
"""
hwmode = radio.pop('hwmode', None)
band = radio.pop('band', None)
if band:
return band
if hwmode:
# Using "hwmode" we can only predict 2GHz and 5GHz radios.
# Support for 802.11ax (2/5/6 GHz) and 802.11ad (60 GHz)
# was added in OpenWrt 21.
if hwmode == '11a':
return '5g'
elif hwmode in ['11b', '11g']:
return '2g'

channel = radio.get('channel')
protocol = radio.get('protocol')
# Infer radio frequency from protocol if possible
if protocol == '802.11ad':
return '60g'
elif protocol in ['802.11b', '802.11g']:
return '2g'
elif protocol in ['802.11a', '802.11ac']:
return '5g'
# Infer radio frequency from channel of the radio
if channel in channels.channels_2ghz:
return '2g'
elif channel in channels.channels_5ghz:
return '5g'
elif channel in channels.channels_6ghz:
return '6g'


def band_to_hwmode(radio):
"""
This function is adapted from
netjsonconfig.backends.openwrt.converters.radios.Radio.__intermediate_hwmode.
Returns value for "hwmode" option (OpenWrt < 21)
If the configuration define "band" (introduced in OpenWrt 21),
then the value for "hwmode" is inferred from "band".
"""
hwmode = radio.pop('hwmode', None)
band = radio.pop('band', None)
if hwmode:
return hwmode
if band:
# 802.11ax and 802.11ad were not supported in OpenWrt < 21.
# Hence, we ignore "6g" and "60g" values.
if band == '2g':
if radio['protocol'] == '802.11b':
return '11b'
else:
return '11g'
elif band == '5g':
return '11a'
# Use protocol to infer "hwmode"
protocol = radio['protocol']
if protocol in ['802.11a', '802.11b', '802.11g']:
# return 11a, 11b or 11g
return protocol[4:]
if protocol == '802.11ac':
return '11a'
# determine hwmode depending on channel used
if radio['channel'] == 0:
# when using automatic channel selection, we need an
# additional parameter to determine the frequency band
return radio.get('hwmode')
elif radio['channel'] <= 13:
return '11g'
else:
return '11a'


def update_config_for_model(Model, func, field):
updated_objects = []
for obj in Model.objects.iterator(chunk_size=100):
update_obj = False
for radio in obj.config.get('radios', []):
if not radio.get(field):
radio[field] = func(radio)
update_obj = True
if update_obj:
updated_objects.append(obj)
if len(updated_objects) > 100:
Model.objects.bulk_update(updated_objects, fields=['config'])
updated_objects = []
if len(updated_objects) != 0:
Model.objects.bulk_update(updated_objects, fields=['config'])


def forward(apps, schema_editor):
"""
Updates "radio" configuration for OpenWrt backend
to use "band" instead of "hwmode".
"""
if not hasattr(channels, 'channels_6ghz'):
raise ImproperlyConfigured(
'The installed netjsonconfig package does not support'
' defining "band" property for "radio" configuration introduced'
' in OpenWrt 21. Install the latest version of netjsonconfig'
' and run migrations again.'
)
Config = apps.get_model('config', 'Config')
Template = apps.get_model('config', 'Template')

update_config_for_model(Config, hwmode_to_band, 'band')
update_config_for_model(Template, hwmode_to_band, 'band')


def reverse(apps, schema_editor):
"""
Updates "radio" configuration for OpenWrt backend
to use "hwmode" instead of "band".
"""
if not hasattr(channels, 'channels_6ghz'):
raise ImproperlyConfigured(
'The installed netjsonconfig package does not support'
' defining "band" property for "radio" configuration introduced'
' in OpenWrt 21. Install the latest version of netjsonconfig'
' and run migrations again.'
)
Config = apps.get_model('config', 'Config')
Template = apps.get_model('config', 'Template')

update_config_for_model(Config, band_to_hwmode, 'hwmode')
update_config_for_model(Template, band_to_hwmode, 'hwmode')


class Migration(migrations.Migration):

dependencies = [
('config', '0047_add_organizationlimits'),
]

operations = [migrations.RunPython(forward, reverse_code=reverse)]
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,9 @@ div.jsoneditor > div > h3.controls{
.jsoneditor-wrapper div.jsoneditor .grid-column > div > .inline-group > .form-row > .vTextField {
padding-left: 100px !important
}
.jsoneditor-wrapper div[data-schemapath^="root.radios"][data-schemapath$=".hwmode"] {
display: none;
}
.jsoneditor-wrapper div[data-schemapath^="root.radios"][data-schemapath$=".band"] {
display: none;
}
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
django-sortedm2m~=3.1.1
django-reversion~=5.0.4
django-taggit~=4.0.0
netjsonconfig~=1.0.1
netjsonconfig @ https://github.com/openwisp/netjsonconfig/tarball/master
django-x509 @ https://github.com/openwisp/django-x509/tarball/master
django-loci @ https://github.com/openwisp/django-loci/tarball/master
django-flat-json-widget @ https://github.com/openwisp/django-flat-json-widget/tarball/master
Expand Down

0 comments on commit 89a501d

Please sign in to comment.