mirror of
https://github.com/Telecominfraproject/ols-ucentral-schema.git
synced 2025-10-29 17:22:23 +00:00
usync-schema: add serveral new schemas and templates
Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.schema
|
||||
@@ -7,6 +7,9 @@ In order to run the test cases you will need the following tools
|
||||
* utpl
|
||||
* usync-jsonschema
|
||||
* jsonlint-php
|
||||
* pip3 install jsonschema2md
|
||||
* pip3 install json-schema-for-humans
|
||||
* pip3 install python-json2yaml
|
||||
|
||||
### Unit testing
|
||||
```sh
|
||||
|
||||
16
cfg_log.tpl
Normal file
16
cfg_log.tpl
Normal file
@@ -0,0 +1,16 @@
|
||||
{%
|
||||
function generate_log() {
|
||||
local log = {};
|
||||
|
||||
uci_set_option(log, cfg.log, "log_size");
|
||||
|
||||
if (uci_requires(cfg.log, [ "log_proto", "log_ip", "log_port" ])) {
|
||||
uci_set_options(log, cfg.log, [ "log_proto", "log_ip", "log_port", "log_hostname" ]);
|
||||
log.log_remote = 1;
|
||||
}
|
||||
|
||||
uci_render("system", { "@system[-1]": log});
|
||||
}
|
||||
|
||||
generate_log();
|
||||
%}
|
||||
192
cfg_network.tpl
Normal file
192
cfg_network.tpl
Normal file
@@ -0,0 +1,192 @@
|
||||
{%
|
||||
function fw_generate_zone(x, n, masq) {
|
||||
local u = uci_new_section(x, n, "zone", {"name": n, "network": n});
|
||||
|
||||
if (masq) {
|
||||
u.input = "REJECT";
|
||||
u.output = "ACCEPT";
|
||||
u.forward = "REJECT";
|
||||
u.masq = 1;
|
||||
u.mtu_fix = 1;
|
||||
} else {
|
||||
u.input = "ACCEPT";
|
||||
u.output = "ACCEPT";
|
||||
u.forward = "ACCEPT";
|
||||
}
|
||||
}
|
||||
|
||||
function fw_generate_fwd(x, src, dest) {
|
||||
local name = sprintf("%s_%s", src, dest);
|
||||
|
||||
uci_new_section(x, name, "forwarding", {"src": src, "dest": dest});
|
||||
}
|
||||
|
||||
function fw_generate_guest(x, src, ipaddr) {
|
||||
local allow = sprintf("%s_allow", src);
|
||||
local block = sprintf("%s_block", src);
|
||||
|
||||
if (ipaddr)
|
||||
uci_new_section(x, allow, "rule", {"src": src, "family": "ipv4",
|
||||
"dest_ip": ipaddr,
|
||||
"proto": "tcp udp", "target": "ACCEPT" });
|
||||
|
||||
uci_new_section(x, block, "rule", {"src": src, "family": "ipv4",
|
||||
"dest_ip": "192.168.0.0/16 172.16.0.0/24 10.0.0.0/24",
|
||||
"proto": "tcp udp", "target": "REJECT" });
|
||||
}
|
||||
|
||||
function bridge_generate_vlan(x, n, vid) {
|
||||
local name = sprintf("%s_vlan", n);
|
||||
local ports = "";
|
||||
|
||||
uci_new_section(x, name, "bridge-vlan", {"device": "bridge", "vlan": vid,
|
||||
"ports": capab.network.wan.ifname + ":t"});
|
||||
}
|
||||
|
||||
function dhcp_generate(x, v, n) {
|
||||
local u = uci_new_section(x, n, "dhcp", {"interface": n});
|
||||
|
||||
if (!v) {
|
||||
u.ignore = 1;
|
||||
return;
|
||||
}
|
||||
uci_defaults(v, { "start": 100, "limit": 100, "leasetime": "12h" });
|
||||
uci_set_options(u, v, ["start", "limit", "leasetime"]);
|
||||
}
|
||||
|
||||
function lease_generate(x, v) {
|
||||
if (!uci_requires(v, [ "hostname", "mac", "ip" ]))
|
||||
return;
|
||||
|
||||
uci_new_section(x, v.hostname, "host", {
|
||||
"hostname": v.hostname,
|
||||
"ip": v.ip,
|
||||
"mac":v.mac
|
||||
});
|
||||
}
|
||||
|
||||
function network_generate_vlan_rule(x, v, n) {
|
||||
if (!v.vlan)
|
||||
return;
|
||||
local name = sprintf("%s_route", n);
|
||||
|
||||
uci_new_section(x, name, "rule", {"in": n, "lookup": v.vlan});
|
||||
}
|
||||
|
||||
function network_generate_name(n, v) {
|
||||
if (v.name && n in ["guest", "nat"])
|
||||
n = v.name;
|
||||
return v.vlan ? sprintf("%s%d", n, v.vlan) : n;
|
||||
}
|
||||
|
||||
function network_generate_static(x, v, n) {
|
||||
local u = uci_new_section(x, n, "interface", {"proto": "static"});
|
||||
|
||||
uci_defaults(v, {"netmask": "255.255.255.0"});
|
||||
uci_set_options(u, v, ["ipaddr", "netmask", "gateway", "dns"]);
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
function network_generate_dhcp(x, v, n) {
|
||||
local u = uci_new_section(x, n, "interface", {"proto": "dhcp"});
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
function network_generate_base(x, v, n) {
|
||||
local u;
|
||||
|
||||
switch(v.proto) {
|
||||
case "dhcp":
|
||||
u = network_generate_dhcp(x.network, v, n);
|
||||
break;
|
||||
case "static":
|
||||
u = network_generate_static(x.network, v, n);
|
||||
break;
|
||||
default:
|
||||
warn("Unhandled network proto\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uci_set_options(u, v, ["mtu", "ip6assign", "disabled"]);
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
function network_generate_wan(x, v) {
|
||||
local name = network_generate_name("wan", v);
|
||||
local u;
|
||||
|
||||
u = network_generate_base(x, v.cfg, name);
|
||||
if (v.vlan) {
|
||||
u.ifname = sprintf("bridge.%d", v.vlan);
|
||||
u.ip4table = v.vlan;
|
||||
u.ip6table = v.vlan;
|
||||
bridge_generate_vlan(x.network, name, v.vlan);
|
||||
fw_generate_zone(x.firewall, name, true);
|
||||
}
|
||||
dhcp_generate(x.dhcp, false, name);
|
||||
}
|
||||
|
||||
function network_generate_lan(x, c, n) {
|
||||
local name = network_generate_name(n, c);
|
||||
local u;
|
||||
|
||||
u = network_generate_base(x, c.cfg, name);
|
||||
dhcp_generate(x.dhcp, c.cfg.dhcp, name);
|
||||
for (local k, v in c.cfg.leases)
|
||||
lease_generate(x.dhcp, v);
|
||||
network_generate_vlan_rule(x.network, c, name);
|
||||
return u;
|
||||
}
|
||||
|
||||
function network_generate_nat(x, c, n) {
|
||||
local name = network_generate_name(n, c);
|
||||
local wan = network_generate_name("wan", c);
|
||||
local u;
|
||||
|
||||
u = network_generate_lan(x, c, n);
|
||||
u.type = "bridge";
|
||||
|
||||
fw_generate_zone(x.firewall, name);
|
||||
fw_generate_fwd(x.firewall, name, wan);
|
||||
}
|
||||
|
||||
function network_generate_guest(x, c) {
|
||||
local name = network_generate_name("guest", c);
|
||||
|
||||
network_generate_nat(x, c, "guest");
|
||||
fw_generate_guest(x.firewall, name, c.cfg.ipaddr);
|
||||
}
|
||||
|
||||
function network_generate() {
|
||||
local uci = {
|
||||
"network": {},
|
||||
"dhcp": {},
|
||||
"firewall": {}
|
||||
};
|
||||
|
||||
for (local k, v in cfg.network) {
|
||||
switch (v.mode) {
|
||||
case "wan":
|
||||
network_generate_wan(uci, v);
|
||||
break;
|
||||
case "nat":
|
||||
network_generate_nat(uci, v, "nat");
|
||||
break;
|
||||
case "lan":
|
||||
network_generate_lan(uci, v, "lan");
|
||||
break;
|
||||
case "guest":
|
||||
network_generate_guest(uci, v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
uci_render("network", uci.network);
|
||||
uci_render("dhcp", uci.dhcp);
|
||||
uci_render("firewall", uci.firewall);
|
||||
}
|
||||
|
||||
network_generate();
|
||||
%}
|
||||
13
cfg_ntp.tpl
Normal file
13
cfg_ntp.tpl
Normal file
@@ -0,0 +1,13 @@
|
||||
{%
|
||||
function generate_ntp() {
|
||||
local ntp= {};
|
||||
|
||||
uci_set_option(ntp, cfg.ntp, "enabled");
|
||||
uci_set_option(ntp, cfg.ntp, "enable_server");
|
||||
uci_set_option(ntp, cfg.ntp, "server");
|
||||
|
||||
uci_render("system", { "ntp": ntp});
|
||||
}
|
||||
|
||||
generate_ntp();
|
||||
%}
|
||||
114
cfg_phy.tpl
Normal file
114
cfg_phy.tpl
Normal file
@@ -0,0 +1,114 @@
|
||||
{%
|
||||
function ssid_generate(x, v, radio) {
|
||||
local crypto = "none";
|
||||
|
||||
if (!uci_requires(v, [ "network", "ssid", "mode", "encryption"])) {
|
||||
warn("ssid is missing a required option\n");
|
||||
return;
|
||||
}
|
||||
if (v.encryption in [ "psk", "psk2", "psk-mixed" ]) {
|
||||
if (!uci_requires(v, [ "key"])) {
|
||||
warn("ssid has invalid psk options\n");
|
||||
return;
|
||||
}
|
||||
crypto = "psk";
|
||||
} else if (v.encryption in [ "wpa", "wpa2", "wpa-mixed" ]) {
|
||||
if (!uci_requires(v, [ "server", "port", "auth_secret" ])) {
|
||||
warn("ssid has invalid wpa options\n");
|
||||
return;
|
||||
}
|
||||
crypto = "wpa";
|
||||
}
|
||||
local name = sprintf("%s_%s", radio, v.network);
|
||||
local u = uci_new_section(x, name, "wifi-iface", { "device": radio });
|
||||
uci_set_options(u, v, ["ssid", "network", "mode", "dtim_period", "hidden",
|
||||
"ieee80211k", "ieee80211k", "ieee80211v", "ieee80211w",
|
||||
"isolate", "rts_threshold", "uapsd", "ft_over_ds",
|
||||
"ft_psk_generate_local", "mobility_domain" ]);
|
||||
switch(crypto) {
|
||||
case "psk":
|
||||
uci_set_option(u, v, "key");
|
||||
break;
|
||||
case "wpa":
|
||||
uci_set_options(u, v, [ "server", "port", "auth_secret" ]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function phy_htmode_verify(c, v) {
|
||||
if (index(v, "HE") == 0 && c.he_capa)
|
||||
return v;
|
||||
if (index(v, "VHT") == 0 && c.vht_capa)
|
||||
return v;
|
||||
if (index(v, "HT") == 0 && c.ht_capa)
|
||||
return v;
|
||||
return "HT20";
|
||||
}
|
||||
|
||||
function phy_channel_verify(c, v) {
|
||||
if (v <= 16 && "2" in c.band)
|
||||
return v;
|
||||
if (v >= 32 && v <= 68 && ("5" in c.band || "5l" in c.band))
|
||||
return v;
|
||||
if (v >= 96 && v <= 173 && ("5" in c.band || "5u" in c.band))
|
||||
return v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
function phy_generate_options(x, c, v) {
|
||||
local u = uci_new_section(x, c.uci, "wifi-device");
|
||||
|
||||
if (v.htmode)
|
||||
u.htmode = phy_htmode_verify(c, v.htmode);
|
||||
if (v.channel)
|
||||
u.channel = phy_channel_verify(c, v.channel);
|
||||
|
||||
uci_set_options(u, v, ["disabled", "country", "beacon_int", "txpower",
|
||||
"chanbw", "require_mode", "txantenna", "rxantenna", "legacy_rates"]);
|
||||
}
|
||||
|
||||
function phy_generate(wifi, x) {
|
||||
for (local phy in cfg.phy):
|
||||
if (phy.band in x.band === false)
|
||||
continue;
|
||||
|
||||
phy_generate_options(wifi, x, phy.cfg);
|
||||
|
||||
for (local ssid in cfg.ssid):
|
||||
for (local band in ssid.band):
|
||||
if (band != phy.band)
|
||||
continue;
|
||||
ssid_generate(wifi, ssid.cfg, x.uci);
|
||||
endfor
|
||||
endfor
|
||||
return true;
|
||||
endfor
|
||||
return false;
|
||||
}
|
||||
|
||||
function wifi_generate() {
|
||||
local wifi= {};
|
||||
|
||||
if (!capab.wifi)
|
||||
return;
|
||||
|
||||
cursor = uci.cursor();
|
||||
cursor.load("wireless");
|
||||
cursor.foreach("wireless", "wifi-device", function(d) {
|
||||
if (!capab.wifi[d.path])
|
||||
continue;
|
||||
capab.wifi[d.path]["uci"] = d[".name"];
|
||||
});
|
||||
|
||||
for (local path in capab.wifi):
|
||||
local phy = capab.wifi[path];
|
||||
|
||||
if (phy_generate(wifi, phy) === false):
|
||||
wifi[phy.uci] = {"disabled": "1"};
|
||||
endif
|
||||
endfor
|
||||
uci_render("wireless", wifi);
|
||||
}
|
||||
|
||||
wifi_generate();
|
||||
%}
|
||||
12
cfg_ssh.tpl
Normal file
12
cfg_ssh.tpl
Normal file
@@ -0,0 +1,12 @@
|
||||
{%
|
||||
function generate_ssh() {
|
||||
local ssh= {};
|
||||
|
||||
uci_set_option(ssh, cfg.ssh, "enable");
|
||||
uci_set_option(ssh, cfg.ssh, "Port");
|
||||
|
||||
uci_render("dropbear", { "@dropbear[-1]": ssh});
|
||||
}
|
||||
|
||||
generate_ssh();
|
||||
%}
|
||||
10
cfg_system.tpl
Normal file
10
cfg_system.tpl
Normal file
@@ -0,0 +1,10 @@
|
||||
{%
|
||||
function generate_system() {
|
||||
local system = {};
|
||||
|
||||
uci_set_options(system, cfg.system, [ "hostname", "timezone" ]);
|
||||
uci_render("system", { "@system[-1]": system});
|
||||
}
|
||||
|
||||
generate_system();
|
||||
%}
|
||||
8
cmd.tpl
Normal file
8
cmd.tpl
Normal file
@@ -0,0 +1,8 @@
|
||||
{%
|
||||
try {
|
||||
if (match(cmd.cmd, /^[A-Za-z0-9_]+$/))
|
||||
include(sprintf("cmd_%s.tpl", cmd.cmd));
|
||||
} catch (e) {
|
||||
warn("Exception while executing: " + cmd + "\n");
|
||||
}
|
||||
%}
|
||||
3
cmd_factory.tpl
Normal file
3
cmd_factory.tpl
Normal file
@@ -0,0 +1,3 @@
|
||||
{%
|
||||
fs.popen('jffs2reset -r -y', 'r');
|
||||
%}
|
||||
4
cmd_reboot.tpl
Normal file
4
cmd_reboot.tpl
Normal file
@@ -0,0 +1,4 @@
|
||||
{%
|
||||
ctx = ubus.connect();
|
||||
ctx.call("system", "reboot");
|
||||
%}
|
||||
19
cmd_sysupgrade.tpl
Normal file
19
cmd_sysupgrade.tpl
Normal file
@@ -0,0 +1,19 @@
|
||||
{%
|
||||
if (!cmd.url) {
|
||||
warn("usync-upgrade: invalid FW URL\n");
|
||||
return;
|
||||
}
|
||||
path = "/tmp/usync.upgrade";
|
||||
fs.popen(sprintf('wget %s -O %s', cmd.url, path), 'r').close();
|
||||
|
||||
ctx = ubus.connect();
|
||||
fw = ctx.call("system", "validate_firmware_image", { "path": path });
|
||||
|
||||
if (!fw.valid) {
|
||||
ctx = ubus.connect();
|
||||
ctx.call("usync", "log", {"error": "firmware file validation failed", "data": fw});
|
||||
warn("usync-upgrade: firmware file validation failed\n");
|
||||
return;
|
||||
}
|
||||
fs.popen(sprintf('/sbin/sysupgrade %s', path), 'r').close();
|
||||
%}
|
||||
175
docs/schema_doc.css
Normal file
175
docs/schema_doc.css
Normal file
@@ -0,0 +1,175 @@
|
||||
body {
|
||||
font: 16px/1.5em "Overpass", "Open Sans", Helvetica, sans-serif;
|
||||
color: #333;
|
||||
font-weight: 300;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.btn.btn-link {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.jsfh-animated-property {
|
||||
animation: eclair;
|
||||
animation-iteration-count: 1;
|
||||
animation-fill-mode: forwards;
|
||||
animation-duration: .75s;
|
||||
|
||||
}
|
||||
|
||||
@keyframes eclair {
|
||||
0%,100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
}
|
||||
|
||||
.btn.btn-primary {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.btn.example-show.collapsed:before {
|
||||
content: "show"
|
||||
}
|
||||
|
||||
.btn.example-show:before {
|
||||
content: "hide"
|
||||
}
|
||||
|
||||
.description.collapse:not(.show) {
|
||||
max-height: 100px !important;
|
||||
overflow: hidden;
|
||||
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.description.collapsing {
|
||||
min-height: 100px !important;
|
||||
}
|
||||
|
||||
.collapse-description-link.collapsed:after {
|
||||
content: '+ Read More';
|
||||
}
|
||||
|
||||
.collapse-description-link:not(.collapsed):after {
|
||||
content: '- Read Less';
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-size: 100%;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.badge.value-type {
|
||||
font-size: 120%;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
.badge.default-value {
|
||||
font-size: 120%;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.badge.restriction {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.badge.required-property,.badge.deprecated-property,.badge.pattern-property,.badge.no-additional {
|
||||
font-size: 100%;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.accordion div.card:only-child {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
|
||||
.examples {
|
||||
padding: 1rem !important;
|
||||
}
|
||||
|
||||
.highlight.jumbotron {
|
||||
padding: 1rem !important;
|
||||
}
|
||||
|
||||
.generated-by-footer {
|
||||
margin-top: 1em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* From https://github.com/richleland/pygments-css/blob/master/friendly.css, see https://github.com/trentm/python-markdown2/wiki/fenced-code-blocks */
|
||||
.highlight { background: #e9ecef; } /* Changed from #f0f0f0 in the original style to be the same as bootstrap's jumbotron */
|
||||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight .c { color: #60a0b0; font-style: italic } /* Comment */
|
||||
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #666666 } /* Operator */
|
||||
.highlight .ch { color: #60a0b0; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #007020 } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #60a0b0; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
|
||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||
.highlight .go { color: #888888 } /* Generic.Output */
|
||||
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #902000 } /* Keyword.Type */
|
||||
.highlight .m { color: #40a070 } /* Literal.Number */
|
||||
.highlight .s { color: #4070a0 } /* Literal.String */
|
||||
.highlight .na { color: #4070a0 } /* Name.Attribute */
|
||||
.highlight .nb { color: #007020 } /* Name.Builtin */
|
||||
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #60add5 } /* Name.Constant */
|
||||
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
||||
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #007020 } /* Name.Exception */
|
||||
.highlight .nf { color: #06287e } /* Name.Function */
|
||||
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
|
||||
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
||||
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #bb60d5 } /* Name.Variable */
|
||||
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mb { color: #40a070 } /* Literal.Number.Bin */
|
||||
.highlight .mf { color: #40a070 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #40a070 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #40a070 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #40a070 } /* Literal.Number.Oct */
|
||||
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
|
||||
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
|
||||
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
|
||||
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
||||
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #235388 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
||||
.highlight .fm { color: #06287e } /* Name.Function.Magic */
|
||||
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
||||
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
|
||||
.highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */
|
||||
1
docs/schema_doc.min.js
vendored
Normal file
1
docs/schema_doc.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
function flashElement(t){myElement=document.getElementById(t),myElement.classList.add("jsfh-animated-property"),setTimeout(function(){myElement.classList.remove("jsfh-animated-property")},1e3)}function setAnchor(t){history.pushState({},"",t)}function anchorOnLoad(){let t=window.location.hash.split("?")[0].split("&")[0];"#"===t[0]&&(t=t.substr(1)),t.length>0&&anchorLink(t)}function anchorLink(t){$("#"+t).parents().addBack().filter(".collapse:not(.show), .tab-pane, [role='tab']").each(function(t){if($(this).hasClass("collapse"))$(this).collapse("show");else if($(this).hasClass("tab-pane")){const t=$("a[href='#"+$(this).attr("id")+"']");t&&t.tab("show")}else"tab"===$(this).attr("role")&&$(this).tab("show")}),setTimeout(function(){let e=document.getElementById(t);e&&(e.scrollIntoView({block:"center",behavior:"smooth"}),setTimeout(function(){flashElement(t)},500))},1e3)}$(document).on("click",'a[href^="#"]',function(t){t.preventDefault(),history.pushState({},"",this.href)});
|
||||
1
docs/usync-schema.html
Normal file
1
docs/usync-schema.html
Normal file
File diff suppressed because one or more lines are too long
88
docs/usync-schema.md
Normal file
88
docs/usync-schema.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# JSON Schema
|
||||
|
||||
*OpenWrt uSync schema*
|
||||
|
||||
## Properties
|
||||
|
||||
- **`uuid`** *(integer)*
|
||||
- **`network`** *(array)*: Network Configuration.
|
||||
- **Items** *(object)*: This section allows you to configure your networks.
|
||||
- **`mode`** *(string)*: This defines if the network interface shall be bridged directly with the WAN side or shall be NAT'ed out from LAN. Must be one of: `['wan', 'lan', 'nat', 'guest']`.
|
||||
- **`vlan`** *(number)*: The VID that shall be assign to packets leaving this network interface. Minimum: `16`. Maximum: `4095`.
|
||||
- **`name`** *(string)*: This option allows us to override the uci naming for NAT and guest networks.
|
||||
- **`cfg`** *(object)*
|
||||
- **`proto`** *(string)*: The configuration that shall be run on the network interface. Must be one of: `['none', 'dhcp', 'static']`.
|
||||
- **`ipaddr`** *(string)*: The IPv4 address that shall be assigned to the network interface.
|
||||
- **`netmask`** *(string)*: The IPv4 netmask that shall be assigned to the network interface.
|
||||
- **`gateway`** *(string)*: The IPv4 gateway that shall be assigned to the network interface.
|
||||
- **`dns`** *(string)*: The IPv4 DNS server that shall be assigned to the network interface.
|
||||
- **`mtu`** *(number)*: The MTU that shall be used by the network interface. Minimum: `256`. Maximum: `65535`.
|
||||
- **`disabled`** *(number)*: This option allows use to disable a network interface. Minimum: `0`. Maximum: `1`.
|
||||
- **`ip6assign`** *(number)*: The prefix delegation mask that the interface shall use. Minimum: `0`. Maximum: `96`.
|
||||
- **`dhcp`** *(object)*: The DHCP configuration of the network interface.
|
||||
- **`start`** *(number)*: This defines which number shall be used as the first leasable IP address. Minimum: `1`. Maximum: `254`.
|
||||
- **`limit`** *(number)*: This defines how many leasable IP addresses are available. Minimum: `10`.
|
||||
- **`leasetime`** *(string)*: This defines how many hours the leases should be valid for. (12h, 30m, ...).
|
||||
- **`leases`** *(array)*: A list of static dhcp leases assigned to the interface.
|
||||
- **Items** *(object)*
|
||||
- **`ip`** *(string)*: The IP address used by this static lease.
|
||||
- **`mac`** *(string)*: The MAC address used by this static lease.
|
||||
- **`hostname`** *(string)*: The hostname address used by this static lease.
|
||||
- **`phy`** *(array)*
|
||||
- **Items** *(object)*
|
||||
- **`band`** *(string)*: Must be one of: `['2', '5', '5u', '5l', '6']`.
|
||||
- **`cfg`** *(object)*
|
||||
- **`beacon_int`** *(number)*: Minimum: `50`. Maximum: `200`.
|
||||
- **`chanbw`** *(number)*: Must be one of: `[5, 10, 20]`.
|
||||
- **`channel`** *(number)*: Minimum: `0`. Maximum: `171`.
|
||||
- **`country`** *(string)*
|
||||
- **`disabled`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`htmode`** *(string)*: Must be one of: `['NOHT', 'HT20', 'HT40', 'HT40+', 'HT40-', 'VHT20', 'VHT40', 'VHT80', 'VHT160', 'HE20', 'HE40', 'HE80', 'HE160']`.
|
||||
- **`hwmode`** *(string)*: Must be one of: `['11a', '11g']`.
|
||||
- **`legacy_rates`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`require_mode`** *(string)*: Must be one of: `['g', 'n', 'ac', 'ax']`.
|
||||
- **`rxantenna`** *(number)*: Minimum: `0`. Maximum: `255`.
|
||||
- **`txantenna`** *(number)*: Minimum: `0`. Maximum: `255`.
|
||||
- **`txpower`** *(number)*: Minimum: `0`. Maximum: `30`.
|
||||
- **`ssid`** *(array)*: This is a list of all our SSIDs that shall be configured. Mapping of PHY/SSID is done via the "band" property.
|
||||
- **Items** *(object)*
|
||||
- **`band`** *(array)*: The list of wifi bands that the SSID should be broadcasted on. This value can be [ 2, 5, 5l, 5u, 6 ].
|
||||
- **`cfg`** *(object)*
|
||||
- **`auth_secret`** *(string)*
|
||||
- **`bss_transition`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`bssid`** *(string)*
|
||||
- **`dtim_period`** *(number)*: Minimum: `1`. Maximum: `255`.
|
||||
- **`encryption`** *(string)*: Must be one of: `['none', 'psk', 'psk2', 'psk-mixed', 'wpa', 'wpa2', 'wpa-mixed']`.
|
||||
- **`ft_over_ds`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`ft_psk_generate_local`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`hidden`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`ieee80211k`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`ieee80211r`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`ieee80211v`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`ieee80211w`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`isolate`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`key`** *(string)*
|
||||
- **`mobility_domain`** *(string)*
|
||||
- **`mode`** *(string)*: Must be one of: `['ap']`.
|
||||
- **`network`** *(string)*
|
||||
- **`port`** *(number)*: Minimum: `1024`. Maximum: `65535`.
|
||||
- **`rts_threshold`** *(number)*: Minimum: `1`. Maximum: `65535`.
|
||||
- **`server`** *(string)*
|
||||
- **`ssid`** *(string)*
|
||||
- **`uapsd`** *(number)*: Minimum: `0`. Maximum: `1`.
|
||||
- **`system`** *(object)*
|
||||
- **`hostname`** *(string)*: This allows you to change the hostname of the device.
|
||||
- **`timezone`** *(string)*: This allows you to change the TZ of the device.
|
||||
- **`log`** *(object)*
|
||||
- **`log_ip`** *(string)*: IP address of a syslog server to which the log messages should be sent in addition to the local destination.
|
||||
- **`log_port`** *(number)*: Port number of the remote syslog server specified with log_ip. Minimum: `100`. Maximum: `65535`.
|
||||
- **`log_proto`** *(string)*: Sets the protocol to use for the connection, either tcp or udp. Must be one of: `['tcp', 'udp']`.
|
||||
- **`log_hostname`** *(string)*: Hostname to send to remote syslog. If none is provided, the actual hostname is send.
|
||||
- **`log_size`** *(number)*: Size of the file based log buffer in KiB. This value is used as the fallback value for log_buffer_size if the latter is not specified. Minimum: `32`.
|
||||
- **`ntp`** *(object)*
|
||||
- **`enabled`** *(number)*: Enable this option to tell the unit that it shall get its time from an upstream NTP server. The servers are defined by the <servers> attribute. Minimum: `0`. Maximum: `1`.
|
||||
- **`enable_server`** *(number)*: Enable this option if you would like the unit to enable a downstream NTP server for its connected clients. Minimum: `0`. Maximum: `1`.
|
||||
- **`server`** *(array)*: This is an array of URL/IP of the upstream NTP servers that the unit shall use to acquire its current time.
|
||||
- **`ssh`** *(object)*
|
||||
- **`enable`** *(number)*: Enable this option if you would like to enable the SSH server on the unit. Minimum: `0`. Maximum: `1`.
|
||||
- **`Port`** *(number)*: This option defines which port the SSH server shall be available on. Minimum: `1`. Maximum: `65535`.
|
||||
14
generate.sh
Executable file
14
generate.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
sed -i "s/\t/ /g" -i *.yml
|
||||
|
||||
yaml2json network.yml network.schema
|
||||
yaml2json system.yml system.schema
|
||||
yaml2json log.yml log.schema
|
||||
yaml2json ntp.yml ntp.schema
|
||||
yaml2json ssh.yml ssh.schema
|
||||
yaml2json wifi-phy.yml wifi-phy.schema
|
||||
yaml2json wifi-ssid.yml wifi-ssid.schema
|
||||
./merge-schema.py
|
||||
jsonschema2md usync.schema.json docs/usync-schema.md
|
||||
generate-schema-doc usync.schema.json docs/usync-schema.html
|
||||
9
log.cfg
Normal file
9
log.cfg
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"log": {
|
||||
"log_proto": "udp",
|
||||
"log_ip": "192.168.11.23",
|
||||
"log_port": 12345,
|
||||
"log_hostname": "foo",
|
||||
"log_size": 128
|
||||
}
|
||||
}
|
||||
34
log.yml
Normal file
34
log.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
type: object
|
||||
properties:
|
||||
log:
|
||||
type: object
|
||||
properties:
|
||||
log_ip:
|
||||
description:
|
||||
IP address of a syslog server to which the log messages should be
|
||||
sent in addition to the local destination.
|
||||
type: string
|
||||
log_port:
|
||||
description:
|
||||
Port number of the remote syslog server specified with log_ip.
|
||||
type: number
|
||||
maximum: 65535
|
||||
minimum: 100
|
||||
log_proto:
|
||||
description:
|
||||
Sets the protocol to use for the connection, either tcp or udp.
|
||||
type: string
|
||||
enum:
|
||||
- tcp
|
||||
- udp
|
||||
log_hostname:
|
||||
description:
|
||||
Hostname to send to remote syslog. If none is provided, the actual
|
||||
hostname is send.
|
||||
type: string
|
||||
log_size:
|
||||
description:
|
||||
Size of the file based log buffer in KiB. This value is used as the fallback
|
||||
value for log_buffer_size if the latter is not specified.
|
||||
type: number
|
||||
minimum: 32
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import json
|
||||
|
||||
merge = {}
|
||||
|
||||
def config_merge(path):
|
||||
try:
|
||||
with open(path) as infile:
|
||||
cfg = json.load(infile)
|
||||
for k in cfg:
|
||||
merge[k] = cfg[k]
|
||||
print(f"merged {path}")
|
||||
except:
|
||||
print(f"failed to merge {path}")
|
||||
|
||||
def config_write():
|
||||
try:
|
||||
with open(f"usync.cfg", 'w') as outfile:
|
||||
json.dump(merge, outfile, indent=True)
|
||||
except:
|
||||
print("failed to write usync.cfg")
|
||||
|
||||
config_merge("wifi-phy.cfg")
|
||||
config_merge("wifi-ssid.cfg")
|
||||
config_write()
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
|
||||
@@ -31,4 +31,8 @@ def schema_write():
|
||||
schema_merge("network", "network.schema")
|
||||
schema_merge("phy", "wifi-phy.schema")
|
||||
schema_merge("ssid", "wifi-ssid.schema")
|
||||
schema_merge("system", "system.schema")
|
||||
schema_merge("log", "log.schema")
|
||||
schema_merge("ntp", "ntp.schema")
|
||||
schema_merge("ssh", "ssh.schema")
|
||||
schema_write()
|
||||
|
||||
39
network.cfg
Normal file
39
network.cfg
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"network": [
|
||||
{
|
||||
"mode": "bridge",
|
||||
"vlan": 200,
|
||||
"cfg": {
|
||||
"proto": "dhcp"
|
||||
}
|
||||
}, {
|
||||
"mode": "nat",
|
||||
"vlan": 200,
|
||||
"cfg": {
|
||||
"proto": "static",
|
||||
"ipaddr": "192.168.100.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"gateway": "192.168.100.2",
|
||||
"dns": "192.168.100.2",
|
||||
"mtu": 1500,
|
||||
"ip6assign": 60,
|
||||
"dhcp": {
|
||||
"start": 10,
|
||||
"limit": 100,
|
||||
"leasetime": "6h"
|
||||
},
|
||||
"leases": [
|
||||
{
|
||||
"ip": "192.168.100.2",
|
||||
"mac": "00:11:22:33:44:55",
|
||||
"hostname": "test"
|
||||
}, {
|
||||
"ip": "192.168.100.3",
|
||||
"mac": "00:11:22:33:44:56",
|
||||
"hostname": "test2"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
{"type": "object", "properties": {"network": {"type": "array", "items": {"type": "object", "properties": {"mode": {"type": "string", "enum": ["bridge", "nat"]}, "cfg": {"type": "object", "required": ["disabled"], "properties": {"proto": {"type": "string", "enum": ["dhcp", "static"]}, "ipaddr": {"type": "string"}, "netmask": {"type": "string"}, "gateway": {"type": "string"}, "dns": {"type": "string"}, "mtu": {"type": "number", "maximum": 65535, "minimum": 256}, "disabled": {"type": "number", "maximum": 1, "minimum": 0}, "ip6assign": {"type": "number", "maximum": 96, "minimum": 0}}}}}}}}
|
||||
{"type": "object", "properties": {"network": {"description": "Network Configuration", "type": "array", "items": {"description": "This section allows you to configure your networks.", "type": "object", "properties": {"mode": {"description": "This defines if the network interface shall be bridged directly with the WAN side or shall be NAT'ed out from LAN.", "type": "string", "enum": ["wan", "lan", "nat", "guest"]}, "vlan": {"description": "The VID that shall be assign to packets leaving this network interface.", "type": "number", "maximum": 4095, "minimum": 16}, "name": {"description": "This option allows us to override the uci naming for NAT and guest networks.", "type": "string"}, "cfg": {"type": "object", "properties": {"proto": {"description": "The configuration that shall be run on the network interface.", "type": "string", "enum": ["none", "dhcp", "static"]}, "ipaddr": {"description": "The IPv4 address that shall be assigned to the network interface.", "type": "string"}, "netmask": {"description": "The IPv4 netmask that shall be assigned to the network interface.", "type": "string"}, "gateway": {"description": "The IPv4 gateway that shall be assigned to the network interface.", "type": "string"}, "dns": {"description": "The IPv4 DNS server that shall be assigned to the network interface.", "type": "string"}, "mtu": {"description": "The MTU that shall be used by the network interface.", "type": "number", "maximum": 65535, "minimum": 256}, "disabled": {"description": "This option allows use to disable a network interface.", "type": "number", "maximum": 1, "minimum": 0}, "ip6assign": {"description": "The prefix delegation mask that the interface shall use.", "type": "number", "maximum": 96, "minimum": 0}, "dhcp": {"description": "The DHCP configuration of the network interface.", "type": "object", "properties": {"start": {"description": "This defines which number shall be used as the first leasable IP address.", "type": "number", "maximum": 254, "minimum": 1}, "limit": {"description": "This defines how many leasable IP addresses are available.", "type": "number", "minimum": 10}, "leasetime": {"description": "This defines how many hours the leases should be valid for. (12h, 30m, ...)", "type": "string"}}}, "leases": {"description": "A list of static dhcp leases assigned to the interface.", "type": "array", "items": {"type": "object", "properties": {"ip": {"description": "The IP address used by this static lease.", "type": "string"}, "mac": {"description": "The MAC address used by this static lease.", "type": "string"}, "hostname": {"description": "The hostname address used by this static lease.", "type": "string"}}}}}}}}}}}
|
||||
79
network.yml
79
network.yml
@@ -1,42 +1,115 @@
|
||||
type: object
|
||||
properties:
|
||||
network:
|
||||
description:
|
||||
Network Configuration
|
||||
type: array
|
||||
items:
|
||||
description:
|
||||
This section allows you to configure your networks.
|
||||
type: object
|
||||
properties:
|
||||
mode:
|
||||
description:
|
||||
This defines if the network interface shall be bridged directly with the
|
||||
WAN side or shall be NAT'ed out from LAN.
|
||||
type: string
|
||||
enum:
|
||||
- 'bridge'
|
||||
- 'wan'
|
||||
- 'lan'
|
||||
- 'nat'
|
||||
- 'guest'
|
||||
vlan:
|
||||
description:
|
||||
The VID that shall be assign to packets leaving this network interface.
|
||||
type: number
|
||||
maximum: 4095
|
||||
minimum: 16
|
||||
name:
|
||||
description:
|
||||
This option allows us to override the uci naming for NAT and guest networks.
|
||||
type: string
|
||||
cfg:
|
||||
type: object
|
||||
required:
|
||||
- disabled
|
||||
properties:
|
||||
proto:
|
||||
description:
|
||||
The configuration that shall be run on the network interface.
|
||||
type: string
|
||||
enum:
|
||||
- "none"
|
||||
- "dhcp"
|
||||
- "static"
|
||||
ipaddr:
|
||||
description:
|
||||
The IPv4 address that shall be assigned to the network interface.
|
||||
type: string
|
||||
netmask:
|
||||
description:
|
||||
The IPv4 netmask that shall be assigned to the network interface.
|
||||
type: string
|
||||
gateway:
|
||||
description:
|
||||
The IPv4 gateway that shall be assigned to the network interface.
|
||||
type: string
|
||||
dns:
|
||||
description:
|
||||
The IPv4 DNS server that shall be assigned to the network interface.
|
||||
type: string
|
||||
mtu:
|
||||
description:
|
||||
The MTU that shall be used by the network interface.
|
||||
type: number
|
||||
maximum: 65535
|
||||
minimum: 256
|
||||
disabled:
|
||||
description:
|
||||
This option allows use to disable a network interface.
|
||||
type: number
|
||||
maximum: 1
|
||||
minimum: 0
|
||||
ip6assign:
|
||||
description:
|
||||
The prefix delegation mask that the interface shall use.
|
||||
type: number
|
||||
maximum: 96
|
||||
minimum: 0
|
||||
dhcp:
|
||||
description:
|
||||
The DHCP configuration of the network interface.
|
||||
type: object
|
||||
properties:
|
||||
start:
|
||||
description:
|
||||
This defines which number shall be used as the first leasable IP address.
|
||||
type: number
|
||||
maximum: 254
|
||||
minimum: 1
|
||||
limit:
|
||||
description:
|
||||
This defines how many leasable IP addresses are available.
|
||||
type: number
|
||||
minimum: 10
|
||||
leasetime:
|
||||
description:
|
||||
This defines how many hours the leases should be valid for. (12h, 30m, ...)
|
||||
type: string
|
||||
leases:
|
||||
description:
|
||||
A list of static dhcp leases assigned to the interface.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
ip:
|
||||
description:
|
||||
The IP address used by this static lease.
|
||||
type: string
|
||||
mac:
|
||||
description:
|
||||
The MAC address used by this static lease.
|
||||
type: string
|
||||
hostname:
|
||||
description:
|
||||
The hostname address used by this static lease.
|
||||
type: string
|
||||
|
||||
11
ntp.cfg
Normal file
11
ntp.cfg
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"ntp": {
|
||||
"enabled": 1,
|
||||
"enable_server": 1,
|
||||
"server": [
|
||||
"0.openwrt.pool.ntp.org",
|
||||
"1.openwrt.pool.ntp.org",
|
||||
"2.openwrt.pool.ntp.org"
|
||||
]
|
||||
}
|
||||
}
|
||||
1
ntp.schema
Normal file
1
ntp.schema
Normal file
@@ -0,0 +1 @@
|
||||
{"type": "object", "properties": {"ntp": {"type": "object", "properties": {"enabled": {"description": "Enable this option to tell the unit that it shall get its time from an upstream NTP server. The servers are defined by the <servers> attribute.", "type": "number", "maximum": 1, "minimum": 0}, "enable_server": {"description": "Enable this option if you would like the unit to enable a downstream NTP server for its connected clients.", "type": "number", "maximum": 1, "minimum": 0}, "server": {"description": "This is an array of URL/IP of the upstream NTP servers that the unit shall use to acquire its current time.", "type": "array"}}}}}
|
||||
24
ntp.yml
Normal file
24
ntp.yml
Normal file
@@ -0,0 +1,24 @@
|
||||
type: object
|
||||
properties:
|
||||
ntp:
|
||||
type: object
|
||||
properties:
|
||||
enabled:
|
||||
description:
|
||||
Enable this option to tell the unit that it shall get its time from an upstream NTP
|
||||
server. The servers are defined by the <servers> attribute.
|
||||
type: number
|
||||
maximum: 1
|
||||
minimum: 0
|
||||
enable_server:
|
||||
description:
|
||||
Enable this option if you would like the unit to enable a downstream NTP server for
|
||||
its connected clients.
|
||||
type: number
|
||||
maximum: 1
|
||||
minimum: 0
|
||||
server:
|
||||
description:
|
||||
This is an array of URL/IP of the upstream NTP servers that the unit shall use to
|
||||
acquire its current time.
|
||||
type: array
|
||||
17
ssh.yml
Normal file
17
ssh.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
type: object
|
||||
properties:
|
||||
ssh:
|
||||
type: object
|
||||
properties:
|
||||
enable:
|
||||
description:
|
||||
Enable this option if you would like to enable the SSH server on the unit.
|
||||
type: number
|
||||
maximum: 1
|
||||
minimum: 0
|
||||
Port:
|
||||
description:
|
||||
This option defines which port the SSH server shall be available on.
|
||||
type: number
|
||||
maximum: 65535
|
||||
minimum: 1
|
||||
6
system.cfg
Normal file
6
system.cfg
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"system": {
|
||||
"hostname": "uSync",
|
||||
"timezone": "CET-1CEST,M3.5.0,M10.5.0/3"
|
||||
}
|
||||
}
|
||||
13
system.yml
Normal file
13
system.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
type: object
|
||||
properties:
|
||||
system:
|
||||
type: object
|
||||
properties:
|
||||
hostname:
|
||||
description:
|
||||
This allows you to change the hostname of the device.
|
||||
type: string
|
||||
timezone:
|
||||
description:
|
||||
This allows you to change the TZ of the device.
|
||||
type: string
|
||||
11
unit.sh
11
unit.sh
@@ -29,12 +29,15 @@ schema_test() {
|
||||
[ $? -eq 0 ] || error_inc
|
||||
}
|
||||
|
||||
./generate
|
||||
|
||||
schema_test network
|
||||
schema_test wifi-phy
|
||||
schema_test wifi-ssid
|
||||
|
||||
test_inc
|
||||
utpl -m fs -i wifi.tpl
|
||||
[ $? -eq 0 ] || error_inc
|
||||
schema_test ntp
|
||||
schema_test ssh
|
||||
schema_test system
|
||||
schema_test log
|
||||
|
||||
echo $error/$test failed
|
||||
|
||||
|
||||
54
usync.cfg
54
usync.cfg
@@ -1,8 +1,57 @@
|
||||
{
|
||||
"ssh": {
|
||||
"enable": 1,
|
||||
"Port": 2222
|
||||
},
|
||||
"ntp": {
|
||||
"enabled": 1,
|
||||
"enable_server": 1,
|
||||
"server": [
|
||||
"0.openwrt.pool.ntp.org",
|
||||
"1.openwrt.pool.ntp.org",
|
||||
"2.openwrt.pool.ntp.org"
|
||||
]
|
||||
},
|
||||
"network": [
|
||||
{
|
||||
"mode": "bridge",
|
||||
"cfg": {
|
||||
"proto": "dhcp"
|
||||
}
|
||||
},
|
||||
{
|
||||
"mode": "nat",
|
||||
"cfg": {
|
||||
"proto": "static",
|
||||
"ipaddr": "192.168.100.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"gateway": "192.168.100.2",
|
||||
"dns": "192.168.100.2",
|
||||
"mtu": 1500,
|
||||
"ip6assign": 60,
|
||||
"dhcp": {
|
||||
"start": 10,
|
||||
"limit": 100,
|
||||
"leasetime": "6h"
|
||||
},
|
||||
"leases": [
|
||||
{
|
||||
"ip": "192.168.100.2",
|
||||
"mac": "00:11:22:33:44:55",
|
||||
"hostname": "test"
|
||||
},
|
||||
{
|
||||
"ip": "192.168.100.3",
|
||||
"mac": "00:11:22:33:44:56",
|
||||
"hostname": "test2"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"phy": [
|
||||
{
|
||||
"band": "2",
|
||||
"name": "radio0",
|
||||
"cfg": {
|
||||
"disabled": 0,
|
||||
"country": "DE",
|
||||
@@ -20,7 +69,6 @@
|
||||
},
|
||||
{
|
||||
"band": "5",
|
||||
"name": "radio1",
|
||||
"cfg": {
|
||||
"disabled": 0,
|
||||
"country": "DE",
|
||||
@@ -50,7 +98,6 @@
|
||||
"key": "12345678",
|
||||
"server": "192.168.10.10",
|
||||
"auth_secret": "secret",
|
||||
"mobility_domain": "abc123",
|
||||
"port": 2000,
|
||||
"ft_over_ds": 0,
|
||||
"ft_psk_generate_local": 0,
|
||||
@@ -79,7 +126,6 @@
|
||||
"key": "12345678",
|
||||
"server": "192.168.10.10",
|
||||
"auth_secret": "secret",
|
||||
"mobility_domain": "abc123",
|
||||
"port": 2000,
|
||||
"ft_over_ds": 0,
|
||||
"ft_psk_generate_local": 0,
|
||||
|
||||
@@ -8,56 +8,119 @@
|
||||
"type": "integer"
|
||||
},
|
||||
"network": {
|
||||
"description": "Network Configuration",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"description": "This section allows you to configure your networks.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mode": {
|
||||
"description": "This defines if the network interface shall be bridged directly with the WAN side or shall be NAT'ed out from LAN.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"bridge",
|
||||
"nat"
|
||||
"wan",
|
||||
"lan",
|
||||
"nat",
|
||||
"guest"
|
||||
]
|
||||
},
|
||||
"vlan": {
|
||||
"description": "The VID that shall be assign to packets leaving this network interface.",
|
||||
"type": "number",
|
||||
"maximum": 4095,
|
||||
"minimum": 16
|
||||
},
|
||||
"name": {
|
||||
"description": "This option allows us to override the uci naming for NAT and guest networks.",
|
||||
"type": "string"
|
||||
},
|
||||
"cfg": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"disabled"
|
||||
],
|
||||
"properties": {
|
||||
"proto": {
|
||||
"description": "The configuration that shall be run on the network interface.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"none",
|
||||
"dhcp",
|
||||
"static"
|
||||
]
|
||||
},
|
||||
"ipaddr": {
|
||||
"description": "The IPv4 address that shall be assigned to the network interface.",
|
||||
"type": "string"
|
||||
},
|
||||
"netmask": {
|
||||
"description": "The IPv4 netmask that shall be assigned to the network interface.",
|
||||
"type": "string"
|
||||
},
|
||||
"gateway": {
|
||||
"description": "The IPv4 gateway that shall be assigned to the network interface.",
|
||||
"type": "string"
|
||||
},
|
||||
"dns": {
|
||||
"description": "The IPv4 DNS server that shall be assigned to the network interface.",
|
||||
"type": "string"
|
||||
},
|
||||
"mtu": {
|
||||
"description": "The MTU that shall be used by the network interface.",
|
||||
"type": "number",
|
||||
"maximum": 65535,
|
||||
"minimum": 256
|
||||
},
|
||||
"disabled": {
|
||||
"description": "This option allows use to disable a network interface.",
|
||||
"type": "number",
|
||||
"maximum": 1,
|
||||
"minimum": 0
|
||||
},
|
||||
"ip6assign": {
|
||||
"description": "The prefix delegation mask that the interface shall use.",
|
||||
"type": "number",
|
||||
"maximum": 96,
|
||||
"minimum": 0
|
||||
},
|
||||
"dhcp": {
|
||||
"description": "The DHCP configuration of the network interface.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"start": {
|
||||
"description": "This defines which number shall be used as the first leasable IP address.",
|
||||
"type": "number",
|
||||
"maximum": 254,
|
||||
"minimum": 1
|
||||
},
|
||||
"limit": {
|
||||
"description": "This defines how many leasable IP addresses are available.",
|
||||
"type": "number",
|
||||
"minimum": 10
|
||||
},
|
||||
"leasetime": {
|
||||
"description": "This defines how many hours the leases should be valid for. (12h, 30m, ...)",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"leases": {
|
||||
"description": "A list of static dhcp leases assigned to the interface.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ip": {
|
||||
"description": "The IP address used by this static lease.",
|
||||
"type": "string"
|
||||
},
|
||||
"mac": {
|
||||
"description": "The MAC address used by this static lease.",
|
||||
"type": "string"
|
||||
},
|
||||
"hostname": {
|
||||
"description": "The hostname address used by this static lease.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,18 +236,15 @@
|
||||
}
|
||||
},
|
||||
"ssid": {
|
||||
"description": "This is a list of all our SSIDs that shall be configured. Mapping of PHY/SSID is done via the \"band\" property.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"band": {
|
||||
"description": "The list of wifi bands that the SSID should be broadcasted on. This value can be [ 2, 5, 5l, 5u, 6 ].",
|
||||
"type": "array"
|
||||
},
|
||||
"name": {
|
||||
"maxLength": 16,
|
||||
"minLength": 1,
|
||||
"type": "string"
|
||||
},
|
||||
"cfg": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -302,6 +362,89 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"system": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"hostname": {
|
||||
"description": "This allows you to change the hostname of the device.",
|
||||
"type": "string"
|
||||
},
|
||||
"timezone": {
|
||||
"description": "This allows you to change the TZ of the device.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"log": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"log_ip": {
|
||||
"description": "IP address of a syslog server to which the log messages should be sent in addition to the local destination.",
|
||||
"type": "string"
|
||||
},
|
||||
"log_port": {
|
||||
"description": "Port number of the remote syslog server specified with log_ip.",
|
||||
"type": "number",
|
||||
"maximum": 65535,
|
||||
"minimum": 100
|
||||
},
|
||||
"log_proto": {
|
||||
"description": "Sets the protocol to use for the connection, either tcp or udp.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"tcp",
|
||||
"udp"
|
||||
]
|
||||
},
|
||||
"log_hostname": {
|
||||
"description": "Hostname to send to remote syslog. If none is provided, the actual hostname is send.",
|
||||
"type": "string"
|
||||
},
|
||||
"log_size": {
|
||||
"description": "Size of the file based log buffer in KiB. This value is used as the fallback value for log_buffer_size if the latter is not specified.",
|
||||
"type": "number",
|
||||
"minimum": 32
|
||||
}
|
||||
}
|
||||
},
|
||||
"ntp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Enable this option to tell the unit that it shall get its time from an upstream NTP server. The servers are defined by the <servers> attribute.",
|
||||
"type": "number",
|
||||
"maximum": 1,
|
||||
"minimum": 0
|
||||
},
|
||||
"enable_server": {
|
||||
"description": "Enable this option if you would like the unit to enable a downstream NTP server for its connected clients.",
|
||||
"type": "number",
|
||||
"maximum": 1,
|
||||
"minimum": 0
|
||||
},
|
||||
"server": {
|
||||
"description": "This is an array of URL/IP of the upstream NTP servers that the unit shall use to acquire its current time.",
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ssh": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enable": {
|
||||
"description": "Enable this option if you would like to enable the SSH server on the unit.",
|
||||
"type": "number",
|
||||
"maximum": 1,
|
||||
"minimum": 0
|
||||
},
|
||||
"Port": {
|
||||
"description": "This option defines which port the SSH server shall be available on.",
|
||||
"type": "number",
|
||||
"maximum": 65535,
|
||||
"minimum": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
usync.tpl
69
usync.tpl
@@ -1,5 +1,18 @@
|
||||
{%
|
||||
function render_uci(file, obj) {
|
||||
function uci_defaults(o, d) {
|
||||
for (local k, v in d)
|
||||
if (!o[k])
|
||||
o[k] = v;
|
||||
}
|
||||
|
||||
function uci_requires(o, d) {
|
||||
for (local k, v in d)
|
||||
if (!o[v])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function uci_render(file, obj) {
|
||||
for (local sname in obj):
|
||||
local section = obj[sname];
|
||||
|
||||
@@ -10,10 +23,60 @@ function render_uci(file, obj) {
|
||||
if (oname == ".type")
|
||||
continue;
|
||||
local option = section[oname];
|
||||
if (type(option) == "array"):
|
||||
-%}del {{file}}.{{ sname }}.{{ oname }}
|
||||
{%
|
||||
for (local k, v in option):
|
||||
-%}add_list {{file}}.{{ sname }}.{{ oname }}='{{ v }}'
|
||||
{%
|
||||
endfor
|
||||
else
|
||||
-%}set {{file}}.{{ sname }}.{{ oname }}='{{ option }}'
|
||||
{% endfor
|
||||
{%
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
}
|
||||
|
||||
include("wifi.tpl")
|
||||
function uci_new_section(x, name, type, vals) {
|
||||
x[name] = { ".type": type };
|
||||
|
||||
if (vals)
|
||||
for(local k,v in vals)
|
||||
x[name][k] = v;
|
||||
|
||||
return x[name];
|
||||
}
|
||||
|
||||
function uci_set_option(obj, cfg, key) {
|
||||
if (exists(cfg, key))
|
||||
obj[key] = cfg[key];
|
||||
}
|
||||
|
||||
function uci_set_options(obj, cfg, key) {
|
||||
for (local k, v in key)
|
||||
uci_set_option(obj, cfg, v);
|
||||
}
|
||||
|
||||
fails = {};
|
||||
failed = false;
|
||||
|
||||
for (key in cfg) {
|
||||
if (key in ["uuid", "ssid"])
|
||||
continue;
|
||||
try {
|
||||
include(sprintf("cfg_%s.tpl", key));
|
||||
} catch (e) {
|
||||
failed = true;
|
||||
fails[key] = e;
|
||||
warn("Exception while generating " + key + ": " + e + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
ctx = ubus.connect();
|
||||
ctx.call("usync", "log", {"error": "failed to apply config", "data": fails});
|
||||
exit(1);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"phy": [
|
||||
{
|
||||
"band": "2",
|
||||
"name": "radio0",
|
||||
"cfg": {
|
||||
"disabled": 0,
|
||||
"country": "DE",
|
||||
@@ -19,7 +18,6 @@
|
||||
}
|
||||
}, {
|
||||
"band": "5",
|
||||
"name": "radio1",
|
||||
"cfg": {
|
||||
"disabled": 0,
|
||||
"country": "DE",
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
"key": "12345678",
|
||||
"server": "192.168.10.10",
|
||||
"auth_secret": "secret",
|
||||
"mobility_domain": "abc123",
|
||||
"port": 2000,
|
||||
"ft_over_ds": 0,
|
||||
"ft_psk_generate_local": 0,
|
||||
@@ -35,7 +34,6 @@
|
||||
"key": "12345678",
|
||||
"server": "192.168.10.10",
|
||||
"auth_secret": "secret",
|
||||
"mobility_domain": "abc123",
|
||||
"port": 2000,
|
||||
"ft_over_ds": 0,
|
||||
"ft_psk_generate_local": 0,
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"type": "object", "properties": {"ssid": {"type": "array", "items": {"type": "object", "properties": {"band": {"type": "array"}, "name": {"maxLength": 16, "minLength": 1, "type": "string"}, "cfg": {"type": "object", "properties": {"auth_secret": {"type": "string"}, "bss_transition": {"maximum": 1, "minimum": 0, "type": "number"}, "bssid": {"maxLength": 17, "minLength": 17, "type": "string"}, "dtim_period": {"maximum": 255, "minimum": 1, "type": "number"}, "encryption": {"enum": ["none", "psk", "psk2", "psk-mixed", "wpa", "wpa2", "wpa-mixed"], "type": "string"}, "ft_over_ds": {"maximum": 1, "minimum": 0, "type": "number"}, "ft_psk_generate_local": {"maximum": 1, "minimum": 0, "type": "number"}, "hidden": {"maximum": 1, "minimum": 0, "type": "number"}, "ieee80211k": {"maximum": 1, "minimum": 0, "type": "number"}, "ieee80211r": {"maximum": 1, "minimum": 0, "type": "number"}, "ieee80211v": {"maximum": 1, "minimum": 0, "type": "number"}, "ieee80211w": {"maximum": 1, "minimum": 0, "type": "number"}, "isolate": {"maximum": 1, "minimum": 0, "type": "number"}, "key": {"maxLength": 63, "minLength": 8, "type": "string"}, "mobility_domain": {"type": "string"}, "mode": {"enum": ["ap"], "type": "string"}, "network": {"type": "string"}, "port": {"maximum": 65535, "minimum": 1024, "type": "number"}, "rts_threshold": {"maximum": 65535, "minimum": 1, "type": "number"}, "server": {"type": "string"}, "ssid": {"maxLength": 32, "minLength": 1, "type": "string"}, "uapsd": {"maximum": 1, "minimum": 0, "type": "number"}}}}}}}}
|
||||
{"type": "object", "properties": {"ssid": {"description": "This is a list of all our SSIDs that shall be configured. Mapping of PHY/SSID is done via the \"band\" property.", "type": "array", "items": {"type": "object", "properties": {"band": {"description": "The list of wifi bands that the SSID should be broadcasted on. This value can be [ 2, 5, 5l, 5u, 6 ].", "type": "array"}, "cfg": {"type": "object", "properties": {"auth_secret": {"type": "string"}, "bss_transition": {"maximum": 1, "minimum": 0, "type": "number"}, "bssid": {"maxLength": 17, "minLength": 17, "type": "string"}, "dtim_period": {"maximum": 255, "minimum": 1, "type": "number"}, "encryption": {"enum": ["none", "psk", "psk2", "psk-mixed", "wpa", "wpa2", "wpa-mixed"], "type": "string"}, "ft_over_ds": {"maximum": 1, "minimum": 0, "type": "number"}, "ft_psk_generate_local": {"maximum": 1, "minimum": 0, "type": "number"}, "hidden": {"maximum": 1, "minimum": 0, "type": "number"}, "ieee80211k": {"maximum": 1, "minimum": 0, "type": "number"}, "ieee80211r": {"maximum": 1, "minimum": 0, "type": "number"}, "ieee80211v": {"maximum": 1, "minimum": 0, "type": "number"}, "ieee80211w": {"maximum": 1, "minimum": 0, "type": "number"}, "isolate": {"maximum": 1, "minimum": 0, "type": "number"}, "key": {"maxLength": 63, "minLength": 8, "type": "string"}, "mobility_domain": {"type": "string"}, "mode": {"enum": ["ap"], "type": "string"}, "network": {"type": "string"}, "port": {"maximum": 65535, "minimum": 1024, "type": "number"}, "rts_threshold": {"maximum": 65535, "minimum": 1, "type": "number"}, "server": {"type": "string"}, "ssid": {"maxLength": 32, "minLength": 1, "type": "string"}, "uapsd": {"maximum": 1, "minimum": 0, "type": "number"}}}}}}}}
|
||||
@@ -1,16 +1,17 @@
|
||||
type: object
|
||||
properties:
|
||||
ssid:
|
||||
description:
|
||||
This is a list of all our SSIDs that shall be configured. Mapping of PHY/SSID is done via the
|
||||
"band" property.
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
band:
|
||||
description:
|
||||
The list of wifi bands that the SSID should be broadcasted on. This value can be [ 2, 5, 5l, 5u, 6 ].
|
||||
type: array
|
||||
name:
|
||||
maxLength: 16
|
||||
minLength: 1
|
||||
type: string
|
||||
cfg:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
62
wifi.tpl
62
wifi.tpl
@@ -1,62 +0,0 @@
|
||||
{%
|
||||
|
||||
function generate_ssid(wifi, radio, ssid, name) {
|
||||
local name = radio + "_" + ssid.name;
|
||||
|
||||
wifi[name] = {".type": "wifi-iface", "device": radio };
|
||||
for (local key in ssid.cfg):
|
||||
local val = ssid.cfg[key];
|
||||
wifi[name][key] = val;
|
||||
endfor
|
||||
}
|
||||
|
||||
function generate_phy(wifi, x) {
|
||||
for (local phy in cfg.phy):
|
||||
if (phy.band in x.band === false)
|
||||
continue;
|
||||
|
||||
wifi[x.uci] = {};
|
||||
for (local key in phy.cfg):
|
||||
local val = phy.cfg[key];
|
||||
|
||||
wifi[x.uci][key] = val;
|
||||
endfor
|
||||
|
||||
for (local ssid in cfg.ssid):
|
||||
for (local band in ssid.band):
|
||||
if (band != phy.band)
|
||||
continue;
|
||||
generate_ssid(wifi, x.uci, ssid);
|
||||
endfor
|
||||
endfor
|
||||
return true;
|
||||
endfor
|
||||
return false;
|
||||
}
|
||||
|
||||
function generate_wifi() {
|
||||
local wifi= {};
|
||||
|
||||
if (!capab.wifi)
|
||||
return;
|
||||
|
||||
cursor = uci.cursor();
|
||||
cursor.load("wireless");
|
||||
cursor.foreach("wireless", "wifi-device", function(d) {
|
||||
if (!capab.wifi[d.path])
|
||||
continue;
|
||||
capab.wifi[d.path]["uci"] = d[".name"];
|
||||
});
|
||||
|
||||
for (local path in capab.wifi):
|
||||
local phy = capab.wifi[path];
|
||||
|
||||
if (generate_phy(wifi, phy) === false):
|
||||
wifi[phy.uci] = {"disabled": "1"};
|
||||
endif
|
||||
endfor
|
||||
render_uci("wireless", wifi);
|
||||
}
|
||||
|
||||
generate_wifi();
|
||||
%}
|
||||
Reference in New Issue
Block a user