嵌入式设备的配置管理器,作为可重用的django-app实现
项目描述
嵌入式设备的配置管理器,作为可重用的django-app实现。
基于NetJSON格式和netjsonconfig库。
当前功能
- 支持不同固件的嵌入式设备的配置管理
可以通过指定自定义后端添加对其他固件的支持
基于JSON-Schema编辑器的配置编辑器
高级编辑模式:编辑NetJSON DeviceConfiguration对象以获得最大灵活性
配置模板:将重复性降到最低
配置变量:在配置和模板中引用类似Ansible的变量
模板标签:标记模板以自动化不同类型的自动配置(例如:网状,WDS,4G)
简单的HTTP资源:允许设备自动下载配置更新
VPN管理:轻松创建VPN服务器和客户端
项目目标
自动化嵌入式设备的配置管理
通过使用模板来最小化重复
提供由第三方应用程序扩展的基逻辑(请参阅扩展 django-netjsonconfig)
提供通过添加自定义后端来支持更多固件的方法
尽可能保持核心简单
在生产环境中部署
自动安装器可在ansible-openwisp2中找到。
依赖项
Python >=3.6
OpenSSL
从pypi安装稳定版本
从pypi安装
pip install django-netjsonconfig
安装开发版本
安装tarball
pip install https://github.com/openwisp/django-netjsonconfig/tarball/master
或者,您可以通过pip使用git安装
pip install -e git+git://github.com/openwisp/django-netjsonconfig#egg=django-netjsonconfig
如果您想贡献,请安装您克隆的分支
git clone git@github.com:<your_fork>/django-netjsonconfig.git
cd django-netjsonconfig
python setup.py develop
设置(集成到现有django项目中)
将django_netjsonconfig,django.contrib.admin,sortedm2m和reversion按以下顺序添加到INSTALLED_APPS
INSTALLED_APPS = [
# other apps
'openwisp_utils.admin_theme',
'django_netjsonconfig',
# ensure the django admin comes after django-netjsonconfig
'django.contrib.admin',
'sortedm2m',
'reversion' # optional, can be removed if not needed
# ...
]
将控制器URL添加到您的主urls.py
urlpatterns = [
# ... other urls in your project ...
# controller URLs
# used by devices to download/update their configuration
# keep the namespace argument unchanged
url(r'^', include('django_netjsonconfig.controller.urls', namespace='controller')),
# common URLs
# shared among django-netjsonconfig components
# keep the namespace argument unchanged
url(r'^', include('django_netjsonconfig.urls', namespace='netjsonconfig')),
]
然后运行
./manage.py migrate
为开发安装
安装sqlite
sudo apt-get install sqlite3 libsqlite3-dev openssl libssl-dev
安装您的分支仓库
git clone git://github.com/<your_fork>/django-netjsonconfig
cd django-netjsonconfig/
python setup.py develop
安装测试需求
pip install -r requirements-test.txt
创建数据库
cd tests/
./manage.py migrate
./manage.py createsuperuser
启动开发服务器
./manage.py runserver
您可以在http://127.0.0.1:8000/admin/访问管理界面。
使用以下命令运行测试
./runtests.py
如何使用配置变量
有时配置在所有设备上并不完全相同,有些参数对每个设备都是唯一的或需要用户修改。
在这种情况下,可以使用配置变量与模板结合使用,此功能也称为配置上下文,将其视为传递给配置渲染函数的字典,以便它可以根据传递的上下文填充变量。
以下将描述变量定义的不同方式。
预定义设备变量
每个设备都会获得以下属性,作为配置变量传递
id
key
name
mac_address
用户定义设备变量
在设备配置部分,您可以通过单击“高级选项(显示)”来访问上下文字段。
然后您可以将变量定义为键值字典(JSON格式),如下所示。
模板默认值
可以在模板中指定变量的默认值。
这可以实现两个目标
无错误地通过架构验证(否则一开始就无法保存模板)
提供在大多数情况下都有效,但如需在设备上覆盖的默认值
这些默认值将被用户定义的设备变量覆盖。
要这样做,请点击编辑模板页面上的“高级选项(显示)”
然后您可以定义变量的默认值
全局变量
也可以使用NETJSONCONFIG_CONTEXT设置全局定义变量。
变量示例用法
以下是一个典型用例,WiFi SSID和WiFi密码。您不希望为每个设备定义这些,但可能希望允许运营商轻松更改特定设备的SSID或WiFi密码,而无需重新定义整个WiFi接口以避免信息重复。
这将是模板
{
"interfaces": [
{
"type": "wireless",
"name": "wlan0",
"wireless": {
"mode": "access_point",
"radio": "radio0",
"ssid": "{{wlan0_ssid}}",
"encryption": {
"protocol": "wpa2_personal",
"key": "{{wlan0_password}}",
"cipher": "auto"
}
}
}
]
}
这些将是模板中的默认值
{
"wlan0_ssid": "SnakeOil PublicWiFi",
"wlan0_password": "Snakeoil_pwd!321654"
}
如果需要,可以在设备级别覆盖默认值,例如
{
"wlan0_ssid": "Room 23 ACME Hotel",
"wlan0_password": "room_23pwd!321654"
}
信号
config_modified
路径: django_netjsonconfig.signals.config_modified
参数:
instance:其config被修改的Config实例
每次修改设备的配置时,都会发出此信号。
如果Config.status已经修改,这不会影响信号的发出,因为这个信号表示设备配置已更改。
当设备首次创建时,不会触发此信号。
当启用推送功能(需要设备凭据)时,此信号用于触发设备的配置更新。
config_status_changed
路径: django_netjsonconfig.signals.config_status_changed
参数:
instance:其status被改变的Config实例
只有当设备的配置状态发生更改时,才会发出此信号。
请求校验和
路径: django_netjsonconfig.signals.checksum_requested
参数:
instance:请求其配置校验和的Device实例
request:HTTP请求对象
当设备通过控制器视图请求校验和时,会发出此信号。
在成功响应返回之前发出信号,如果响应未成功,则不会发送信号。
请求配置下载
路径: django_netjsonconfig.signals.config_download_requested
参数:
instance:请求下载其配置的Device实例
request:HTTP请求对象
当设备通过控制器视图请求下载其配置时,会发出此信号。
在成功响应返回之前发出信号,如果响应未成功,则不会发送信号。
设置
NETJSONCONFIG_BACKENDS
类型: |
元组 |
默认值: |
|
可用的配置后端。更多信息,请参阅netjsonconfig后端。
NETJSONCONFIG_VPN_BACKENDS
类型: |
元组 |
默认值: |
|
用于VPN服务器对象的可用VPN后端。更多信息,请参阅OpenVPN netjsonconfig后端。
VPN后端必须遵循一些基本规则才能与django-netjsonconfig兼容
它必须至少允许一个VPN实例,最多一个VPN实例
主NetJSON属性必须匹配类名的小写版本,例如:当使用OpenVpn后端时,系统将查看config['openvpn']
它应专注于所使用的VPN软件的服务器功能
NETJSONCONFIG_DEFAULT_BACKEND
类型: |
字符串 |
默认值: |
NETJSONCONFIG_BACKENDS[0][0] |
在管理界面中添加新的 Config 或 Template 对象时,将用作初始值的首选后端。
此设置默认为 NETJSONCONFIG_BACKENDS 设置中第一个项目的原始值,即 netjsonconfig.OpenWrt。
将其设置为 None 将强制用户显式选择。
NETJSONCONFIG_DEFAULT_VPN_BACKEND
类型: |
字符串 |
默认值: |
NETJSONCONFIG_VPN_BACKENDS[0][0] |
在管理界面中添加新的 Vpn 对象时,将用作初始值的首选后端。
此设置默认为 NETJSONCONFIG_VPN_BACKENDS 设置中第一个项目的原始值,即 django_netjsonconfig.vpn_backends.OpenVpn。
将其设置为 None 将强制用户显式选择。
NETJSONCONFIG_REGISTRATION_ENABLED
类型: |
布尔值 |
默认值: |
True |
设备是否可以通过控制器自动注册。
此功能默认启用。
为了正常工作,设备必须支持自动注册,有关更多信息,请参阅openwisp-config自动注册。
NETJSONCONFIG_CONSISTENT_REGISTRATION
类型: |
布尔值 |
默认值: |
True |
在重新刷机或重置后是否识别已注册的设备,从而保留现有配置而无需创建新的配置。
此功能默认启用。
为了正常工作,设备上也必须启用自动注册,有关更多信息,请参阅openwisp-config一致密钥生成。
NETJSONCONFIG_REGISTRATION_SELF_CREATION
类型: |
布尔值 |
默认值: |
True |
是否允许尚未存在于系统中的设备进行注册。
如果您仍然想使用自动注册来避免手动设置设备的UUID和密钥在配置文件中,但又想避免未经明确许可就注册新设备,请关闭此选项。
NETJSONCONFIG_CONTEXT
类型: |
字典 |
默认值: |
{} |
传递给每个设备对象默认上下文的附加上下文。
NETJSONCONFIG_CONTEXT 可以用来定义系统范围的配置变量。
有关在 OpenWISP 下一层处理变量的技术信息,请参阅 netjsonconfig 上下文:配置变量。
NETJSONCONFIG_DEFAULT_AUTO_CERT
类型: |
布尔值 |
默认值: |
True |
新 Template 对象的 auto_cert 字段的默认值。
auto_cert 字段仅对已将 type 设置为 VPN 的模板有效,表示是否应自动为使用该模板的每个配置创建新的 x509 证书。
当不再需要时(例如,当从配置对象中删除VPN模板时),自动创建的证书也将被删除。
NETJSONCONFIG_CERT_PATH
类型: |
字符串 |
默认值: |
/etc/x509 |
当使用 auto_cert(默认启用)并在路由器上下载时,x509 证书将被安装到的文件系统路径。
NETJSONCONFIG_COMMON_NAME_FORMAT
类型: |
字符串 |
默认值: |
{mac_address}-{name} |
定义在使用将 auto_cert 设置为 True 的 VPN 模板自动创建 VPN 客户端证书时 common_name 属性的格式。
NETJSONCONFIG_MANAGEMENT_IP_DEVICE_LIST
类型: |
布尔值 |
默认值: |
True |
在设备列表页面上,如果可用,则列 IP 将显示 management_ip,否则默认为 last_ip。
如果此设置设置为False,即使在设备列表页面存在,management_ip也不会显示,它只会显示在设备详情页。
如果出于某种原因,大多数用户不关心管理IP地址,您可以将其设置为False。
NETJSONCONFIG_BACKEND_DEVICE_LIST
类型: |
布尔值 |
默认值: |
True |
在设备列表页面,默认显示列backend和后端过滤器。
如果此设置设置为False,这些项将从UI中删除。
如果您仅使用一个配置后端,并且此UI元素对用户没有增加任何价值,您可以将其设置为False。
NETJSONCONFIG_HARDWARE_ID_ENABLED
类型: |
布尔值 |
默认值: |
False |
字段hardware_id可用于存储唯一的硬件ID,例如序列号。
如果此设置设置为True,则此字段将首先在设备列表页面和添加/编辑设备页面显示。
此功能默认禁用。
NETJSONCONFIG_HARDWARE_ID_OPTIONS
类型: |
字典 |
默认值: |
|
模型字段hardware_id的选项。
blank:字段是否允许为空
null:空值是否在数据库中以NULL存储
max_length:字段的最大长度
unique:字段值是否必须唯一
verbose_name:字段的用户可读标签的文本
help_text:与字段一起显示的帮助文本
NETJSONCONFIG_HARDWARE_ID_AS_NAME
类型: |
布尔值 |
默认值: |
True |
当启用硬件ID功能时,设备将通过其硬件ID而不是其名称进行引用。
如果您仍然希望通过名称引用设备,请将其设置为False。
扩展 django-netjsonconfig
django-netjsonconfig提供了一组模型、管理类和通用视图,可以被第三方应用程序导入、扩展和重用。
要扩展django-netjsonconfig,您绝对不能将其添加到settings.INSTALLED_APPS,但您必须创建自己的应用程序(该应用程序包含在settings.INSTALLED_APPS中),从django-netjsonconfig导入基本类,并添加您的自定义设置。
为了帮助django找到django-netjsonconfig的静态文件和模板,您需要执行以下步骤。
1. 添加 EXTENDED_APPS
将以下内容添加到您的settings.py
EXTENDED_APPS = ('django_netjsonconfig', 'django_x509',)
2. 添加 openwisp_utils.staticfiles.DependencyFinder
将openwisp_utils.staticfiles.DependencyFinder添加到您的settings.py中的STATICFILES_FINDERS
STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'openwisp_utils.staticfiles.DependencyFinder',
]
3. 添加 openwisp_utils.loaders.DependencyLoader
将openwisp_utils.loaders.DependencyLoader添加到您的settings.py中的TEMPLATES
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'OPTIONS': {
'loaders': [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'openwisp_utils.loaders.DependencyLoader',
],
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
}
]
扩展模型
此示例提供了一个示例,说明如何通过添加到名为Organization的另一个django模型的关系来扩展django-netjsonconfig的基本模型。
# models.py of your custom ``config`` app
from django.db import models
from sortedm2m.fields import SortedManyToManyField
from taggit.managers import TaggableManager
from django_netjsonconfig.base.config import AbstractConfig, TemplatesVpnMixin
from django_netjsonconfig.base.tag import AbstractTaggedTemplate, AbstractTemplateTag
from django_netjsonconfig.base.template import AbstractTemplate
from django_netjsonconfig.base.vpn import AbstractVpn, AbstractVpnClient
# the model ``organizations.Organization`` is omitted for brevity
# if you are curious to see a real implementation, check out django-organizations
# https://github.com/bennylope/django-organizations
class OrganizationMixin(models.Model):
organization = models.ForeignKey('organizations.Organization')
class Meta:
abstract = True
class Config(OrganizationMixin, TemplatesVpnMixin, AbstractConfig):
templates = SortedManyToManyField('config.Template',
related_name='config_relations',
blank=True)
vpn = models.ManyToManyField('config.Vpn',
through='config.VpnClient',
related_name='vpn_relations',
blank=True)
def clean(self):
# your own validation logic here...
pass
class Meta(AbstractConfig.Meta):
abstract = False
class TemplateTag(AbstractTemplateTag):
class Meta(AbstractTemplateTag.Meta):
abstract = False
class TaggedTemplate(AbstractTaggedTemplate):
tag = models.ForeignKey('config.TemplateTag',
related_name='%(app_label)s_%(class)s_items',
on_delete=models.CASCADE)
class Meta(AbstractTaggedTemplate.Meta):
abstract = False
class Template(OrganizationMixin, AbstractTemplate):
tags = TaggableManager(through='config.TaggedTemplate', blank=True)
vpn = models.ForeignKey('config.Vpn', blank=True, null=True)
def clean(self):
# your own validation logic here...
pass
class Meta(AbstractTemplate.Meta):
abstract = False
class Vpn(OrganizationMixin, AbstractVpn):
class Meta(AbstractVpn.Meta):
abstract = False
class VpnClient(AbstractVpnClient):
config = models.ForeignKey('config.Config', on_delete=models.CASCADE)
vpn = models.ForeignKey('config.Vpn', on_delete=models.CASCADE)
cert = models.OneToOneField('django_x509.Cert',
on_delete=models.CASCADE,
blank=True,
null=True)
class Meta(AbstractVpnClient.Meta):
abstract = False
扩展管理界面
在先前的Organization示例中,您可以通过导入基本管理类并使用它们来注册模型来避免重复管理代码。
# admin.py of your app
# these are your custom models, they must be imported before the abstract admin classes
from .models import Config, Template, Vpn
from django.contrib import admin
from django_netjsonconfig.base.admin import (AbstractConfigAdmin,
AbstractConfigForm,
AbstractTemplateAdmin,
AbstractVpnAdmin,
AbstractVpnForm,
BaseForm)
class ConfigForm(AbstractConfigForm):
class Meta(AbstractConfigForm.Meta):
model = Config
class ConfigAdmin(AbstractConfigAdmin):
form = ConfigForm
class TemplateForm(BaseForm):
class Meta(BaseForm.Meta):
model = Template
class TemplateAdmin(AbstractTemplateAdmin):
form = TemplateForm
class VpnForm(AbstractVpnForm):
class Meta(AbstractVpnForm.Meta):
model = Vpn
class VpnAdmin(AbstractVpnAdmin):
form = VpnForm
admin.site.register(Config, ConfigAdmin)
admin.site.register(Template, TemplateAdmin)
admin.site.register(Vpn, VpnAdmin)
扩展控制器视图
如果您的用例与基本用例没有很大差异,您也可能想尝试重用控制器视图
# your_config_app.controller.views
from ..models import Device, Vpn
from django_netjsonconfig.controller.generics import (BaseDeviceChecksumView, BaseDeviceDownloadConfigView,
BaseDeviceRegisterView, BaseDeviceReportStatusView,
BaseVpnChecksumView, BaseVpnDownloadConfigView)
class DeviceChecksumView(BaseDeviceChecksumView):
model = Device
class DeviceDownloadConfigView(BaseDeviceDownloadConfigView):
model = Device
class DeviceReportStatusView(BaseDeviceReportStatusView):
model = Device
class DeviceRegisterView(BaseDeviceRegisterView):
model = Device
class VpnChecksumView(BaseVpnChecksumView):
model = Vpn
class VpnDownloadConfigView(BaseVpnDownloadConfigView):
model = Vpn
device_checksum = DeviceChecksumView.as_view()
device_download_config = DeviceDownloadConfigView.as_view()
device_report_status = DeviceReportStatusView.as_view()
device_register = DeviceRegisterView.as_view()
vpn_checksum = VpnChecksumView.as_view()
vpn_download_config = VpnDownloadConfigView.as_view()
控制器URL
如果您没有对控制器视图进行重大更改,您可以通过使用get_controller_urls函数来避免重复URL逻辑。在您的控制器urls.py中放置此内容
# your_config_app.controller.urls
from django_netjsonconfig.utils import get_controller_urls
from . import views
urlpatterns = get_controller_urls(views)
扩展 AppConfig
您可能还想重用django-netjsonconfig的AppConfig类
from django_netjsonconfig.apps import DjangoNetjsonconfigApp
class MyOwnConfig(DjangoNetjsonconfigApp):
name = 'yourapp.config'
label = 'config'
def __setmodels__(self):
from .models import Config, VpnClient # these are your custom models
self.config_model = Config
self.vpnclient_model = VpnClient
django-netjsonconfig的真实世界扩展
有关扩展django-netjsonconfig的django项目的完整工作示例,请参阅
截图
贡献
在OpenWISP 邮件列表中宣布您的意图
分叉此存储库并安装它
编写代码
为您的代码编写测试
确保所有测试都通过
确保测试覆盖率不降低
记录您的更改
发送拉取请求
变更日志
查看变更记录。
许可证
查看许可证。
支持
项目详情
下载文件
下载您平台上的文件。如果您不确定选择哪个,请了解有关安装软件包的更多信息。
源分布
构建分布
哈希值 for django_netjsonconfig-0.12-py2.py3-none-any.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 1071ecbec1cd9d4fcd914cf15f52ce0627826c850aebf9385ffb89461128c778 |
|
MD5 | e09f2485dc28cec5f6b2c9ad6a1bf9f9 |
|
BLAKE2b-256 | 9413c9bc0b9e7ad5835dbaa2d0f90eea85ef9c025d7980b08634be6d8183904a |