-
-
Notifications
You must be signed in to change notification settings - Fork 183
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[change] Added data migration for changing "hwmode" to "band"
OpenWrt 21 introduced new property "band" for radio configuration that deprecates the "hwmode" property. Related to openwisp/netjsonconfig#236
- Loading branch information
Showing
3 changed files
with
162 additions
and
1 deletion.
There are no files selected for viewing
155 changes: 155 additions & 0 deletions
155
openwisp_controller/config/migrations/0048_wifi_radio_band_migration.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters