Compare commits

...

131 Commits

Author SHA1 Message Date
TIP Automation User
af7cbf0ce1 Chg: update image tag in helm values to v2.7.0-RC6 2022-10-05 02:46:05 +00:00
Stephane Bourque
d50e8c0c44 Merge pull request #74 from Telecominfraproject/main
Fix for WIFI-10942
2022-10-04 19:41:23 -07:00
stephb9959
c5e44f2a98 Merge remote-tracking branch 'origin/main' 2022-10-04 08:20:51 -07:00
stephb9959
5c2937c7ec https://telecominfraproject.atlassian.net/browse/WIFI-10942
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-10-04 08:20:42 -07:00
Dmitry Dunaev
698b467d3f Merge pull request #72 from Telecominfraproject/main
[WIFI-10581] Fix: securityContext fsGroup in helm
2022-10-03 15:54:01 +03:00
Dmitry Dunaev
a8f1483362 [WIFI-10581] Fix: securityContext fsGroup in helm
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-10-03 15:53:05 +03:00
TIP Automation User
693814de1c Chg: update image tag in helm values to v2.7.0-RC5 2022-10-03 11:14:26 +00:00
Dmitry Dunaev
0394369410 Merge pull request #71 from Telecominfraproject/main
[WIFI-10581] Add: postgresql-client in Dockerfile
2022-10-03 14:06:07 +03:00
Dmitry Dunaev
5abe7a9909 [WIFI-10581] Fix: Helm image to main
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-10-03 12:11:10 +03:00
Dmitry Dunaev
0a3a9a4b20 Merge pull request #70 from Telecominfraproject/fix/wifi-10581--postgres-client
[WIFI-10581] Add: postgresql-client in Dockerfile
2022-10-03 11:24:32 +03:00
Dmitry Dunaev
9d4eb1e502 [WIFI-10581] Add: postgresql-client in Dockerfile
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-10-03 11:24:15 +03:00
Stephane Bourque
0b6d68def5 Merge pull request #69 from Telecominfraproject/main
https://telecominfraproject.atlassian.net/browse/WIFI-10942
2022-10-02 11:30:41 -07:00
Stephane Bourque
51ba962338 Merge branch 'release/v2.7.0' into main 2022-10-02 11:30:09 -07:00
Stephane Bourque
fef07e3150 Merge pull request #68 from Telecominfraproject/WIFI-10942
https://telecominfraproject.atlassian.net/browse/WIFI-10942
2022-10-02 11:28:07 -07:00
Stephane Bourque
03a6675359 Merge branch 'main' into WIFI-10942 2022-10-02 11:27:38 -07:00
stephb9959
19686da4d8 https://telecominfraproject.atlassian.net/browse/WIFI-10942 2022-10-02 11:26:16 -07:00
stephb9959
c5997a3511 Merge remote-tracking branch 'origin/WIFI-10942' into WIFI-10942 2022-10-02 11:26:02 -07:00
Stephane Bourque
3feb5fd666 https://telecominfraproject.atlassian.net/browse/WIFI-10942 2022-10-02 11:25:53 -07:00
Stephane Bourque
d3cd3a1a21 https://telecominfraproject.atlassian.net/browse/WIFI-10942 2022-10-02 11:25:19 -07:00
Stephane Bourque
5e6228b9d6 Merge pull request #51 from Telecominfraproject/WIFI-10581-switch-images-to-debian-slim
[WIFI-10581] Switch microservice Docker images from Alpine to Debian-slim
2022-10-02 11:20:58 -07:00
TIP Automation User
ad526ebf1d Chg: update image tag in helm values to v2.7.0-RC4 2022-09-30 19:49:00 +00:00
Stephane Bourque
8de53277e6 Merge pull request #67 from Telecominfraproject/WIFI-10942
https://telecominfraproject.atlassian.net/browse/WIFI-10942
2022-09-30 11:27:14 -07:00
Stephane Bourque
93fbb3017a Merge branch 'release/v2.7.0' into WIFI-10942 2022-09-30 11:27:06 -07:00
stephb9959
2e4d1ad3e8 https://telecominfraproject.atlassian.net/browse/WIFI-10942
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-30 11:25:38 -07:00
TIP Automation User
109a9affc5 Chg: update image tag in helm values to v2.7.0-RC3 2022-09-30 16:31:37 +00:00
Stephane Bourque
9c65813735 Merge pull request #66 from Telecominfraproject/WIFI-10942
https://telecominfraproject.atlassian.net/browse/WIFI-10942
2022-09-30 09:00:23 -07:00
stephb9959
7d0bdf059d https://telecominfraproject.atlassian.net/browse/WIFI-10942
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-30 08:59:38 -07:00
TIP Automation User
93e4b069c4 Chg: update image tag in helm values to v2.7.0-RC2 2022-09-29 23:27:45 +00:00
jaspreetsachdev
4fe1367651 Merge pull request #65 from Telecominfraproject/main
Fixes WIFI-10821
2022-09-29 19:05:58 -04:00
Dmitry Dunaev
5f5f2fd699 Merge pull request #64 from Telecominfraproject/feature/wifi-10932--docker-support-http
[WIFI-10932] Add: restapi disable property in docker entrypoint
2022-09-28 17:37:09 +03:00
Dmitry Dunaev
c2e0d32e0d [WIFI-10932] Add: restapi disable property in docker entrypoint
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-09-28 17:36:34 +03:00
Dmitry Dunaev
cab81a3930 Merge pull request #63 from Telecominfraproject/feature/wifi-10582--helm-global-cert-secret
[WIFI-10582] Add: functionality to use external existing certificates secret
2022-09-28 17:06:06 +03:00
Dmitry Dunaev
01395f11a3 [WIFI-10582] Add: functionality to use external existing certificates secret
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-09-28 13:36:41 +03:00
Stephane Bourque
250c12acf1 Merge pull request #62 from Telecominfraproject/WIFI-10821
https://telecominfraproject.atlassian.net/browse/WIFI-10821
2022-09-27 08:27:17 -07:00
stephb9959
e23d04c1d0 https://telecominfraproject.atlassian.net/browse/WIFI-10821
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-27 08:26:46 -07:00
Stephane Bourque
b48955e791 Merge pull request #61 from Telecominfraproject/WIFI-10821
https://telecominfraproject.atlassian.net/browse/WIFI-10821
2022-09-22 20:41:44 -07:00
stephb9959
e58eb38d53 https://telecominfraproject.atlassian.net/browse/WIFI-10821
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-22 20:41:17 -07:00
Stephane Bourque
791af9aeba Merge pull request #60 from Telecominfraproject/WIFI-10821
https://telecominfraproject.atlassian.net/browse/WIFI-10821
2022-09-21 19:53:48 -07:00
stephb9959
67081917a9 https://telecominfraproject.atlassian.net/browse/WIFI-10821
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-21 19:53:10 -07:00
TIP Automation User
3a33815096 Chg: update image tag in helm values to v2.7.0-RC1 2022-09-16 19:55:04 +00:00
Stephane Bourque
f515bb8e30 Merge pull request #59 from Telecominfraproject/WIFI-10821
https://telecominfraproject.atlassian.net/browse/WIFI-10821
2022-09-14 00:00:15 -07:00
stephb9959
02fd6d726a https://telecominfraproject.atlassian.net/browse/WIFI-10821
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-13 23:57:49 -07:00
Stephane Bourque
27ffb31a7c Merge pull request #58 from Telecominfraproject/WIFI-10082
https://telecominfraproject.atlassian.net/browse/WIFI-10082
2022-09-08 09:55:57 -07:00
stephb9959
5fd9831d6b https://telecominfraproject.atlassian.net/browse/WIFI-10082
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-08 09:54:27 -07:00
Stephane Bourque
fed085cc4a Merge pull request #57 from Telecominfraproject/WIFI-10714
https://telecominfraproject.atlassian.net/browse/WIFI-10714
2022-09-02 12:32:07 -07:00
stephb9959
121fee841e https://telecominfraproject.atlassian.net/browse/WIFI-10714
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-02 12:28:59 -07:00
stephb9959
4c6f03ba14 https://telecominfraproject.atlassian.net/browse/WIFI-10752
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-02 12:10:19 -07:00
Stephane Bourque
0fb9478675 Merge pull request #56 from Telecominfraproject/WIFI-10752
https://telecominfraproject.atlassian.net/browse/WIFI-10752
2022-09-02 08:58:19 -07:00
stephb9959
97c2af83fd https://telecominfraproject.atlassian.net/browse/WIFI-10752
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-02 08:57:12 -07:00
Stephane Bourque
599ba0793c Merge pull request #55 from Telecominfraproject/WIFI-10714
https://telecominfraproject.atlassian.net/browse/WIFI-10714
2022-09-02 08:04:47 -07:00
stephb9959
6df780dba3 https://telecominfraproject.atlassian.net/browse/WIFI-10714
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-02 08:03:48 -07:00
Dmitry Dunaev
a00287ae85 Merge pull request #54 from Telecominfraproject/feature/wifi-10069--add-wait-postgres-initcontainer
[WIFI-10069] Add: helm - wait-postgres init container
2022-09-02 14:40:39 +03:00
Dmitry Dunaev
c7a300b81e [WIFI-10069] Add: helm - wait-postgres init container
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-09-02 14:40:18 +03:00
Stephane Bourque
5dc507a82e Merge pull request #52 from Telecominfraproject/WIFI-9988
https://telecominfraproject.atlassian.net/browse/WIFI-9988
2022-08-23 15:19:04 -07:00
stephb9959
8b3e1326b7 https://telecominfraproject.atlassian.net/browse/WIFI-9988
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-23 15:17:59 -07:00
stephb9959
667f8bc4bd https://telecominfraproject.atlassian.net/browse/WIFI-9988
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-23 09:26:41 -07:00
Johann Hoffmann
6cacebad28 Fix self-signed cert file extension for Debian
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-08-19 17:19:40 +02:00
Johann Hoffmann
e487b68945 Create necessary library links in Docker image
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-08-19 16:13:11 +02:00
Johann Hoffmann
ffddfa87d2 Switch to Debian-slim base images
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-08-18 17:53:53 +02:00
Stephane Bourque
0168301d6b Merge pull request #50 from Telecominfraproject/WIFI-10577
https://telecominfraproject.atlassian.net/browse/WIFI-10577
2022-08-16 09:04:00 -07:00
stephb9959
1a0b00e989 https://telecominfraproject.atlassian.net/browse/WIFI-10577
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-16 09:02:59 -07:00
Dmitry Dunaev
7c2229f3d6 Merge pull request #49 from Telecominfraproject/fix/wifi-10413--cve-fix
[WIFI-10413] Fix: vulnerable base Docker image version
2022-08-15 13:31:04 +03:00
Dmitry Dunaev
541df429ec [WIFI-10413] Fix: vulnerable base Docker image version
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-08-15 11:16:55 +03:00
Stephane Bourque
6f9fe6cd5d Merge pull request #48 from Telecominfraproject/WIFI-10245
https://telecominfraproject.atlassian.net/browse/WIFI-10245
2022-08-10 16:35:14 -07:00
stephb9959
2594a2c5f2 https://telecominfraproject.atlassian.net/browse/WIFI-10245
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-10 16:34:47 -07:00
Stephane Bourque
2e02d96523 Merge pull request #47 from Telecominfraproject/feature/wifi-10388--versioning
[WIFI-10388] Chg: use Docker build arg to define dependency version
2022-08-08 12:12:49 -07:00
Dmitry Dunaev
a1375f9468 [WIFI-10388] Chg: use Docker build arg to define dependency version
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-08-08 17:44:29 +03:00
Stephane Bourque
777bc0f2aa Merge pull request #46 from Telecominfraproject/WIFI-10388
https://telecominfraproject.atlassian.net/browse/WIFI-10388
2022-08-07 22:29:22 -07:00
stephb9959
bd0e99309c https://telecominfraproject.atlassian.net/browse/WIFI-10388
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-07 22:28:45 -07:00
Stephane Bourque
6cb6a60142 Merge pull request #45 from Telecominfraproject/WIFI-10388
https://telecominfraproject.atlassian.net/browse/WIFI-10388
2022-08-01 09:16:08 -07:00
stephb9959
fc7947394d https://telecominfraproject.atlassian.net/browse/WIFI-10388
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-01 09:13:54 -07:00
stephb9959
1341e15874 https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-26 14:51:49 -07:00
stephb9959
f065815df3 https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-25 12:44:48 -07:00
stephb9959
03ba51e869 https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-24 12:21:13 -07:00
stephb9959
efd7ef2a9b https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-24 12:14:39 -07:00
stephb9959
4b90a6e893 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-11 08:51:21 -07:00
stephb9959
f5cb4a5a87 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-11 07:17:25 -07:00
stephb9959
e3e4aac202 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-11 07:06:12 -07:00
Stephane Bourque
5945d02b3d Merge pull request #43 from Telecominfraproject/WIFI-10070
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
2022-07-10 08:56:53 -07:00
stephb9959
0ac192cdc0 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-10 08:55:45 -07:00
stephb9959
1b5eb87eef Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-09 21:15:07 -07:00
stephb9959
46db18d7cd Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-09 21:13:10 -07:00
stephb9959
30b8665d7d Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-09 20:37:21 -07:00
stephb9959
c8b3a3b060 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-09 20:36:00 -07:00
Stephane Bourque
096da35ff4 Merge pull request #41 from Telecominfraproject/WIFI-10070
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
2022-07-08 22:11:59 -07:00
stephb9959
bd7f3af11c Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-08 22:10:57 -07:00
Stephane Bourque
2a06021c4a Merge pull request #40 from Telecominfraproject/WIFI-10070
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
2022-07-08 21:55:15 -07:00
stephb9959
bf18bb25ba Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-08 21:54:35 -07:00
Stephane Bourque
e93f899b76 Merge pull request #38 from Telecominfraproject/WIFI-10070
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
2022-07-07 21:44:36 -07:00
stephb9959
eda73038f6 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-07 21:04:13 -07:00
Stephane Bourque
953ca155a4 Merge pull request #37 from Telecominfraproject/WIFI-10070
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
2022-07-07 10:51:39 -07:00
stephb9959
898806f232 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-07 10:49:55 -07:00
stephb9959
7d97b19b85 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-07 10:47:09 -07:00
stephb9959
d6c587fde6 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-07 10:33:52 -07:00
stephb9959
58c9a7805b Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-07 10:29:15 -07:00
stephb9959
94dd4c84e9 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-07 10:26:33 -07:00
stephb9959
2636715f6f Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-07 10:24:19 -07:00
stephb9959
f9f4624add Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-07 10:23:01 -07:00
stephb9959
cf441de197 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10070
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-07 10:16:35 -07:00
Stephane Bourque
158455a528 Merge pull request #35 from Telecominfraproject/WIFI-10004v2
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10004
2022-07-05 19:32:34 -07:00
stephb9959
4d2ccec1a8 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10004
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-05 15:23:04 -07:00
Stephane Bourque
7dad5a9bdb Merge pull request #34 from Telecominfraproject/WIFI-10004
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
2022-07-04 21:40:30 -07:00
stephb9959
cd2ac84c5b Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-04 14:02:56 -07:00
Stephane Bourque
9735f709e9 Merge pull request #32 from Telecominfraproject/WIFI-10004
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10004
2022-07-01 09:21:12 -07:00
stephb9959
ae5fd31818 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10004
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10017
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10019

Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-01 08:32:16 -07:00
Johann Hoffmann
2b46ad4a66 Always re-generate config file if TEMPLATE_CONFIG is set to true (#30)
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-06-24 18:29:52 +02:00
stephb9959
43d7078cb7 Merge remote-tracking branch 'origin/main' 2022-06-23 10:57:05 -07:00
stephb9959
18f5d42f00 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-9553
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-06-23 10:56:55 -07:00
stephb9959
70622b2bb8 Merge branch 'main' of github.com:Telecominfraproject/wlan-cloud-owprov 2022-06-23 10:45:09 -07:00
stephb9959
5b24aea47c Fix: https://telecominfraproject.atlassian.net/browse/WIFI-7955
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-06-23 10:43:59 -07:00
stephb9959
e97617a0db Fix: https://telecominfraproject.atlassian.net/browse/WIFI-7955
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-06-23 10:36:05 -07:00
stephb9959
ba63a7033f Merge remote-tracking branch 'origin/main' 2022-06-20 15:48:27 -07:00
stephb9959
e9db2e1a0d Fix:https://telecominfraproject.atlassian.net/browse/WIFI-7955
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-06-20 15:48:19 -07:00
stephb9959
d85fef7725 Merge remote-tracking branch 'origin/main' 2022-06-20 12:39:53 -07:00
stephb9959
543c46bf68 Fixing: https://telecominfraproject.atlassian.net/browse/WIFI-9466
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-06-20 12:39:45 -07:00
stephb9959
73eec53fe4 Merge remote-tracking branch 'origin/main' 2022-06-18 21:59:08 -07:00
stephb9959
8ad2d67c2c Framework update.
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-06-18 21:58:59 -07:00
Johann Hoffmann
442f810688 Supress curl output in PR cleanup workflow
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-06-17 13:27:19 +02:00
Johann Hoffmann
2dca5204ea [WIFI-9534] Add condition to avoid deleting default and release branch images
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-06-17 13:24:41 +02:00
stephb9959
dc2abe2154 Merge remote-tracking branch 'origin/main' 2022-06-15 09:10:01 -07:00
stephb9959
8c14bb5b3a Framework update. 2022-06-15 09:09:52 -07:00
Johann Hoffmann
6ec4bc7115 Temporarily disable cleanup for merges into release branches
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-06-15 14:46:48 +02:00
Dmitry Dunaev
9883a40ec6 Merge pull request #24 from Telecominfraproject/fix/wifi-9174--dep-charts
[WIFI-9174] Fix: switch from deprecated bitnami charts to mirrored ones
2022-06-03 19:25:14 +03:00
Dmitry Dunaev
cc647b8108 [WIFI-9174] Fix: switch from deprecated bitnami charts to mirrored ones
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-06-03 19:24:54 +03:00
stephb9959
3b0f2a0977 Framework update. 2022-05-31 23:53:11 -07:00
stephb9959
dfefe39188 Framework update. 2022-05-31 23:25:46 -07:00
stephb9959
7d65e19d29 Adding proper parsing of port ranges for firewall. 2022-05-31 11:49:10 -07:00
stephb9959
1e16c59743 Adding proper parsing of port ranges for firewall. 2022-05-31 11:47:27 -07:00
stephb9959
4582cbd133 OpenRoaming API definition. 2022-05-31 11:12:18 -07:00
stephb9959
18e4b68c1f Merge remote-tracking branch 'origin/main' 2022-05-27 07:11:28 -07:00
stephb9959
46a11ebda2 Framework update. 2022-05-27 07:11:16 -07:00
62 changed files with 3822 additions and 1318 deletions

View File

@@ -17,4 +17,10 @@ jobs:
steps: steps:
- run: | - run: |
export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-') export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owprov/$PR_BRANCH_TAG"
if [[ ! $PR_BRANCH_TAG =~ (main|master|release-*) ]]; then
echo "PR branch is $PR_BRANCH_TAG, deleting Docker image"
curl -s -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owprov/$PR_BRANCH_TAG"
else
echo "PR branch is $PR_BRANCH_TAG, not deleting Docker image"
fi

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
project(owprov VERSION 2.6.0) project(owprov VERSION 2.7.0)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
@@ -58,6 +58,8 @@ include_directories(/usr/local/include /usr/local/opt/openssl/include src inclu
configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY) configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY)
add_definitions(-DPOCO_LOG_DEBUG="1")
add_compile_options(-Wall -Wextra) add_compile_options(-Wall -Wextra)
if(ASAN) if(ASAN)
add_compile_options(-fsanitize=address) add_compile_options(-fsanitize=address)
@@ -76,7 +78,9 @@ add_executable(owprov
src/framework/ConfigurationValidator.cpp src/framework/ConfigurationValidator.cpp
src/framework/ConfigurationValidator.h src/framework/ConfigurationValidator.h
src/framework/ow_constants.h src/framework/ow_constants.h
src/framework/MicroServiceErrorHandler.h
src/framework/WebSocketClientNotifications.h src/framework/WebSocketClientNotifications.h
src/framework/MicroServiceErrorHandler.h
src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp
src/RESTObjects/RESTAPI_ProvObjects.cpp src/RESTObjects/RESTAPI_ProvObjects.h src/RESTObjects/RESTAPI_ProvObjects.cpp src/RESTObjects/RESTAPI_ProvObjects.h
src/RESTObjects/RESTAPI_GWobjects.h src/RESTObjects/RESTAPI_GWobjects.cpp src/RESTObjects/RESTAPI_GWobjects.h src/RESTObjects/RESTAPI_GWobjects.cpp
@@ -125,7 +129,6 @@ add_executable(owprov
src/RESTAPI/RESTAPI_db_helpers.h src/RESTAPI/RESTAPI_db_helpers.h
src/JobController.cpp src/JobController.h src/JobController.cpp src/JobController.h
src/JobRegistrations.cpp src/JobRegistrations.cpp
src/storage/storage_jobs.cpp src/storage/storage_jobs.h
src/storage/storage_maps.cpp src/storage/storage_maps.h src/storage/storage_maps.cpp src/storage/storage_maps.h
src/RESTAPI/RESTAPI_map_handler.cpp src/RESTAPI/RESTAPI_map_handler.h src/RESTAPI/RESTAPI_map_handler.cpp src/RESTAPI/RESTAPI_map_handler.h
src/RESTAPI/RESTAPI_map_list_handler.cpp src/RESTAPI/RESTAPI_map_list_handler.h src/RESTAPI/RESTAPI_map_list_handler.cpp src/RESTAPI/RESTAPI_map_list_handler.h
@@ -135,7 +138,14 @@ add_executable(owprov
src/storage/storage_variables.cpp src/storage/storage_variables.h src/storage/storage_variables.cpp src/storage/storage_variables.h
src/RESTAPI/RESTAPI_variables_handler.cpp src/RESTAPI/RESTAPI_variables_handler.h src/RESTAPI/RESTAPI_variables_handler.cpp src/RESTAPI/RESTAPI_variables_handler.h
src/RESTAPI/RESTAPI_variables_list_handler.cpp src/RESTAPI/RESTAPI_variables_list_handler.h src/RESTAPI/RESTAPI_variables_list_handler.cpp src/RESTAPI/RESTAPI_variables_list_handler.h
src/FileDownloader.cpp src/FileDownloader.h src/Tasks/VenueConfigUpdater.h src/Kafka_ProvUpdater.cpp src/Kafka_ProvUpdater.h src/storage/storage_operataor.cpp src/storage/storage_operataor.h src/storage/storage_sub_devices.cpp src/storage/storage_sub_devices.h src/storage/storage_service_class.cpp src/storage/storage_service_class.h src/RESTAPI/RESTAPI_sub_devices_list_handler.cpp src/RESTAPI/RESTAPI_sub_devices_list_handler.h src/RESTAPI/RESTAPI_sub_devices_handler.cpp src/RESTAPI/RESTAPI_sub_devices_handler.h src/RESTAPI/RESTAPI_service_class_list_handler.cpp src/RESTAPI/RESTAPI_service_class_list_handler.h src/RESTAPI/RESTAPI_service_class_handler.cpp src/RESTAPI/RESTAPI_service_class_handler.h src/RESTAPI/RESTAPI_operators_list_handler.cpp src/RESTAPI/RESTAPI_operators_list_handler.h src/RESTAPI/RESTAPI_operators_handler.cpp src/RESTAPI/RESTAPI_operators_handler.h src/storage/storage_op_contacts.cpp src/storage/storage_op_contacts.h src/storage/storage_op_locations.cpp src/storage/storage_op_locations.h src/RESTAPI/RESTAPI_op_contact_list_handler.cpp src/RESTAPI/RESTAPI_op_contact_list_handler.h src/RESTAPI/RESTAPI_op_contact_handler.cpp src/RESTAPI/RESTAPI_op_contact_handler.h src/RESTAPI/RESTAPI_op_location_list_handler.cpp src/RESTAPI/RESTAPI_op_location_list_handler.h src/RESTAPI/RESTAPI_op_location_handler.cpp src/RESTAPI/RESTAPI_op_location_handler.h src/ProvWebSocketClient.cpp src/ProvWebSocketClient.h src/Tasks/VenueRebooter.h src/Tasks/VenueUpgrade.h src/sdks/SDK_fms.cpp src/sdks/SDK_fms.h) src/FileDownloader.cpp src/FileDownloader.h
src/Tasks/VenueConfigUpdater.h
src/libs/croncpp.h
src/Kafka_ProvUpdater.cpp src/Kafka_ProvUpdater.h
src/storage/storage_operataor.cpp src/storage/storage_operataor.h
src/storage/storage_sub_devices.cpp src/storage/storage_sub_devices.h
src/storage/storage_service_class.cpp src/storage/storage_service_class.h
src/RESTAPI/RESTAPI_sub_devices_list_handler.cpp src/RESTAPI/RESTAPI_sub_devices_list_handler.h src/RESTAPI/RESTAPI_sub_devices_handler.cpp src/RESTAPI/RESTAPI_sub_devices_handler.h src/RESTAPI/RESTAPI_service_class_list_handler.cpp src/RESTAPI/RESTAPI_service_class_list_handler.h src/RESTAPI/RESTAPI_service_class_handler.cpp src/RESTAPI/RESTAPI_service_class_handler.h src/RESTAPI/RESTAPI_operators_list_handler.cpp src/RESTAPI/RESTAPI_operators_list_handler.h src/RESTAPI/RESTAPI_operators_handler.cpp src/RESTAPI/RESTAPI_operators_handler.h src/storage/storage_op_contacts.cpp src/storage/storage_op_contacts.h src/storage/storage_op_locations.cpp src/storage/storage_op_locations.h src/RESTAPI/RESTAPI_op_contact_list_handler.cpp src/RESTAPI/RESTAPI_op_contact_list_handler.h src/RESTAPI/RESTAPI_op_contact_handler.cpp src/RESTAPI/RESTAPI_op_contact_handler.h src/RESTAPI/RESTAPI_op_location_list_handler.cpp src/RESTAPI/RESTAPI_op_location_list_handler.h src/RESTAPI/RESTAPI_op_location_handler.cpp src/RESTAPI/RESTAPI_op_location_handler.h src/ProvWebSocketClient.cpp src/ProvWebSocketClient.h src/Tasks/VenueRebooter.h src/Tasks/VenueUpgrade.h src/sdks/SDK_fms.cpp src/sdks/SDK_fms.h)
target_link_libraries(owprov PUBLIC target_link_libraries(owprov PUBLIC
${Poco_LIBRARIES} ${Poco_LIBRARIES}

View File

@@ -1,16 +1,23 @@
FROM alpine:3.15 AS build-base ARG DEBIAN_VERSION=11.4-slim
ARG POCO_VERSION=poco-tip-v1
ARG FMTLIB_VERSION=9.0.0
ARG CPPKAFKA_VERSION=tip-v1
ARG JSON_VALIDATOR_VERSION=2.1.0
RUN apk add --update --no-cache \ FROM debian:$DEBIAN_VERSION AS build-base
RUN apt-get update && apt-get install --no-install-recommends -y \
make cmake g++ git \ make cmake g++ git \
unixodbc-dev postgresql-dev mariadb-dev \ libpq-dev libmariadb-dev libmariadbclient-dev-compat \
librdkafka-dev boost-dev openssl-dev \ librdkafka-dev libboost-all-dev libssl-dev \
zlib-dev nlohmann-json \ zlib1g-dev nlohmann-json3-dev ca-certificates libcurl4-openssl-dev
curl-dev
FROM build-base AS poco-build FROM build-base AS poco-build
ADD https://api.github.com/repos/stephb9959/poco/git/refs/heads/master version.json ARG POCO_VERSION
RUN git clone https://github.com/stephb9959/poco /poco
ADD https://api.github.com/repos/AriliaWireless/poco/git/refs/tags/${POCO_VERSION} version.json
RUN git clone https://github.com/AriliaWireless/poco --branch ${POCO_VERSION} /poco
WORKDIR /poco WORKDIR /poco
RUN mkdir cmake-build RUN mkdir cmake-build
@@ -19,10 +26,26 @@ RUN cmake ..
RUN cmake --build . --config Release -j8 RUN cmake --build . --config Release -j8
RUN cmake --build . --target install RUN cmake --build . --target install
FROM build-base AS fmtlib-build
ARG FMTLIB_VERSION
ADD https://api.github.com/repos/fmtlib/fmt/git/refs/tags/${FMTLIB_VERSION} version.json
RUN git clone https://github.com/fmtlib/fmt --branch ${FMTLIB_VERSION} /fmtlib
WORKDIR /fmtlib
RUN mkdir cmake-build
WORKDIR cmake-build
RUN cmake ..
RUN make
RUN make install
FROM build-base AS cppkafka-build FROM build-base AS cppkafka-build
ADD https://api.github.com/repos/stephb9959/cppkafka/git/refs/heads/master version.json ARG CPPKAFKA_VERSION
RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
ADD https://api.github.com/repos/AriliaWireless/cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
RUN git clone https://github.com/AriliaWireless/cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
WORKDIR /cppkafka WORKDIR /cppkafka
RUN mkdir cmake-build RUN mkdir cmake-build
@@ -33,8 +56,10 @@ RUN cmake --build . --target install
FROM build-base AS json-schema-validator-build FROM build-base AS json-schema-validator-build
ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/heads/master version.json ARG JSON_VALIDATOR_VERSION
RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator
ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/tags/${JSON_VALIDATOR_VERSION} version.json
RUN git clone https://github.com/pboettch/json-schema-validator --branch ${JSON_VALIDATOR_VERSION} /json-schema-validator
WORKDIR /json-schema-validator WORKDIR /json-schema-validator
RUN mkdir cmake-build RUN mkdir cmake-build
@@ -43,18 +68,6 @@ RUN cmake ..
RUN make RUN make
RUN make install RUN make install
FROM build-base AS fmtlib-build
ADD https://api.github.com/repos/fmtlib/fmt/git/refs/heads/master version.json
RUN git clone https://github.com/fmtlib/fmt /fmtlib
WORKDIR /fmtlib
RUN mkdir cmake-build
WORKDIR cmake-build
RUN cmake ..
RUN make
RUN make install
FROM build-base AS owprov-build FROM build-base AS owprov-build
ADD CMakeLists.txt build /owprov/ ADD CMakeLists.txt build /owprov/
@@ -77,21 +90,21 @@ WORKDIR /owprov/cmake-build
RUN cmake .. RUN cmake ..
RUN cmake --build . --config Release -j8 RUN cmake --build . --config Release -j8
FROM alpine:3.15 FROM debian:$DEBIAN_VERSION
ENV OWPROV_USER=owprov \ ENV OWPROV_USER=owprov \
OWPROV_ROOT=/owprov-data \ OWPROV_ROOT=/owprov-data \
OWPROV_CONFIG=/owprov-data OWPROV_CONFIG=/owprov-data
RUN addgroup -S "$OWPROV_USER" && \ RUN useradd "$OWPROV_USER"
adduser -S -G "$OWPROV_USER" "$OWPROV_USER"
RUN mkdir /openwifi RUN mkdir /openwifi
RUN mkdir -p "$OWPROV_ROOT" "$OWPROV_CONFIG" && \ RUN mkdir -p "$OWPROV_ROOT" "$OWPROV_CONFIG" && \
chown "$OWPROV_USER": "$OWPROV_ROOT" "$OWPROV_CONFIG" chown "$OWPROV_USER": "$OWPROV_ROOT" "$OWPROV_CONFIG"
RUN apk add --update --no-cache librdkafka su-exec gettext ca-certificates bash jq curl \ RUN apt-get update && apt-get install --no-install-recommends -y \
mariadb-connector-c libpq unixodbc postgresql-client librdkafka++1 gosu gettext ca-certificates bash jq curl wget \
libmariadb-dev-compat libpq5 unixodbc postgresql-client
COPY readiness_check /readiness_check COPY readiness_check /readiness_check
COPY test_scripts/curl/cli /cli COPY test_scripts/curl/cli /cli
@@ -100,12 +113,14 @@ COPY owprov.properties.tmpl /
COPY docker-entrypoint.sh / COPY docker-entrypoint.sh /
COPY wait-for-postgres.sh / COPY wait-for-postgres.sh /
RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \ RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem -O /usr/local/share/ca-certificates/restapi-ca-selfsigned.crt
COPY --from=owprov-build /owprov/cmake-build/owprov /openwifi/owprov COPY --from=owprov-build /owprov/cmake-build/owprov /openwifi/owprov
COPY --from=cppkafka-build /cppkafka/cmake-build/src/lib/* /usr/local/lib COPY --from=cppkafka-build /cppkafka/cmake-build/src/lib/* /usr/local/lib
COPY --from=poco-build /poco/cmake-build/lib/* /usr/local/lib COPY --from=poco-build /poco/cmake-build/lib/* /usr/local/lib
RUN ldconfig
EXPOSE 16005 17005 16105 EXPOSE 16005 17005 16105
ENTRYPOINT ["/docker-entrypoint.sh"] ENTRYPOINT ["/docker-entrypoint.sh"]

2
build
View File

@@ -1 +1 @@
126 28

View File

@@ -1,11 +1,11 @@
#!/bin/sh #!/bin/bash
set -e set -e
if [ "$SELFSIGNED_CERTS" = 'true' ]; then if [ "$SELFSIGNED_CERTS" = 'true' ]; then
update-ca-certificates update-ca-certificates
fi fi
if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWPROV_CONFIG"/owprov.properties ]]; then if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWPROV_ROOT/certs/restapi-ca.pem"} \ RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWPROV_ROOT/certs/restapi-ca.pem"} \
RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16005"} \ RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16005"} \
RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWPROV_ROOT/certs/restapi-cert.pem"} \ RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWPROV_ROOT/certs/restapi-cert.pem"} \
@@ -24,6 +24,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWPROV_CONFIG"/owprov.properties ]];
SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17005"} \ SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17005"} \
SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16005"} \ SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16005"} \
SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \ SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
SECURITY_RESTAPI_DISABLE=${SECURITY_RESTAPI_DISABLE:-"false"} \
KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \ KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \
KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \ KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \
KAFKA_SSL_CA_LOCATION=${KAFKA_SSL_CA_LOCATION:-""} \ KAFKA_SSL_CA_LOCATION=${KAFKA_SSL_CA_LOCATION:-""} \
@@ -48,7 +49,7 @@ if [ "$1" = '/openwifi/owprov' -a "$(id -u)" = '0' ]; then
if [ "$RUN_CHOWN" = 'true' ]; then if [ "$RUN_CHOWN" = 'true' ]; then
chown -R "$OWPROV_USER": "$OWPROV_ROOT" "$OWPROV_CONFIG" chown -R "$OWPROV_USER": "$OWPROV_ROOT" "$OWPROV_CONFIG"
fi fi
exec su-exec "$OWPROV_USER" "$@" exec gosu "$OWPROV_USER" "$@"
fi fi
exec "$@" exec "$@"

2
helm/.gitignore vendored
View File

@@ -1 +1,3 @@
*.swp *.swp
Chart.lock
charts/

View File

@@ -5,14 +5,14 @@ name: owprov
version: 0.1.0 version: 0.1.0
dependencies: dependencies:
- name: postgresql - name: postgresql
repository: https://charts.bitnami.com/bitnami repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
version: 10.9.2 version: 10.9.2
condition: postgresql.enabled condition: postgresql.enabled
- name: mysql - name: mysql
repository: https://charts.bitnami.com/bitnami repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
version: 8.8.3 version: 8.8.3
condition: mysql.enabled condition: mysql.enabled
- name: mariadb - name: mariadb
repository: https://charts.bitnami.com/bitnami repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
version: 9.4.2 version: 9.4.2
condition: mariadb.enabled condition: mariadb.enabled

View File

@@ -70,8 +70,8 @@ The following table lists the configurable parameters of the chart and their def
| persistence.size | string | Defines PV size | `'10Gi'` | | persistence.size | string | Defines PV size | `'10Gi'` |
| public_env_variables | hash | Defines list of environment variables to be passed to the Provisioning | | | public_env_variables | hash | Defines list of environment variables to be passed to the Provisioning | |
| configProperties | hash | Configuration properties that should be passed to the application in `owprov.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | | | configProperties | hash | Configuration properties that should be passed to the application in `owprov.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | |
| certs | hash | Defines files (keys and certificates) that should be passed to the Provisioning (PEM format is adviced to be used) (see `volumes.owprov` on where it is mounted) | | | existingCertsSecret | string | Existing Kubernetes secret containing all required certificates and private keys for microservice operation. If set, certificates from `certs` key are ignored | `""` |
| certs | hash | Defines files (keys and certificates) that should be passed to the Gateway (PEM format is adviced to be used) (see `volumes.owprov` on where it is mounted). If `existingCertsSecret` is set, certificates passed this way will not be used. | |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,

View File

@@ -1,4 +1,5 @@
{{- $root := . -}} {{- $root := . -}}
{{- $storageType := index .Values.configProperties "storage.type" -}}
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
@@ -46,6 +47,39 @@ spec:
- -timeout - -timeout
- 600s - 600s
{{- if eq $storageType "postgresql" }}
- name: wait-postgres
image: "{{ .Values.images.owprov.repository }}:{{ .Values.images.owprov.tag }}"
imagePullPolicy: {{ .Values.images.owprov.pullPolicy }}
command:
- /wait-for-postgres.sh
- {{ index .Values.configProperties "storage.type.postgresql.host" }}
- echo
- "PostgreSQL is ready"
env:
- name: KUBERNETES_DEPLOYED
value: "{{ now }}"
{{- range $key, $value := .Values.public_env_variables }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- range $key, $value := .Values.secret_env_variables }}
- name: {{ $key }}
valueFrom:
secretKeyRef:
name: {{ include "owprov.fullname" $root }}-env
key: {{ $key }}
{{- end }}
volumeMounts:
{{- range .Values.volumes.owprov }}
- name: {{ .name }}
mountPath: {{ .mountPath }}
{{- if .subPath }}
subPath: {{ .subPath }}
{{- end }}
{{- end }}
{{- end }}
containers: containers:
- name: owprov - name: owprov
@@ -97,8 +131,10 @@ spec:
{{- toYaml . | nindent 12 }} {{- toYaml . | nindent 12 }}
{{- end }} {{- end }}
{{- with .Values.securityContext }}
securityContext: securityContext:
fsGroup: 101 {{- toYaml . | nindent 8 }}
{{- end }}
imagePullSecrets: imagePullSecrets:
{{- range $image, $imageValue := .Values.images }} {{- range $image, $imageValue := .Values.images }}

View File

@@ -9,7 +9,7 @@ fullnameOverride: ""
images: images:
owprov: owprov:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owprov repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owprov
tag: main tag: v2.7.0-RC6
pullPolicy: Always pullPolicy: Always
# regcred: # regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io # registry: tip-tip-wlan-cloud-ucentral.jfrog.io
@@ -71,7 +71,7 @@ volumes:
mountPath: /owprov-data/certs mountPath: /owprov-data/certs
volumeDefinition: | volumeDefinition: |
secret: secret:
secretName: {{ include "owprov.fullname" . }}-certs secretName: {{ if .Values.existingCertsSecret }}{{ .Values.existingCertsSecret }}{{ else }}{{ include "owprov.fullname" . }}-certs{{ end }}
# Change this if you want to use another volume type # Change this if you want to use another volume type
- name: persist - name: persist
mountPath: /owprov-data/persist mountPath: /owprov-data/persist
@@ -91,6 +91,9 @@ resources: {}
# cpu: 100m # cpu: 100m
# memory: 128Mi # memory: 128Mi
securityContext:
fsGroup: 1000
nodeSelector: {} nodeSelector: {}
tolerations: [] tolerations: []
@@ -199,6 +202,9 @@ configProperties:
storage.type.mysql.username: stephb storage.type.mysql.username: stephb
storage.type.mysql.password: snoopy99 storage.type.mysql.password: snoopy99
# NOTE: List of required certificates may be found in "certs" key. Alternative way to pass required certificates is to create external secret with all required certificates and set secret name in "existingCertsSecret" key. Details may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart#tldr
existingCertsSecret: ""
certs: certs:
# restapi-ca.pem: "" # restapi-ca.pem: ""
# restapi-cert.pem: "" # restapi-cert.pem: ""

View File

@@ -0,0 +1,268 @@
openapi: 3.0.1
info:
title: OpenWiFi Open roaming Ameriband Provisioning Model
description: Registration of an OpenRoaming profile with Ameriband for TIP OpenWifi.
version: 1.0.0
license:
name: BSD3
url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
servers:
- url: 'https://tip.regiatration.ameriband.com:8001/api/v1'
security:
- bearerAuth: []
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
responses:
NotFound:
description: The specified resource was not found.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: string
Unauthorized:
description: The requested does not have sufficient rights to perform the operation.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
enum:
- 0 # Success
- 8 # INVALID_TOKEN
- 9 # EXPIRED_TOKEN
ErrorDetails:
type: string
ErrorDescription:
type: string
Success:
description: The requested operation was performed.
content:
application/json:
schema:
properties:
Operation:
type: string
Details:
type: string
Code:
type: integer
BadRequest:
description: The requested operation failed.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: integer
schemas:
RegistrationRequest:
type: object
properties:
orgRequestId:
type: string
format: uuid
minLength: 36
maxLength: 36
example:
Client will generate a UUID that must be returned in the response.
orgAcceptedTermsAndConditions:
type: boolean
default: false
orgLegalName:
type: string
minLength: 1
orgWebSite:
type: string
format: url
minLength: 1
orgContact:
type: string
minLength: 1
example:
John Smith
orgEmail:
type: string
format: email
minLength: 1
orgPhone:
type: string
example:
(607)555-1234 or +1(223)555-1222
orgLocation:
type: string
example:
Boston, NH - LA, CA
orgCertificate:
type: string
minLength: 1
example:
This must be the entire PEM file content of the certificate, encoded using base64
RegistrationResponse:
type: object
properties:
orgRequestId:
type: string
format: uuid
minLength: 36
maxLength: 36
example:
This should be the same orgRequestId passed during registration.
orgNASID:
type: string
minLength: 10
description:
This is the NASID generated by Ameriband. It will be used by the operator as NASID when contacting Ameriband.
ameribandCertificate:
type: string
minLength: 1
example:
This must be the entire PEM file content of the certificate, encoded using base64
RegistrationInformationRequest:
type: object
properties:
link:
description: This should be the link where a potential registrant can read the terms and conditions of registering with Ameriband.
type: string
format: url
minLength: 1
example:
https://ameriband.com/romain-registration.html
paths:
/termsAndConditions:
get:
summary: The registrant must be given a chance to view the terms and conditions of the relationship they are entering into
operationId: getTermsAndConditions
responses:
200:
description: Sucessfully retrieved Terms and Conditions
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationInformationRequest'
404:
$ref: '#/components/responses/Unauthorized'
/registration:
get:
tags:
- Registration
operationId: getRegistrationInformation
summary: This should return the information from a registration based on the NASID
parameters:
- in: query
name: orgNASID
schema:
type: string
required: true
example:
This is the orgNASID returned during registration.
responses:
200:
$ref: '#/components/schemas/RegistrationResponse'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
post:
summary: Called when the registrant ahs read the T&Cs and iw willing to submit their information to enter in a partnership
tags:
- Registration
operationId: createRegistration
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationRequest'
responses:
200:
description: Succesfully registered
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationResponse'
400:
description: Registration failed due to missing or incomplete information
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
put:
summary: Called when the registrant needs to update its information with Ameriband. The does not generate a new NASID.
tags:
- Registration
operationId: updateRegistration
parameters:
- in: query
name: orgNASID
schema:
type: string
required: true
example:
This is the orgNASID returned during registration.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationRequest'
responses:
200:
description: Succesfully found the information based on the orgNASID
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationResponse'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
delete:
tags:
- Registration
summary: When a registrant wants to terminate a relationship with Ameriband. Ameriband should also delete all information from the registrant
operationId: deleteRegistration
parameters:
- in: query
name: orgNASID
schema:
type: string
required: true
example:
This is the orgNASID returned during registration.
responses:
204:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'

View File

@@ -27,71 +27,13 @@ components:
responses: responses:
NotFound: NotFound:
description: The specified resource was not found. $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/NotFound'
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: string
Unauthorized: Unauthorized:
description: The requested does not have sufficient rights to perform the operation. $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Unauthorized'
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
enum:
- 0 # Success
- 1 # PASSWORD_CHANGE_REQUIRED,
- 2 # INVALID_CREDENTIALS,
- 3 # PASSWORD_ALREADY_USED,
- 4 # USERNAME_PENDING_VERIFICATION,
- 5 # PASSWORD_INVALID,
- 6 # INTERNAL_ERROR,
- 7 # ACCESS_DENIED,
- 8 # INVALID_TOKEN
- 9 # EXPIRED_TOKEN
- 10 # RATE_LIMIT_EXCEEDED
- 11 # BAD_MFA_TRANSACTION
- 12 # MFA_FAILURE
- 13 # SECURITY_SERVICE_UNREACHABLE
ErrorDetails:
type: string
ErrorDescription:
type: string
Success: Success:
description: The requested operation was performed. $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Success'
content:
application/json:
schema:
properties:
Operation:
type: string
Details:
type: string
Code:
type: integer
BadRequest: BadRequest:
description: The requested operation failed. $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/BadRequest'
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: integer
schemas: schemas:
@@ -2016,11 +1958,6 @@ paths:
schema: schema:
type: boolean type: boolean
required: false required: false
- in: query
name: deviceType
schema:
type: string
required: false
- in: query - in: query
description: Pagination start (starts at 1. If not specified, 1 is assumed) description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: offset name: offset
@@ -2092,6 +2029,21 @@ paths:
type: string type: string
format: uuid format: uuid
required: false required: false
- in: query
description: return RRM settings for a specific device
name: rrmSettings
schema:
type: boolean
default: false
required: false
- in: query
description: return the resolved configuration for a specific device
name: resolveConfig
schema:
type: boolean
default: false
required: false
responses: responses:
200: 200:
description: Return a list of elements description: Return a list of elements
@@ -2313,12 +2265,6 @@ paths:
type: string type: string
example: serial1,serial2,serial3 example: serial1,serial2,serial3
required: false required: false
- in: query
description: only serial numbers of full device details
name: serialOnly
schema:
type: boolean
required: false
- in: query - in: query
description: return the number of devices description: return the number of devices
name: countOnly name: countOnly

174
openapi/rrm_provider.yaml Normal file
View File

@@ -0,0 +1,174 @@
openapi: 3.0.1
info:
title: OpenWiFi RRM Provider Model
description: Definitions and APIs to manages an OpenWiFi RRM Providers.
version: 1.0.0
license:
name: BSD3
url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
servers:
- url: 'https://localhost:16022/api/v1'
security:
- bearerAuth: []
- ApiKeyAuth: []
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-KEY
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
responses:
NotFound:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/NotFound'
Unauthorized:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Unauthorized'
Success:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Success'
BadRequest:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/BadRequest'
schemas:
Provider:
type: object
properties:
vendor:
description: The name of the vendor for display.
type: string
minLength: 1
maxLength: 128
vendorShortname:
description: A shortname for the vendor. Only letters and numbers are allowed. This is the name used internally.
type: string
minLength: 4
maxLength: 16
version:
description: An identifier that will help users identify the version of the RRM module they are using.
type: string
about:
description: A link to the Vendor page for this RRM Module
type: string
Algorithm:
type: object
properties:
name:
description: A display for this algorithm.
type: string
minLength: 1
maxLength: 128
description:
description: A description of the algorithm.
type: string
shortName:
description: This is the name used internally.
type: string
minLength: 4
maxLength: 16
parameterFormat:
description: this is a Regex used to validate the input. If this is empty, no validation will be performed.
type: string
parameterSamples:
description: These samples will be displayed in the UI to the user trying to configure the options
type: array
items:
type: string
helper:
description: A link to a web page or PDF document explaining the algorithm and its parameters
type: string
Algorithms:
description: The list of all algorithms supported by the vendor
type: array
items:
$ref: '#/components/schemas/Algorithm'
paths:
/provider:
get:
tags:
- RRM
operationId: getProvider
summary: Retrieve information about the provider for this RRM Module
responses:
200:
$ref: '#/components/schemas/Provider'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/algorithms:
get:
tags:
- RRM
operationId: getAlgorithms
summary: Retrieve a lists of algorithms supported in the module.
responses:
200:
$ref: '#/components/schemas/Algorithms'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/runRRM:
put:
tags:
- RRM
operationId: runRRMNow
summary: Run a specific or default RRM algorithm. The UI user or CLI user will have the ability to run an algorithm on demand.
parameters:
- in: query
description:
name: venue
schema:
type: string
format: uuid
required: true
- in: query
description: Perform RRM without updating anything. This may be used by an admin to see what RRM would do.
name: mock
schema:
type: boolean
default: false
required: false
- in: query
description: Specify the RRM algorithm to use. If omitted, select the default algorithm.
schema:
type: string
required: false
- in: query
description: Specify the parameters to use with the RRM algorithm to use. If omitted, select the default parameters.
schema:
type: string
required: false
responses:
200:
description: Return the list of actions that were or would be performed.
content:
application/json:
schema:
type: array
items:
type: string
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'

View File

@@ -34,6 +34,7 @@ openwifi.system.uri.private = https://localhost:17005
openwifi.system.uri.public = https://ucentral.dpaas.arilia.com:16005 openwifi.system.uri.public = https://ucentral.dpaas.arilia.com:16005
openwifi.system.commandchannel = /tmp/app.owprov openwifi.system.commandchannel = /tmp/app.owprov
openwifi.system.uri.ui = owprov-ui.arilia.com openwifi.system.uri.ui = owprov-ui.arilia.com
openwifi.security.restapi.disable = false
firmware.updater.upgrade = false firmware.updater.upgrade = false
firmware.updater.releaseonly = false firmware.updater.releaseonly = false
@@ -115,4 +116,4 @@ storage.type.mysql.connectiontimeout = 60
######################################################################## ########################################################################
logging.type = file logging.type = file
logging.path = $OWPROV_ROOT/logs logging.path = $OWPROV_ROOT/logs
logging.level = debug logging.level = debug

View File

@@ -39,6 +39,7 @@ openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE}
openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC} openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC}
openwifi.system.commandchannel = /tmp/app.ucentralfms openwifi.system.commandchannel = /tmp/app.ucentralfms
openwifi.system.uri.ui = ${SYSTEM_URI_UI} openwifi.system.uri.ui = ${SYSTEM_URI_UI}
openwifi.security.restapi.disable = ${SECURITY_RESTAPI_DISABLE}
############################# #############################
# Generic information for all micro services # Generic information for all micro services

View File

@@ -153,60 +153,62 @@ namespace OpenWifi {
} }
} }
std::set<std::string> Sections; try {
for(const auto &i:Config_) { std::set<std::string> Sections;
Poco::JSON::Parser P; for (const auto &i: Config_) {
auto O = P.parse(i.element.configuration).extract<Poco::JSON::Object::Ptr>(); Poco::JSON::Parser P;
auto Names = O->getNames(); auto O = P.parse(i.element.configuration).extract<Poco::JSON::Object::Ptr>();
for(const auto &SectionName:Names) { auto Names = O->getNames();
auto InsertInfo = Sections.insert(SectionName); for (const auto &SectionName: Names) {
if (InsertInfo.second) { auto InsertInfo = Sections.insert(SectionName);
if (O->isArray(SectionName)) { if (InsertInfo.second) {
auto OriginalArray = O->getArray(SectionName); if (O->isArray(SectionName)) {
if (Explain_) { auto OriginalArray = O->getArray(SectionName);
Poco::JSON::Object ExObj; if (Explain_) {
ExObj.set("from-uuid", i.info.id); Poco::JSON::Object ExObj;
ExObj.set("from-name", i.info.name); ExObj.set("from-uuid", i.info.id);
ExObj.set("action", "added"); ExObj.set("from-name", i.info.name);
ExObj.set("element", OriginalArray); ExObj.set("action", "added");
Explanation_.add(ExObj); ExObj.set("element", OriginalArray);
Explanation_.add(ExObj);
}
auto ExpandedArray = Poco::makeShared<Poco::JSON::Array>();
ReplaceVariablesInArray(OriginalArray, ExpandedArray);
Configuration->set(SectionName, ExpandedArray);
} else if (O->isObject(SectionName)) {
auto OriginalSection = O->get(SectionName).extract<Poco::JSON::Object::Ptr>();
if (Explain_) {
Poco::JSON::Object ExObj;
ExObj.set("from-uuid", i.info.id);
ExObj.set("from-name", i.info.name);
ExObj.set("action", "added");
ExObj.set("element", OriginalSection);
Explanation_.add(ExObj);
}
auto ExpandedSection = Poco::makeShared<Poco::JSON::Object>();
ReplaceVariablesInObject(OriginalSection, ExpandedSection);
Configuration->set(SectionName, ExpandedSection);
} else {
std::cout << " --- unknown element type --- " << O->get(SectionName).toString()
<< std::endl;
} }
auto ExpandedArray = Poco::makeShared<Poco::JSON::Array>();
ReplaceVariablesInArray(OriginalArray, ExpandedArray);
Configuration->set(SectionName, ExpandedArray);
} else if (O->isObject(SectionName)) {
auto OriginalSection = O->get(SectionName).extract<Poco::JSON::Object::Ptr>();
if (Explain_) {
Poco::JSON::Object ExObj;
ExObj.set("from-uuid", i.info.id);
ExObj.set("from-name", i.info.name);
ExObj.set("action", "added");
ExObj.set("element", OriginalSection);
Explanation_.add(ExObj);
}
auto ExpandedSection = Poco::makeShared<Poco::JSON::Object>();
ReplaceVariablesInObject(OriginalSection, ExpandedSection);
Configuration->set(SectionName, ExpandedSection);
} else { } else {
std::cout << " --- unknown element type --- " << O->get(SectionName).toString() << std::endl; if (Explain_) {
} Poco::JSON::Object ExObj;
} else { ExObj.set("from-uuid", i.info.id);
if (Explain_) { ExObj.set("from-name", i.info.name);
Poco::JSON::Object ExObj; ExObj.set("action", "ignored");
ExObj.set("from-uuid", i.info.id); ExObj.set("reason", "weight insufficient");
ExObj.set("from-name", i.info.name); ExObj.set("element", O->get(SectionName));
ExObj.set("action", "ignored"); Explanation_.add(ExObj);
ExObj.set("reason", "weight insufficient"); }
ExObj.set("element", O->get(SectionName));
Explanation_.add(ExObj);
} }
} }
} }
} } catch (...) {
if(Config_.empty())
return false;
return true; }
return !Config_.empty();
} }
static bool DeviceTypeMatch(const std::string &DeviceType, const Types::StringVec & Types) { static bool DeviceTypeMatch(const std::string &DeviceType, const Types::StringVec & Types) {

View File

@@ -26,6 +26,7 @@ namespace OpenWifi {
void AutoDiscovery::run() { void AutoDiscovery::run() {
Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification()); Poco::AutoPtr<Poco::Notification> Note(Queue_.waitDequeueNotification());
Utils::SetThreadName("auto-discovery");
while(Note && Running_) { while(Note && Running_) {
auto Msg = dynamic_cast<DiscoveryMessage *>(Note.get()); auto Msg = dynamic_cast<DiscoveryMessage *>(Note.get());
if(Msg!= nullptr) { if(Msg!= nullptr) {

View File

@@ -33,7 +33,7 @@ namespace OpenWifi {
void Stop() override; void Stop() override;
void ConnectionReceived( const std::string & Key, const std::string & Payload) { void ConnectionReceived( const std::string & Key, const std::string & Payload) {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
Logger().information(Poco::format("Device(%s): Connection/Ping message.", Key)); poco_debug(Logger(),Poco::format("Device(%s): Connection/Ping message.", Key));
Queue_.enqueueNotification( new DiscoveryMessage(Key,Payload)); Queue_.enqueueNotification( new DiscoveryMessage(Key,Payload));
} }
void run() override; void run() override;

View File

@@ -73,17 +73,25 @@ namespace OpenWifi {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
try { int ExitCode;
auto App = OpenWifi::Daemon::instance(); try {
auto ExitCode = App->run(argc, argv); Poco::Net::SSLManager::instance().initializeServer(nullptr, nullptr, nullptr);
delete App; auto App = OpenWifi::Daemon::instance();
ExitCode = App->run(argc, argv);
Poco::Net::SSLManager::instance().shutdown();
} catch (Poco::Exception &exc) {
ExitCode = Poco::Util::Application::EXIT_SOFTWARE;
std::cout << exc.displayText() << std::endl;
} catch (std::exception &exc) {
ExitCode = Poco::Util::Application::EXIT_TEMPFAIL;
std::cout << exc.what() << std::endl;
} catch (...) {
ExitCode = Poco::Util::Application::EXIT_TEMPFAIL;
std::cout << "Exception on closure" << std::endl;
}
return ExitCode; std::cout << "Exitcode: " << ExitCode << std::endl;
return ExitCode;
} catch (Poco::Exception &exc) {
std::cerr << exc.displayText() << std::endl;
return Poco::Util::Application::EXIT_SOFTWARE;
}
} }
// end of namespace // end of namespace

View File

@@ -26,6 +26,8 @@ namespace OpenWifi {
{"https://ucentral.io/ucentral.schema.pretty.json", "ucentral.schema.pretty.json" } {"https://ucentral.io/ucentral.schema.pretty.json", "ucentral.schema.pretty.json" }
}; };
Utils::SetThreadName("file-dmnldr");
for(const auto &[url,filename]:Files) { for(const auto &[url,filename]:Files) {
try { try {
std::string FileContent; std::string FileContent;

View File

@@ -27,11 +27,32 @@ namespace OpenWifi {
void JobController::run() { void JobController::run() {
Running_ = true ; Running_ = true ;
Utils::SetThreadName("job-controller");
while(Running_) { while(Running_) {
Poco::Thread::trySleep(2000); Poco::Thread::trySleep(2000);
std::lock_guard G(Mutex_);
for(auto &current_job:jobs_) {
if(current_job!=nullptr) {
if(current_job->Started()==0 && Pool_.used()<Pool_.available()) {
current_job->Logger().information(fmt::format("Starting {}: {}",current_job->JobId(),current_job->Name()));
current_job->Start();
Pool_.start(*current_job);
}
}
}
for(auto it = jobs_.begin(); it!=jobs_.end();) {\
auto current_job = *it;
if(current_job!=nullptr && current_job->Completed()!=0) {
current_job->Logger().information(fmt::format("Completed {}: {}",current_job->JobId(),current_job->Name()));
it = jobs_.erase(it);
delete current_job;
} else {
++it;
}
}
} }
} }
} }

View File

@@ -7,99 +7,45 @@
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <functional> #include <functional>
#include <list>
#include "framework/MicroService.h" #include "framework/MicroService.h"
namespace OpenWifi { namespace OpenWifi {
class Job { class Job : public Poco::Runnable {
public: public:
struct Parameter { Job(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) :
std::string name; jobId_(JobID),
std::string value; name_(name),
inline void to_json(Poco::JSON::Object &Obj) const { parameters_(parameters),
RESTAPI_utils::field_to_json(Obj,"name",name); when_(when),
RESTAPI_utils::field_to_json(Obj,"value",value); userinfo_(UI),
} Logger_(L)
{};
inline bool from_json(const Poco::JSON::Object::Ptr &Obj) { virtual void run() = 0;
try { [[nodiscard]] std::string Name() const { return name_; }
RESTAPI_utils::field_from_json(Obj,"name",name); const SecurityObjects::UserInfo & UserInfo() const { return userinfo_; }
RESTAPI_utils::field_from_json(Obj,"value",value); Poco::Logger & Logger() { return Logger_; }
return true; const std::string & JobId() const { return jobId_; }
} catch (...) { const std::string & Parameter(int x) const { return parameters_[x];}
uint64_t When() const { return when_; }
void Start() { started_ = OpenWifi::Now(); }
uint64_t Started() const { return started_; }
uint64_t Completed() const { return completed_;}
void Complete() { completed_ = OpenWifi::Now(); }
} private:
return false; std::string jobId_;
} std::string name_;
}; std::vector<std::string> parameters_;
uint64_t when_=0;
struct Status { SecurityObjects::UserInfo userinfo_;
Types::UUID_t UUID; Poco::Logger & Logger_;
uint64_t Start = 0 ; uint64_t started_=0;
uint64_t Progress = 0 ; uint64_t completed_=0;
uint64_t Completed = 0 ;
std::string CurrentDisplay;
};
struct Result {
int Error=0;
std::string Reason;
};
typedef std::vector<Parameter> Parameters;
typedef std::vector<Parameters> ParametersVec;
typedef std::function<bool(const Parameters &Parameters, Result &Result, bool &Retry)> WorkerFunction;
typedef std::vector<Status> Statuses;
Job(std::string Title,
std::string Description,
std::string RegisteredName,
ParametersVec Parameters,
[[maybe_unused]] bool Parallel=true) :
Title_(std::move(Title)),
Description_(std::move(Description)),
RegisteredName_(std::move(RegisteredName)),
Parameters_(std::move(Parameters))
{
UUID_ = MicroService::instance().CreateUUID();
}
[[nodiscard]] inline const Types::UUID_t & ID() const { return UUID_; }
private:
Types::UUID_t UUID_;
std::string Title_;
std::string Description_;
std::string RegisteredName_;
ParametersVec Parameters_;
}; };
class JobRegistry {
public:
static auto instance() {
static auto instance_ = new JobRegistry;
return instance_;
}
inline void RegisterJobType( const std::string & JobType, Job::WorkerFunction Function) {
JobTypes_[JobType] = std::move(Function);
}
inline bool Execute(const std::string &JobType, const Job::Parameters & Params, Job::Result &Result, bool & Retry) {
auto Hint = JobTypes_.find(JobType);
if(Hint != end(JobTypes_)) {
Hint->second(Params, Result, Retry);
return true;
}
return false;
}
private:
std::map<std::string,Job::WorkerFunction> JobTypes_;
};
inline auto JobRegistry() { return JobRegistry::instance(); }
class JobController : public SubSystemServer, Poco::Runnable { class JobController : public SubSystemServer, Poco::Runnable {
public: public:
static auto instance() { static auto instance() {
@@ -112,11 +58,16 @@ namespace OpenWifi {
void run() override; void run() override;
inline void wakeup() { Thr_.wakeUp(); } inline void wakeup() { Thr_.wakeUp(); }
bool JobList(Job::Statuses & Statuses); void AddJob( Job* newJob ) {
std::lock_guard G(Mutex_);
jobs_.push_back(newJob);
}
private: private:
Poco::Thread Thr_; Poco::Thread Thr_;
std::atomic_bool Running_=false; std::atomic_bool Running_=false;
std::list<Job *> jobs_;
Poco::ThreadPool Pool_;
JobController() noexcept: JobController() noexcept:
SubSystemServer("JobController", "JOB-SVR", "job") SubSystemServer("JobController", "JOB-SVR", "job")

View File

@@ -23,6 +23,7 @@ namespace OpenWifi {
bool &Done, std::string &Answer) { bool &Done, std::string &Answer) {
Done = false; Done = false;
auto Prefix = O->get("serial_prefix").toString(); auto Prefix = O->get("serial_prefix").toString();
Poco::toLowerInPlace(Prefix);
Logger().information(Poco::format("serial_number_search: %s", Prefix)); Logger().information(Poco::format("serial_number_search: %s", Prefix));
if (!Prefix.empty() && Prefix.length() < 13) { if (!Prefix.empty() && Prefix.length() < 13) {
std::vector<uint64_t> Numbers; std::vector<uint64_t> Numbers;
@@ -83,6 +84,7 @@ namespace OpenWifi {
Done = false; Done = false;
auto operatorId = O->get("operatorId").toString(); auto operatorId = O->get("operatorId").toString();
auto Prefix = O->get("serial_prefix").toString(); auto Prefix = O->get("serial_prefix").toString();
Poco::toLowerInPlace(Prefix);
std::string Query; std::string Query;
if(Prefix[0]=='*') { if(Prefix[0]=='*') {

View File

@@ -9,6 +9,9 @@
#include "framework/MicroService.h" #include "framework/MicroService.h"
#include "framework/ConfigurationValidator.h" #include "framework/ConfigurationValidator.h"
#include "sdks/SDK_sec.h" #include "sdks/SDK_sec.h"
#include "Poco/StringTokenizer.h"
#include "libs/croncpp.h"
namespace OpenWifi { namespace OpenWifi {
@@ -405,7 +408,9 @@ namespace OpenWifi {
} }
inline bool ValidateConfigBlock(const ProvObjects::DeviceConfiguration &Config, RESTAPI::Errors::msg & Error) { inline bool ValidateConfigBlock(const ProvObjects::DeviceConfiguration &Config, RESTAPI::Errors::msg & Error) {
static const std::vector<std::string> SectionNames{ "globals", "interfaces", "metrics", "radios", "services", "unit" }; static const std::vector<std::string> SectionNames{ "globals", "interfaces", "metrics", "radios", "services",
"unit", "definitions", "ethernet", "switch", "config-raw",
"third-party" };
for(const auto &i:Config.configuration) { for(const auto &i:Config.configuration) {
Poco::JSON::Parser P; Poco::JSON::Parser P;
@@ -521,12 +526,39 @@ namespace OpenWifi {
} }
} }
} }
return Result; return Result;
} }
inline bool ValidSchedule(const std::string &v) {
try
{
auto cron = cron::make_cron(v);
return true;
}
catch (cron::bad_cronexpr const & ex)
{
}
return false;
}
inline bool ValidRRM(const std::string &v) {
if((v=="no") || (v=="inherit")) return true;
try {
Poco::JSON::Parser P;
auto O = P.parse(v).extract<Poco::JSON::Object::Ptr>();
ProvObjects::RRMDetails D;
if(D.from_json(O)) {
return ValidSchedule(D.schedule);
}
} catch (...) {
}
return false;
}
inline bool ValidDeviceRules(const ProvObjects::DeviceRules & DR) { inline bool ValidDeviceRules(const ProvObjects::DeviceRules & DR) {
return (DR.rrm=="yes" || DR.rrm=="no" || DR.rrm=="inherit") && return (ValidRRM(DR.rrm)) &&
(DR.firmwareUpgrade=="yes" || DR.firmwareUpgrade=="no" || DR.firmwareUpgrade=="inherit") && (DR.firmwareUpgrade=="yes" || DR.firmwareUpgrade=="no" || DR.firmwareUpgrade=="inherit") &&
(DR.rcOnly=="yes" || DR.rcOnly=="no" || DR.rcOnly=="inherit"); (DR.rcOnly=="yes" || DR.rcOnly=="no" || DR.rcOnly=="inherit");
} }

View File

@@ -35,36 +35,53 @@ namespace OpenWifi{
void RESTAPI_inventory_handler::DoGet() { void RESTAPI_inventory_handler::DoGet() {
ProvObjects::InventoryTag Existing; ProvObjects::InventoryTag Existing;
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER,""); std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
Logger().debug(Poco::format("%s: Retrieving inventory information.",SerialNumber)); Logger().debug(Poco::format("%s: Retrieving inventory information.", SerialNumber));
if(SerialNumber.empty() || !DB_.GetRecord(RESTAPI::Protocol::SERIALNUMBER,SerialNumber,Existing)) { if (SerialNumber.empty() || !DB_.GetRecord(RESTAPI::Protocol::SERIALNUMBER, SerialNumber, Existing)) {
return NotFound(); return NotFound();
} }
Logger().debug(Poco::format("%s,%s: Retrieving inventory information.", Existing.serialNumber, Existing.info.id )); Logger().debug(
Poco::format("%s,%s: Retrieving inventory information.", Existing.serialNumber, Existing.info.id));
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
std::string Arg; std::string Arg;
if(HasParameter("config",Arg) && Arg=="true") { if (HasParameter("config", Arg) && Arg == "true") {
bool Explain = (HasParameter("explain",Arg) && Arg == "true"); bool Explain = (HasParameter("explain", Arg) && Arg == "true");
APConfig Device(SerialNumber,Existing.deviceType,Logger(), Explain); APConfig Device(SerialNumber, Existing.deviceType, Logger(), Explain);
auto Configuration = Poco::makeShared<Poco::JSON::Object>(); auto Configuration = Poco::makeShared<Poco::JSON::Object>();
if(Device.Get(Configuration)) { if (Device.Get(Configuration)) {
Answer.set("config", Configuration); Answer.set("config", Configuration);
if(Explain) if (Explain)
Answer.set("explanation", Device.Explanation()); Answer.set("explanation", Device.Explanation());
} else { } else {
Answer.set("config","none"); Answer.set("config", "none");
} }
return ReturnObject(Answer); return ReturnObject(Answer);
} else if(HasParameter("firmwareOptions", Arg) && Arg=="true") { } else if (GetBoolParameter("firmwareOptions", false)) {
ProvObjects::DeviceRules Rules; ProvObjects::DeviceRules Rules;
StorageService()->InventoryDB().EvaluateDeviceSerialNumberRules(SerialNumber,Rules); StorageService()->InventoryDB().EvaluateDeviceSerialNumberRules(SerialNumber, Rules);
Answer.set("firmwareUpgrade",Rules.firmwareUpgrade); Answer.set("firmwareUpgrade", Rules.firmwareUpgrade);
Answer.set("firmwareRCOnly", Rules.rcOnly == "yes" ); Answer.set("firmwareRCOnly", Rules.rcOnly == "yes");
return ReturnObject(Answer); return ReturnObject(Answer);
} else if(HasParameter("applyConfiguration",Arg) && Arg=="true") { } else if(GetBoolParameter("rrmSettings",false)) {
ProvObjects::DeviceRules Rules;
StorageService()->InventoryDB().EvaluateDeviceSerialNumberRules(SerialNumber, Rules);
if(Rules.rrm=="no" || Rules.rrm=="inherit") {
Answer.set("rrm", Rules.rrm);
} else {
ProvObjects::RRMDetails D;
Poco::JSON::Parser P;
try {
auto Obj = P.parse(Rules.rrm).extract<Poco::JSON::Object::Ptr>();
Answer.set("rrm", Obj);
} catch (...) {
Answer.set("rrm", "invalid");
}
}
return ReturnObject(Answer);
} else if(GetBoolParameter("applyConfiguration", false)) {
Logger().debug(Poco::format("%s: Retrieving configuration.",Existing.serialNumber)); Logger().debug(Poco::format("%s: Retrieving configuration.",Existing.serialNumber));
auto Device = std::make_shared<APConfig>(SerialNumber, Existing.deviceType, Logger(), false); auto Device = std::make_shared<APConfig>(SerialNumber, Existing.deviceType, Logger(), false);
auto Configuration = Poco::makeShared<Poco::JSON::Object>(); auto Configuration = Poco::makeShared<Poco::JSON::Object>();
@@ -91,6 +108,19 @@ namespace OpenWifi{
} }
Results.to_json(Answer); Results.to_json(Answer);
return ReturnObject(Answer); return ReturnObject(Answer);
} else if(GetBoolParameter("resolveConfig", false)) {
Logger().debug(Poco::format("%s: Retrieving configuration.",Existing.serialNumber));
auto Device = std::make_shared<APConfig>(SerialNumber, Existing.deviceType, Logger(), false);
auto Configuration = Poco::makeShared<Poco::JSON::Object>();
Poco::JSON::Object ErrorsObj, WarningsObj;
ProvObjects::InventoryConfigApplyResult Results;
Logger().debug(Poco::format("%s: Computing configuration.",Existing.serialNumber));
if (Device->Get(Configuration)) {
Answer.set("configuration", Configuration);
} else {
Answer.set("error", 1);
}
return ReturnObject(Answer);
} else if(QB_.AdditionalInfo) { } else if(QB_.AdditionalInfo) {
AddExtendedInfo(Existing,Answer); AddExtendedInfo(Existing,Answer);
} }
@@ -136,6 +166,7 @@ namespace OpenWifi{
void RESTAPI_inventory_handler::DoPost() { void RESTAPI_inventory_handler::DoPost() {
std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER,""); std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER,"");
Poco::toLowerInPlace(SerialNumber);
if(SerialNumber.empty()) { if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber); return BadRequest(RESTAPI::Errors::MissingSerialNumber);
} }
@@ -154,6 +185,11 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
} }
NormalizeMac(NewObject.serialNumber);
if(SerialNumber!=NewObject.serialNumber) {
return BadRequest(RESTAPI::Errors::SerialNumberMismatch);
}
if((RawObject->has("deviceRules") && !ValidDeviceRules(NewObject.deviceRules,*this))) { if((RawObject->has("deviceRules") && !ValidDeviceRules(NewObject.deviceRules,*this))) {
return; return;
} }

View File

@@ -101,7 +101,7 @@ namespace OpenWifi {
{ "email", UserName }, { "email", UserName },
{ "signupUUID" , SignupUUID }, { "signupUUID" , SignupUUID },
{ "owner" , SignupOperator.info.id }, { "owner" , SignupOperator.info.id },
{ "operatorName", SignupOperator.registrationId }
}, Body, 30000); }, Body, 30000);
Poco::JSON::Object::Ptr Answer; Poco::JSON::Object::Ptr Answer;

View File

@@ -27,6 +27,7 @@ namespace OpenWifi{
for (const auto &i: V.children) { for (const auto &i: V.children) {
ProvObjects::Venue V2; ProvObjects::Venue V2;
if (StorageService()->VenueDB().GetRecord("id", i, V2)) { if (StorageService()->VenueDB().GetRecord("id", i, V2)) {
std::copy(V2.devices.begin(),V2.devices.end(),std::back_inserter(R));
auto LowerDevs = GetDevices(V2, GetChildren); auto LowerDevs = GetDevices(V2, GetChildren);
std::copy(LowerDevs.begin(), LowerDevs.end(), std::back_inserter(R)); std::copy(LowerDevs.begin(), LowerDevs.end(), std::back_inserter(R));
} }
@@ -227,10 +228,10 @@ namespace OpenWifi{
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
SNL.serialNumbers = Existing.devices; SNL.serialNumbers = Existing.devices;
auto JobId = MicroService::instance().CreateUUID();
auto Task = new VenueConfigUpdater(UUID,UserInfo_.userinfo,0,Logger()); Types::StringVec Parameters{UUID};;
auto JobId = Task->Start(); auto NewJob = new VenueConfigUpdater(JobId,"VenueConfigurationUpdater", Parameters, 0, UserInfo_.userinfo, Logger());
JobController()->AddJob(dynamic_cast<Job*>(NewJob));
SNL.to_json(Answer); SNL.to_json(Answer);
Answer.set("jobId",JobId); Answer.set("jobId",JobId);
return ReturnObject(Answer); return ReturnObject(Answer);
@@ -241,10 +242,10 @@ namespace OpenWifi{
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
SNL.serialNumbers = Existing.devices; SNL.serialNumbers = Existing.devices;
auto JobId = MicroService::instance().CreateUUID();
auto Task = new VenueUpgrade(UUID,UserInfo_.userinfo,0,Logger()); Types::StringVec Parameters{UUID};;
auto JobId = Task->Start(); auto NewJob = new VenueUpgrade(JobId,"VenueFirmwareUpgrade", Parameters, 0, UserInfo_.userinfo, Logger());
JobController()->AddJob(dynamic_cast<Job*>(NewJob));
SNL.to_json(Answer); SNL.to_json(Answer);
Answer.set("jobId",JobId); Answer.set("jobId",JobId);
return ReturnObject(Answer); return ReturnObject(Answer);
@@ -255,10 +256,10 @@ namespace OpenWifi{
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
SNL.serialNumbers = Existing.devices; SNL.serialNumbers = Existing.devices;
auto JobId = MicroService::instance().CreateUUID();
auto Task = new VenueRebooter(UUID,UserInfo_.userinfo,0,Logger()); Types::StringVec Parameters{UUID};;
auto JobId = Task->Start(); auto NewJob = new VenueRebooter(JobId,"VenueRebooter", Parameters, 0, UserInfo_.userinfo, Logger());
JobController()->AddJob(dynamic_cast<Job*>(NewJob));
SNL.to_json(Answer); SNL.to_json(Answer);
Answer.set("jobId",JobId); Answer.set("jobId",JobId);
return ReturnObject(Answer); return ReturnObject(Answer);

View File

@@ -538,8 +538,8 @@ namespace OpenWifi::AnalyticsObjects {
void WifiClientHistory::to_json(Poco::JSON::Object &Obj) const { void WifiClientHistory::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"timestamp",timestamp); field_to_json(Obj,"timestamp",timestamp);
field_to_json(Obj,"stationId",stationId); field_to_json(Obj,"station_id",station_id);
field_to_json(Obj,"bssId",bssId); field_to_json(Obj,"bssid",bssid);
field_to_json(Obj,"ssid",ssid); field_to_json(Obj,"ssid",ssid);
field_to_json(Obj,"rssi",rssi); field_to_json(Obj,"rssi",rssi);
field_to_json(Obj,"rx_bitrate",rx_bitrate); field_to_json(Obj,"rx_bitrate",rx_bitrate);
@@ -573,13 +573,14 @@ namespace OpenWifi::AnalyticsObjects {
field_to_json(Obj,"connected",connected); field_to_json(Obj,"connected",connected);
field_to_json(Obj,"inactive",inactive); field_to_json(Obj,"inactive",inactive);
field_to_json(Obj,"tx_retries",tx_retries); field_to_json(Obj,"tx_retries",tx_retries);
field_to_json(Obj,"venue_id",venue_id);
} }
bool WifiClientHistory::from_json(const Poco::JSON::Object::Ptr &Obj) { bool WifiClientHistory::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj,"timestamp",timestamp); field_from_json(Obj,"timestamp",timestamp);
field_from_json(Obj,"stationId",stationId); field_from_json(Obj,"station_id",station_id);
field_from_json(Obj,"bssId",bssId); field_from_json(Obj,"bssid",bssid);
field_from_json(Obj,"ssid",ssid); field_from_json(Obj,"ssid",ssid);
field_from_json(Obj,"rssi",rssi); field_from_json(Obj,"rssi",rssi);
field_from_json(Obj,"rx_bitrate",rx_bitrate); field_from_json(Obj,"rx_bitrate",rx_bitrate);
@@ -613,6 +614,7 @@ namespace OpenWifi::AnalyticsObjects {
field_from_json(Obj,"connected",connected); field_from_json(Obj,"connected",connected);
field_from_json(Obj,"inactive",inactive); field_from_json(Obj,"inactive",inactive);
field_from_json(Obj,"tx_retries",tx_retries); field_from_json(Obj,"tx_retries",tx_retries);
field_from_json(Obj,"venue_id",venue_id);
return true; return true;
} catch(...) { } catch(...) {

View File

@@ -376,8 +376,8 @@ namespace OpenWifi {
struct WifiClientHistory { struct WifiClientHistory {
uint64_t timestamp=OpenWifi::Now(); uint64_t timestamp=OpenWifi::Now();
std::string stationId; std::string station_id;
std::string bssId; std::string bssid;
std::string ssid; std::string ssid;
int64_t rssi=0; int64_t rssi=0;
uint32_t rx_bitrate=0; uint32_t rx_bitrate=0;
@@ -411,6 +411,7 @@ namespace OpenWifi {
uint64_t connected=0; uint64_t connected=0;
uint64_t inactive=0; uint64_t inactive=0;
uint64_t tx_retries=0; uint64_t tx_retries=0;
std::string venue_id;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj); bool from_json(const Poco::JSON::Object::Ptr &Obj);

View File

@@ -3,176 +3,206 @@
// //
#include "RESTAPI_CertObjects.h" #include "RESTAPI_CertObjects.h"
#include "framework/MicroService.h"
using OpenWifi::RESTAPI_utils::field_to_json; using OpenWifi::RESTAPI_utils::field_to_json;
using OpenWifi::RESTAPI_utils::field_from_json; using OpenWifi::RESTAPI_utils::field_from_json;
namespace OpenWifi { namespace OpenWifi::CertObjects {
namespace CertObjects { void CertificateEntry::to_json(Poco::JSON::Object &Obj) const {
void CertificateEntry::to_json(Poco::JSON::Object &Obj) const { field_to_json(Obj,"id", id);
field_to_json(Obj,"id", id); field_to_json(Obj,"entity", entity);
field_to_json(Obj,"entity", entity); field_to_json(Obj,"creator", creator);
field_to_json(Obj,"creator", creator); field_to_json(Obj,"type", type);
field_to_json(Obj,"type", type); field_to_json(Obj,"status", status);
field_to_json(Obj,"status", status); field_to_json(Obj,"certificate", certificate);
field_to_json(Obj,"certificate", certificate); field_to_json(Obj,"key", key);
field_to_json(Obj,"key", key); field_to_json(Obj,"devid", devid);
field_to_json(Obj,"devid", devid); field_to_json(Obj,"cas", cas);
field_to_json(Obj,"cas", cas); field_to_json(Obj,"manufacturer", manufacturer);
field_to_json(Obj,"manufacturer", manufacturer); field_to_json(Obj,"model", model);
field_to_json(Obj,"model", model); field_to_json(Obj,"redirector", redirector);
field_to_json(Obj,"redirector", redirector); field_to_json(Obj,"commonName", commonName);
field_to_json(Obj,"commonName", commonName); field_to_json(Obj,"certificateId", certificateId);
field_to_json(Obj,"certificateId", certificateId); field_to_json(Obj,"batch", batch);
field_to_json(Obj,"batch", batch); field_to_json(Obj,"created", created);
field_to_json(Obj,"created", created); field_to_json(Obj,"modified", modified);
field_to_json(Obj,"modified", modified); field_to_json(Obj,"revoked", revoked);
field_to_json(Obj,"revoked", revoked); field_to_json(Obj,"revokeCount", revokeCount);
field_to_json(Obj,"revokeCount", revokeCount); field_to_json(Obj,"synched", synched);
} }
bool CertificateEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { bool CertificateEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj,"id", id); field_from_json(Obj,"id", id);
field_from_json(Obj,"entity", entity); field_from_json(Obj,"entity", entity);
field_from_json(Obj,"creator", creator); field_from_json(Obj,"creator", creator);
field_from_json(Obj,"type", type); field_from_json(Obj,"type", type);
field_from_json(Obj,"status", status); field_from_json(Obj,"status", status);
field_from_json(Obj,"certificate", certificate); field_from_json(Obj,"certificate", certificate);
field_from_json(Obj,"key", key); field_from_json(Obj,"key", key);
field_from_json(Obj,"devid", devid); field_from_json(Obj,"devid", devid);
field_from_json(Obj,"cas", cas); field_from_json(Obj,"cas", cas);
field_from_json(Obj,"manufacturer", manufacturer); field_from_json(Obj,"manufacturer", manufacturer);
field_from_json(Obj,"model", model); field_from_json(Obj,"model", model);
field_from_json(Obj,"redirector", redirector); field_from_json(Obj,"redirector", redirector);
field_from_json(Obj,"commonName", commonName); field_from_json(Obj,"commonName", commonName);
field_from_json(Obj,"certificateId", certificateId); field_from_json(Obj,"certificateId", certificateId);
field_from_json(Obj,"batch", batch); field_from_json(Obj,"batch", batch);
field_from_json(Obj,"created", created); field_from_json(Obj,"created", created);
field_from_json(Obj,"modified", modified); field_from_json(Obj,"modified", modified);
field_from_json(Obj,"revoked", revoked); field_from_json(Obj,"revoked", revoked);
field_from_json(Obj,"revokeCount", revokeCount); field_from_json(Obj,"revokeCount", revokeCount);
return true; field_from_json(Obj,"synched", synched);
} catch (...) { return true;
} } catch (...) {
return false;
} }
return false;
}
void EntityEntry::to_json(Poco::JSON::Object &Obj) const { void EntityEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id); field_to_json(Obj,"id", id);
field_to_json(Obj,"creator", creator); field_to_json(Obj,"creator", creator);
field_to_json(Obj,"name", name); field_to_json(Obj,"name", name);
field_to_json(Obj,"description", description); field_to_json(Obj,"description", description);
field_to_json(Obj,"defaultRedirector", defaultRedirector); field_to_json(Obj,"defaultRedirector", defaultRedirector);
field_to_json(Obj,"apiKey", apiKey); field_to_json(Obj,"apiKey", apiKey);
field_to_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile); field_to_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
field_to_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile); field_to_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
field_to_json(Obj,"organization", organization); field_to_json(Obj,"organization", organization);
field_to_json(Obj,"created", created); field_to_json(Obj,"created", created);
field_to_json(Obj,"modified", modified); field_to_json(Obj,"modified", modified);
field_to_json(Obj,"suspended", suspended); field_to_json(Obj,"suspended", suspended);
field_to_json(Obj,"deleted", deleted); field_to_json(Obj,"deleted", deleted);
field_to_json(Obj,"notes", notes); field_to_json(Obj,"notes", notes);
} }
bool EntityEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { bool EntityEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj,"id", id); field_from_json(Obj,"id", id);
field_from_json(Obj,"creator", creator); field_from_json(Obj,"creator", creator);
field_from_json(Obj,"name", name); field_from_json(Obj,"name", name);
field_from_json(Obj,"description", description); field_from_json(Obj,"description", description);
field_from_json(Obj,"defaultRedirector", defaultRedirector); field_from_json(Obj,"defaultRedirector", defaultRedirector);
field_from_json(Obj,"apiKey", apiKey); field_from_json(Obj,"apiKey", apiKey);
field_from_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile); field_from_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
field_from_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile); field_from_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
field_from_json(Obj,"organization", organization); field_from_json(Obj,"organization", organization);
field_from_json(Obj,"created", created); field_from_json(Obj,"created", created);
field_from_json(Obj,"modified", modified); field_from_json(Obj,"modified", modified);
field_from_json(Obj,"suspended", suspended); field_from_json(Obj,"suspended", suspended);
field_from_json(Obj,"deleted", deleted); field_from_json(Obj,"deleted", deleted);
field_from_json(Obj,"notes", notes); field_from_json(Obj,"notes", notes);
return true; return true;
} catch (...) { } catch (...) {
}
return false;
} }
return false;
}
void BatchEntry::to_json(Poco::JSON::Object &Obj) const { void BatchEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id); field_to_json(Obj,"id", id);
field_to_json(Obj,"entity", entity); field_to_json(Obj,"entity", entity);
field_to_json(Obj,"creator", creator); field_to_json(Obj,"creator", creator);
field_to_json(Obj,"name", name); field_to_json(Obj,"name", name);
field_to_json(Obj,"description", description); field_to_json(Obj,"description", description);
field_to_json(Obj,"manufacturer", manufacturer); field_to_json(Obj,"manufacturer", manufacturer);
field_to_json(Obj,"model", model); field_to_json(Obj,"model", model);
field_to_json(Obj,"redirector", redirector); field_to_json(Obj,"redirector", redirector);
field_to_json(Obj,"commonNames", commonNames); field_to_json(Obj,"commonNames", commonNames);
field_to_json(Obj,"jobHistory", jobHistory); field_to_json(Obj,"jobHistory", jobHistory);
field_to_json(Obj,"notes", notes); field_to_json(Obj,"notes", notes);
field_to_json(Obj,"submitted", submitted); field_to_json(Obj,"submitted", submitted);
field_to_json(Obj,"started", started); field_to_json(Obj,"started", started);
field_to_json(Obj,"completed", completed); field_to_json(Obj,"completed", completed);
field_to_json(Obj,"modified", modified); field_to_json(Obj,"modified", modified);
} }
bool BatchEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { bool BatchEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj,"id", id); field_from_json(Obj,"id", id);
field_from_json(Obj,"entity", entity); field_from_json(Obj,"entity", entity);
field_from_json(Obj,"creator", creator); field_from_json(Obj,"creator", creator);
field_from_json(Obj,"name", name); field_from_json(Obj,"name", name);
field_from_json(Obj,"description", description); field_from_json(Obj,"description", description);
field_from_json(Obj,"manufacturer", manufacturer); field_from_json(Obj,"manufacturer", manufacturer);
field_from_json(Obj,"model", model); field_from_json(Obj,"model", model);
field_from_json(Obj,"redirector", redirector); field_from_json(Obj,"redirector", redirector);
field_from_json(Obj,"commonNames", commonNames); field_from_json(Obj,"commonNames", commonNames);
field_from_json(Obj,"jobHistory", jobHistory); field_from_json(Obj,"jobHistory", jobHistory);
field_from_json(Obj,"notes", notes); field_from_json(Obj,"notes", notes);
field_from_json(Obj,"submitted", submitted); field_from_json(Obj,"submitted", submitted);
field_from_json(Obj,"started", started); field_from_json(Obj,"started", started);
field_from_json(Obj,"completed", completed); field_from_json(Obj,"completed", completed);
field_from_json(Obj,"modified", modified); field_from_json(Obj,"modified", modified);
return true; return true;
} catch (...) { } catch (...) {
}
return false;
} }
return false;
}
void JobEntry::to_json(Poco::JSON::Object &Obj) const { void JobEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id); field_to_json(Obj,"id", id);
field_to_json(Obj,"entity", entity); field_to_json(Obj,"entity", entity);
field_to_json(Obj,"creator", creator); field_to_json(Obj,"creator", creator);
field_to_json(Obj,"batch", batch); field_to_json(Obj,"batch", batch);
field_to_json(Obj,"commonNames", commonNames); field_to_json(Obj,"commonNames", commonNames);
field_to_json(Obj,"completedNames", completedNames); field_to_json(Obj,"completedNames", completedNames);
field_to_json(Obj,"errorNames", errorNames); field_to_json(Obj,"errorNames", errorNames);
field_to_json(Obj,"status", status); field_to_json(Obj,"status", status);
field_to_json(Obj,"command", command); field_to_json(Obj,"command", command);
field_to_json(Obj,"parameters", parameters); field_to_json(Obj,"parameters", parameters);
field_to_json(Obj,"submitted", submitted); field_to_json(Obj,"submitted", submitted);
field_to_json(Obj,"started", started); field_to_json(Obj,"started", started);
field_to_json(Obj,"completed", completed); field_to_json(Obj,"completed", completed);
} }
bool JobEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { bool JobEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj,"id", id); field_from_json(Obj,"id", id);
field_from_json(Obj,"entity", entity); field_from_json(Obj,"entity", entity);
field_from_json(Obj,"creator", creator); field_from_json(Obj,"creator", creator);
field_from_json(Obj,"batch", batch); field_from_json(Obj,"batch", batch);
field_from_json(Obj,"commonNames", commonNames); field_from_json(Obj,"commonNames", commonNames);
field_from_json(Obj,"completedNames", completedNames); field_from_json(Obj,"completedNames", completedNames);
field_from_json(Obj,"errorNames", errorNames); field_from_json(Obj,"errorNames", errorNames);
field_from_json(Obj,"status", status); field_from_json(Obj,"status", status);
field_from_json(Obj,"command", command); field_from_json(Obj,"command", command);
field_from_json(Obj,"parameters", parameters); field_from_json(Obj,"parameters", parameters);
field_from_json(Obj,"submitted", submitted); field_from_json(Obj,"submitted", submitted);
field_from_json(Obj,"started", started); field_from_json(Obj,"started", started);
field_from_json(Obj,"completed", completed); field_from_json(Obj,"completed", completed);
return true; return true;
} catch (...) { } catch (...) {
}
return false;
} }
return false;
}
void DashBoardYearlyStats::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "year", year);
field_to_json(Obj, "activeCerts", activeCerts);
field_to_json(Obj, "revokedCerts", revokedCerts);
}
void Dashboard::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"snapshot", snapshot);
field_to_json(Obj,"numberOfIssuedCerts", numberOfIssuedCerts);
field_to_json(Obj,"numberOfRevokedCerts", numberOfRevokedCerts);
field_to_json(Obj,"activeCertsPerOrganization", activeCertsPerOrganization);
field_to_json(Obj,"revokedCertsPerOrganization", revokedCertsPerOrganization);
field_to_json(Obj,"numberOfRedirectors", numberOfRedirectors);
field_to_json(Obj,"deviceTypes", deviceTypes);
field_to_json(Obj,"monthlyNumberOfCerts", monthlyNumberOfCerts);
field_to_json(Obj,"monthlyNumberOfCertsPerOrgPerYear", monthlyNumberOfCertsPerOrgPerYear);
}
void Dashboard::reset() {
snapshot=0;
numberOfRevokedCerts = numberOfIssuedCerts = 0;
activeCertsPerOrganization.clear();
revokedCertsPerOrganization.clear();
numberOfRedirectors.clear();
deviceTypes.clear();
monthlyNumberOfCerts.clear();
monthlyNumberOfCertsPerOrgPerYear.clear();
} }
} }

View File

@@ -5,97 +5,118 @@
#pragma once #pragma once
#include <string> #include <string>
#include "framework/MicroService.h"
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h" #include "RESTObjects/RESTAPI_SecurityObjects.h"
namespace OpenWifi { namespace OpenWifi::CertObjects {
namespace CertObjects { struct CertificateEntry {
OpenWifi::Types::UUID_t id;
OpenWifi::Types::UUID_t entity;
OpenWifi::Types::UUID_t creator;
std::string type;
std::string status;
std::string certificate;
std::string key;
std::string devid;
std::string cas;
std::string manufacturer;
std::string model;
std::string redirector;
std::string commonName;
std::string certificateId;
OpenWifi::Types::UUID_t batch;
uint64_t created = 0;
uint64_t modified = 0;
uint64_t revoked = 0;
uint64_t revokeCount = 0;
uint64_t synched = 0;
struct CertificateEntry { void to_json(Poco::JSON::Object &Obj) const;
OpenWifi::Types::UUID_t id; bool from_json(const Poco::JSON::Object::Ptr &Obj);
OpenWifi::Types::UUID_t entity; };
OpenWifi::Types::UUID_t creator;
std::string type;
std::string status;
std::string certificate;
std::string key;
std::string devid;
std::string cas;
std::string manufacturer;
std::string model;
std::string redirector;
std::string commonName;
std::string certificateId;
OpenWifi::Types::UUID_t batch;
uint64_t created = 0;
uint64_t modified = 0;
uint64_t revoked = 0;
uint64_t revokeCount = 0;
void to_json(Poco::JSON::Object &Obj) const; struct EntityEntry {
bool from_json(const Poco::JSON::Object::Ptr &Obj); OpenWifi::Types::UUID_t id;
}; OpenWifi::Types::UUID_t creator;
std::string name;
std::string description;
std::string defaultRedirector;
std::string apiKey;
std::string serverEnrollmentProfile;
std::string clientEnrollmentProfile;
std::string organization;
SecurityObjects::NoteInfoVec notes;
bool suspended=false;
bool deleted=false;
uint64_t created = 0 ;
uint64_t modified = 0 ;
struct EntityEntry { void to_json(Poco::JSON::Object &Obj) const;
OpenWifi::Types::UUID_t id; bool from_json(const Poco::JSON::Object::Ptr &Obj);
OpenWifi::Types::UUID_t creator; };
std::string name;
std::string description;
std::string defaultRedirector;
std::string apiKey;
std::string serverEnrollmentProfile;
std::string clientEnrollmentProfile;
std::string organization;
SecurityObjects::NoteInfoVec notes;
bool suspended=false;
bool deleted=false;
uint64_t created = 0 ;
uint64_t modified = 0 ;
void to_json(Poco::JSON::Object &Obj) const; struct BatchEntry {
bool from_json(const Poco::JSON::Object::Ptr &Obj); OpenWifi::Types::UUID_t id;
}; OpenWifi::Types::UUID_t entity;
OpenWifi::Types::UUID_t creator;
std::string name;
std::string description;
std::string manufacturer;
std::string model;
std::string redirector;
std::vector<std::string> commonNames;
std::vector<std::string> jobHistory;
SecurityObjects::NoteInfoVec notes;
uint64_t submitted = 0 ;
uint64_t started = 0 ;
uint64_t completed = 0 ;
uint64_t modified = 0 ;
struct BatchEntry { void to_json(Poco::JSON::Object &Obj) const;
OpenWifi::Types::UUID_t id; bool from_json(const Poco::JSON::Object::Ptr &Obj);
OpenWifi::Types::UUID_t entity; };
OpenWifi::Types::UUID_t creator;
std::string name;
std::string description;
std::string manufacturer;
std::string model;
std::string redirector;
std::vector<std::string> commonNames;
std::vector<std::string> jobHistory;
SecurityObjects::NoteInfoVec notes;
uint64_t submitted = 0 ;
uint64_t started = 0 ;
uint64_t completed = 0 ;
uint64_t modified = 0 ;
void to_json(Poco::JSON::Object &Obj) const; struct JobEntry {
bool from_json(const Poco::JSON::Object::Ptr &Obj); OpenWifi::Types::UUID_t id;
}; OpenWifi::Types::UUID_t entity;
OpenWifi::Types::UUID_t creator;
OpenWifi::Types::UUID_t batch;
std::string command;
OpenWifi::Types::StringVec commonNames;
OpenWifi::Types::StringVec completedNames;
OpenWifi::Types::StringVec errorNames;
Types::StringPairVec parameters;
std::string status;
uint64_t submitted=0;
uint64_t started=0;
uint64_t completed=0;
struct JobEntry { void to_json(Poco::JSON::Object &Obj) const;
OpenWifi::Types::UUID_t id; bool from_json(const Poco::JSON::Object::Ptr &Obj);
OpenWifi::Types::UUID_t entity; };
OpenWifi::Types::UUID_t creator;
OpenWifi::Types::UUID_t batch; struct DashBoardYearlyStats {
std::string command; uint64_t year=0;
OpenWifi::Types::StringVec commonNames; OpenWifi::Types::Counted3DMapSII activeCerts;
OpenWifi::Types::StringVec completedNames; OpenWifi::Types::Counted3DMapSII revokedCerts;
OpenWifi::Types::StringVec errorNames;
Types::StringPairVec parameters; void to_json(Poco::JSON::Object &Obj) const;
std::string status; };
uint64_t submitted=0;
uint64_t started=0; struct Dashboard {
uint64_t completed=0; uint64_t snapshot=0;
uint64_t numberOfIssuedCerts=0;
uint64_t numberOfRevokedCerts=0;
OpenWifi::Types::CountedMap activeCertsPerOrganization;
OpenWifi::Types::CountedMap revokedCertsPerOrganization;
OpenWifi::Types::CountedMap numberOfRedirectors;
OpenWifi::Types::CountedMap deviceTypes;
OpenWifi::Types::CountedMap monthlyNumberOfCerts;
std::vector<DashBoardYearlyStats> monthlyNumberOfCertsPerOrgPerYear;
void to_json(Poco::JSON::Object &Obj) const;
void reset();
};
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
}
} }

View File

@@ -233,7 +233,7 @@ namespace OpenWifi::FMSObjects {
UnknownFirmwares_.clear(); UnknownFirmwares_.clear();
totalSecondsOld_.clear(); totalSecondsOld_.clear();
numberOfDevices = 0 ; numberOfDevices = 0 ;
snapshot = std::time(nullptr); snapshot = OpenWifi::Now();
} }
bool DeviceReport::from_json([[maybe_unused]] const Poco::JSON::Object::Ptr &Obj) { bool DeviceReport::from_json([[maybe_unused]] const Poco::JSON::Object::Ptr &Obj) {
@@ -273,4 +273,37 @@ namespace OpenWifi::FMSObjects {
} }
return false; return false;
} }
void DeviceCurrentInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "serialNumber",serialNumber);
field_to_json(Obj, "revision", revision);
field_to_json(Obj, "upgraded", upgraded);
}
bool DeviceCurrentInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serialNumber",serialNumber);
field_from_json(Obj, "revision", revision);
field_from_json(Obj, "upgraded", upgraded);
return true;
} catch(...) {
}
return false;
}
void DeviceCurrentInfoList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "devices",devices);
}
bool DeviceCurrentInfoList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "devices",devices);
return true;
} catch(...) {
}
return false;
}
} }

View File

@@ -4,9 +4,7 @@
#include <string> #include <string>
#ifndef UCENTRALFMS_RESTAPI_FMSOBJECTS_H #pragma once
#define UCENTRALFMS_RESTAPI_FMSOBJECTS_H
#include "RESTAPI_SecurityObjects.h" #include "RESTAPI_SecurityObjects.h"
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
@@ -29,7 +27,7 @@ namespace OpenWifi::FMSObjects {
std::string location; std::string location;
std::string uploader; std::string uploader;
std::string digest; std::string digest;
bool latest=0; bool latest=false;
SecurityObjects::NoteInfoVec notes; SecurityObjects::NoteInfoVec notes;
uint64_t created=0; uint64_t created=0;
@@ -141,7 +139,21 @@ namespace OpenWifi::FMSObjects {
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj); bool from_json(const Poco::JSON::Object::Ptr &Obj);
}; };
struct DeviceCurrentInfo {
std::string serialNumber;
std::string revision;
uint64_t upgraded=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct DeviceCurrentInfoList {
std::vector<DeviceCurrentInfo> devices;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
} }
#endif //UCENTRALFMS_RESTAPI_FMSOBJECTS_H

View File

@@ -203,6 +203,10 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"kafkaClients", kafkaClients); field_to_json(Obj,"kafkaClients", kafkaClients);
field_to_json(Obj,"kafkaPackets", kafkaPackets); field_to_json(Obj,"kafkaPackets", kafkaPackets);
field_to_json(Obj,"locale", locale); field_to_json(Obj,"locale", locale);
field_to_json(Obj,"started", started);
field_to_json(Obj,"sessionId", sessionId);
field_to_json(Obj,"connectionCompletionTime", connectionCompletionTime);
field_to_json(Obj,"totalConnectionTime", OpenWifi::Now() - started);
switch(VerifiedCertificate) { switch(VerifiedCertificate) {
case NO_CERTIFICATE: case NO_CERTIFICATE:
@@ -218,6 +222,21 @@ namespace OpenWifi::GWObjects {
} }
} }
void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"averageConnectionTime", averageConnectionTime);
field_to_json(Obj,"connectedDevices", connectedDevices );
}
bool DeviceConnectionStatistics::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"averageConnectionTime", averageConnectionTime);
field_from_json(Obj,"connectedDevices", connectedDevices );
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void RttySessionDetails::to_json(Poco::JSON::Object &Obj) const { void RttySessionDetails::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"serialNumber", SerialNumber); field_to_json(Obj,"serialNumber", SerialNumber);
field_to_json(Obj,"server", Server); field_to_json(Obj,"server", Server);
@@ -293,7 +312,6 @@ namespace OpenWifi::GWObjects {
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
} }
return false; return false;
} }
void RadiusProxyPoolList::to_json(Poco::JSON::Object &Obj) const { void RadiusProxyPoolList::to_json(Poco::JSON::Object &Obj) const {
@@ -314,6 +332,8 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"description",description); field_to_json(Obj,"description",description);
field_to_json(Obj,"authConfig",authConfig); field_to_json(Obj,"authConfig",authConfig);
field_to_json(Obj,"acctConfig",acctConfig); field_to_json(Obj,"acctConfig",acctConfig);
field_to_json(Obj,"coaConfig",coaConfig);
field_to_json(Obj,"useByDefault",useByDefault);
} }
bool RadiusProxyPool::from_json(const Poco::JSON::Object::Ptr &Obj) { bool RadiusProxyPool::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -322,6 +342,8 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj,"description",description); field_from_json(Obj,"description",description);
field_from_json(Obj,"authConfig",authConfig); field_from_json(Obj,"authConfig",authConfig);
field_from_json(Obj,"acctConfig",acctConfig); field_from_json(Obj,"acctConfig",acctConfig);
field_from_json(Obj,"coaConfig",coaConfig);
field_from_json(Obj,"useByDefault",useByDefault);
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
} }
@@ -329,7 +351,7 @@ namespace OpenWifi::GWObjects {
} }
void RadiusProxyServerConfig::to_json(Poco::JSON::Object &Obj) const { void RadiusProxyServerConfig::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"policy",strategy); field_to_json(Obj,"strategy",strategy);
field_to_json(Obj,"monitor",monitor); field_to_json(Obj,"monitor",monitor);
field_to_json(Obj,"monitorMethod",monitorMethod); field_to_json(Obj,"monitorMethod",monitorMethod);
field_to_json(Obj,"methodParameters",methodParameters); field_to_json(Obj,"methodParameters",methodParameters);
@@ -338,7 +360,7 @@ namespace OpenWifi::GWObjects {
bool RadiusProxyServerConfig::from_json(const Poco::JSON::Object::Ptr &Obj) { bool RadiusProxyServerConfig::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj,"policy",strategy); field_from_json(Obj,"strategy",strategy);
field_from_json(Obj,"monitor",monitor); field_from_json(Obj,"monitor",monitor);
field_from_json(Obj,"monitorMethod",monitorMethod); field_from_json(Obj,"monitorMethod",monitorMethod);
field_from_json(Obj,"methodParameters",methodParameters); field_from_json(Obj,"methodParameters",methodParameters);
@@ -354,6 +376,16 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"ip",ip); field_to_json(Obj,"ip",ip);
field_to_json(Obj,"port",port); field_to_json(Obj,"port",port);
field_to_json(Obj,"weight",weight); field_to_json(Obj,"weight",weight);
field_to_json(Obj,"secret",secret);
field_to_json(Obj,"certificate",certificate);
field_to_json(Obj,"radsec",radsec);
field_to_json(Obj,"radsecPort",radsecPort);
field_to_json(Obj,"radsecSecret",radsecSecret);
field_to_json(Obj,"radsecCacerts",radsecCacerts);
field_to_json(Obj,"radsecCert",radsecCert);
field_to_json(Obj,"radsecKey",radsecKey);
field_to_json(Obj,"radsecRealms",radsecRealms);
field_to_json(Obj,"ignore",ignore);
} }
bool RadiusProxyServerEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { bool RadiusProxyServerEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -362,6 +394,16 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj,"ip",ip); field_from_json(Obj,"ip",ip);
field_from_json(Obj,"port",port); field_from_json(Obj,"port",port);
field_from_json(Obj,"weight",weight); field_from_json(Obj,"weight",weight);
field_from_json(Obj,"secret",secret);
field_from_json(Obj,"certificate",certificate);
field_from_json(Obj,"radsec",radsec);
field_from_json(Obj,"radsecSecret",radsecSecret);
field_from_json(Obj,"radsecPort",radsecPort);
field_from_json(Obj,"radsecCacerts",radsecCacerts);
field_from_json(Obj,"radsecCert",radsecCert);
field_from_json(Obj,"radsecKey",radsecKey);
field_from_json(Obj,"radsecRealms",radsecRealms);
field_from_json(Obj,"ignore",ignore);
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
} }

View File

@@ -38,6 +38,10 @@ namespace OpenWifi::GWObjects {
uint64_t kafkaPackets=0; uint64_t kafkaPackets=0;
uint64_t websocketPackets=0; uint64_t websocketPackets=0;
std::string locale; std::string locale;
uint64_t started=0;
uint64_t sessionId=0;
double connectionCompletionTime=0.0;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
}; };
@@ -71,6 +75,13 @@ namespace OpenWifi::GWObjects {
void Print() const; void Print() const;
}; };
struct DeviceConnectionStatistics {
std::uint64_t connectedDevices = 0;
std::uint64_t averageConnectionTime = 0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct Statistics { struct Statistics {
std::string SerialNumber; std::string SerialNumber;
uint64_t UUID = 0 ; uint64_t UUID = 0 ;
@@ -216,6 +227,16 @@ namespace OpenWifi::GWObjects {
std::string ip; std::string ip;
uint16_t port=0; uint16_t port=0;
uint64_t weight=0; uint64_t weight=0;
std::string secret;
std::string certificate;
bool radsec=false;
uint16_t radsecPort=2083;
std::string radsecSecret;
std::string radsecKey;
std::string radsecCert;
std::vector<std::string> radsecCacerts;
std::vector<std::string> radsecRealms;
bool ignore=false;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj); bool from_json(const Poco::JSON::Object::Ptr &Obj);
@@ -237,6 +258,8 @@ namespace OpenWifi::GWObjects {
std::string description; std::string description;
RadiusProxyServerConfig authConfig; RadiusProxyServerConfig authConfig;
RadiusProxyServerConfig acctConfig; RadiusProxyServerConfig acctConfig;
RadiusProxyServerConfig coaConfig;
bool useByDefault=false;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj); bool from_json(const Poco::JSON::Object::Ptr &Obj);

View File

@@ -0,0 +1,110 @@
//
// Created by stephane bourque on 2021-08-31.
//
#include "framework/MicroService.h"
using OpenWifi::RESTAPI_utils::field_to_json;
using OpenWifi::RESTAPI_utils::field_from_json;
using OpenWifi::RESTAPI_utils::EmbedDocument;
#include "RESTAPI_OWLSobjects.h"
// SIM -> 0x53/0x073, 0x49/0x69, 0x4d/0x6d
namespace OpenWifi::OWLSObjects {
void SimulationDetails::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"name", name);
field_to_json(Obj,"gateway", gateway);
field_to_json(Obj,"certificate", certificate);
field_to_json(Obj,"key", key);
field_to_json(Obj,"macPrefix", macPrefix);
field_to_json(Obj,"deviceType", deviceType);
field_to_json(Obj,"devices", devices);
field_to_json(Obj,"healthCheckInterval", healthCheckInterval);
field_to_json(Obj,"stateInterval", stateInterval);
field_to_json(Obj,"minAssociations", minAssociations);
field_to_json(Obj,"maxAssociations", maxAssociations);
field_to_json(Obj,"minClients", minClients);
field_to_json(Obj,"maxClients", maxClients);
field_to_json(Obj,"simulationLength", simulationLength);
field_to_json(Obj,"threads", threads);
field_to_json(Obj,"clientInterval", clientInterval);
field_to_json(Obj,"keepAlive", keepAlive);
field_to_json(Obj,"reconnectInterval", reconnectInterval);
field_to_json(Obj,"concurrentDevices", concurrentDevices);
}
bool SimulationDetails::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"name", name);
field_from_json(Obj,"gateway", gateway);
field_from_json(Obj,"certificate", certificate);
field_from_json(Obj,"key", key);
field_from_json(Obj,"macPrefix", macPrefix);
field_from_json(Obj,"deviceType", deviceType);
field_from_json(Obj,"devices", devices);
field_from_json(Obj,"healthCheckInterval", healthCheckInterval);
field_from_json(Obj,"stateInterval", stateInterval);
field_from_json(Obj,"minAssociations", minAssociations);
field_from_json(Obj,"maxAssociations", maxAssociations);
field_from_json(Obj,"minClients", minClients);
field_from_json(Obj,"maxClients", maxClients);
field_from_json(Obj,"simulationLength", simulationLength);
field_from_json(Obj,"threads", threads);
field_from_json(Obj,"clientInterval", clientInterval);
field_from_json(Obj,"keepAlive", keepAlive);
field_from_json(Obj,"reconnectInterval", reconnectInterval);
field_from_json(Obj,"concurrentDevices", concurrentDevices);
return true;
} catch(...) {
}
return false;
}
void SimulationDetailsList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"list", list);
}
bool SimulationDetailsList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"list", list);
return true;
} catch(...) {
}
return false;
}
void SimulationStatus::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"simulationId", simulationId);
field_to_json(Obj,"state", state);
field_to_json(Obj,"tx", tx);
field_to_json(Obj,"rx", rx);
field_to_json(Obj,"msgsTx", msgsTx);
field_to_json(Obj,"msgsRx", msgsRx);
field_to_json(Obj,"liveDevices", liveDevices);
field_to_json(Obj,"timeToFullDevices", timeToFullDevices);
field_to_json(Obj,"startTime", startTime);
field_to_json(Obj,"endTime", endTime);
field_to_json(Obj,"errorDevices", errorDevices);
field_to_json(Obj,"owner", owner);
}
void Dashboard::to_json([[maybe_unused]] Poco::JSON::Object &Obj) const {
}
bool Dashboard::from_json([[maybe_unused]] const Poco::JSON::Object::Ptr &Obj) {
return true;
}
void Dashboard::reset() {
}
}

View File

@@ -0,0 +1,77 @@
//
// Created by stephane bourque on 2021-08-31.
//
#ifndef UCENTRALSIM_RESTAPI_OWLSOBJECTS_H
#define UCENTRALSIM_RESTAPI_OWLSOBJECTS_H
#include <vector>
#include "Poco/JSON/Object.h"
namespace OpenWifi::OWLSObjects {
struct SimulationDetails {
std::string id;
std::string name;
std::string gateway;
std::string certificate;
std::string key;
std::string macPrefix;
std::string deviceType;
uint64_t devices = 5;
uint64_t healthCheckInterval = 60;
uint64_t stateInterval = 60 ;
uint64_t minAssociations = 1;
uint64_t maxAssociations = 3;
uint64_t minClients = 1 ;
uint64_t maxClients = 3;
uint64_t simulationLength = 60 * 60;
uint64_t threads = 16;
uint64_t clientInterval = 1;
uint64_t keepAlive = 300;
uint64_t reconnectInterval = 30 ;
uint64_t concurrentDevices = 5;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SimulationDetailsList {
std::vector<SimulationDetails> list;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SimulationStatus {
std::string id;
std::string simulationId;
std::string state;
uint64_t tx;
uint64_t rx;
uint64_t msgsTx;
uint64_t msgsRx;
uint64_t liveDevices;
uint64_t timeToFullDevices;
uint64_t startTime;
uint64_t endTime;
uint64_t errorDevices;
std::string owner;
void to_json(Poco::JSON::Object &Obj) const;
};
struct Dashboard {
int O;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
void reset();
};
}
#endif //UCENTRALSIM_RESTAPI_OWLSOBJECTS_H

View File

@@ -1159,5 +1159,40 @@ namespace OpenWifi::ProvObjects {
return false; return false;
} }
void RRMAlgorithmDetails::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"name",name);
field_to_json(Obj,"parameters",parameters);
}
bool RRMAlgorithmDetails::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"name",name);
field_from_json(Obj,"parameters",parameters);
return true;
} catch(...) {
}
return false;
}
void RRMDetails::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"vendor",vendor);
field_to_json(Obj,"schedule",schedule);
field_to_json(Obj,"algorithms",algorithms);
}
bool RRMDetails::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"vendor",vendor);
field_from_json(Obj,"schedule",schedule);
field_from_json(Obj,"algorithms",algorithms);
return true;
} catch(...) {
}
return false;
}
} }

View File

@@ -62,6 +62,21 @@ namespace OpenWifi::ProvObjects {
}; };
typedef std::vector<ManagementPolicy> ManagementPolicyVec; typedef std::vector<ManagementPolicy> ManagementPolicyVec;
struct RRMAlgorithmDetails {
std::string name;
std::string parameters;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct RRMDetails {
std::string vendor;
std::string schedule;
std::vector<RRMAlgorithmDetails> algorithms;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct DeviceRules { struct DeviceRules {
std::string rcOnly{"inherit"}; std::string rcOnly{"inherit"};
std::string rrm{"inherit"}; std::string rrm{"inherit"};

View File

@@ -9,6 +9,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <type_traits>
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "Poco/Data/LOB.h" #include "Poco/Data/LOB.h"
@@ -27,8 +28,13 @@ namespace OpenWifi {
bool Delete_ = true; bool Delete_ = true;
bool PortalLogin_ = true; bool PortalLogin_ = true;
AclTemplate() noexcept = default;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj); }; bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
static_assert( std::is_nothrow_move_constructible_v<AclTemplate> );
struct WebToken { struct WebToken {
std::string access_token_; std::string access_token_;

View File

@@ -42,6 +42,7 @@ namespace OpenWifi {
void Signup::run() { void Signup::run() {
Running_ = true; Running_ = true;
Utils::SetThreadName("signup-mgr");
while(Running_) { while(Running_) {
Poco::Thread::trySleep(5000); Poco::Thread::trySleep(5000);

View File

@@ -105,6 +105,7 @@ namespace OpenWifi {
} }
void Storage::onTimer([[maybe_unused]] Poco::Timer &timer) { void Storage::onTimer([[maybe_unused]] Poco::Timer &timer) {
Utils::SetThreadName("strg-janitor");
} }
void Storage::Stop() { void Storage::Stop() {
@@ -194,18 +195,24 @@ namespace OpenWifi {
// check that all inventory in venues and entities actually exists, if not, fix it. // check that all inventory in venues and entities actually exists, if not, fix it.
auto FixVenueDevices = [&](const ProvObjects::Venue &V) -> bool { auto FixVenueDevices = [&](const ProvObjects::Venue &V) -> bool {
Types::UUIDvec_t NewDevices; Types::UUIDvec_t NewDevices;
bool modified=false;
for(const auto &device:V.devices) { for(const auto &device:V.devices) {
ProvObjects::InventoryTag T; ProvObjects::InventoryTag T;
if(InventoryDB().GetRecord("id", device, T)) { if(InventoryDB().GetRecord("id", device, T)) {
NewDevices.emplace_back(device); NewDevices.emplace_back(device);
} else { } else {
modified=true;
} }
} }
if(NewDevices!=V.devices) { ProvObjects::Venue NewVenue = V;
if(V.deviceRules.rrm=="yes") {
NewVenue.deviceRules.rrm="inherit";
modified=true;
}
if(modified) {
Logger().warning(fmt::format(" fixing venue: {}", V.info.name)); Logger().warning(fmt::format(" fixing venue: {}", V.info.name));
ProvObjects::Venue NewVenue = V;
NewVenue.devices = NewDevices; NewVenue.devices = NewDevices;
VenueDB().UpdateRecord("id", V.info.id, NewVenue); VenueDB().UpdateRecord("id", V.info.id, NewVenue);
} }
@@ -213,31 +220,175 @@ namespace OpenWifi {
return true; return true;
}; };
auto FixEntityDevices = [&](const ProvObjects::Entity &E) -> bool { auto FixEntity = [&](const ProvObjects::Entity &E) -> bool {
Types::UUIDvec_t NewDevices; Types::UUIDvec_t NewDevices;
bool Modified=false;
for(const auto &device:E.devices) { for(const auto &device:E.devices) {
ProvObjects::InventoryTag T; ProvObjects::InventoryTag T;
if(InventoryDB().GetRecord("id", device, T)) { if(InventoryDB().GetRecord("id", device, T)) {
NewDevices.emplace_back(device); NewDevices.emplace_back(device);
} else { } else {
Modified=true;
} }
} }
if(NewDevices!=E.devices) { Types::UUIDvec_t NewContacts;
for(const auto &contact:E.contacts) {
ProvObjects::Contact C;
if(ContactDB().GetRecord("id", contact, C)) {
NewContacts.emplace_back(contact);
} else {
Modified=true;
}
}
Types::UUIDvec_t NewLocations;
for(const auto &location:E.locations) {
ProvObjects::Location L;
if(LocationDB().GetRecord("id", location, L)) {
NewLocations.emplace_back(location);
} else {
Modified=true;
}
}
Types::UUIDvec_t NewVenues;
for(const auto &venue:E.venues) {
ProvObjects::Venue V;
if(VenueDB().GetRecord("id", venue, V)) {
NewVenues.emplace_back(venue);
} else {
Modified=true;
}
}
Types::UUIDvec_t NewVariables;
for(const auto &variable:E.variables) {
ProvObjects::VariableBlock V;
if(VariablesDB().GetRecord("id", variable, V)) {
NewVariables.emplace_back(variable);
} else {
Modified=true;
}
}
ProvObjects::Entity NewEntity = E;
if(E.deviceRules.rrm=="yes") {
NewEntity.deviceRules.rrm="inherit";
Modified=true;
}
if(Modified)
{
Logger().warning(fmt::format(" fixing entity: {}",E.info.name)); Logger().warning(fmt::format(" fixing entity: {}",E.info.name));
ProvObjects::Entity NewEntity = E;
NewEntity.devices = NewDevices; NewEntity.devices = NewDevices;
NewEntity.contacts = NewContacts;
NewEntity.locations = NewLocations;
NewEntity.venues = NewVenues;
NewEntity.variables = NewVariables;
EntityDB().UpdateRecord("id", E.info.id, NewEntity); EntityDB().UpdateRecord("id", E.info.id, NewEntity);
} }
return true; return true;
}; };
auto FixInventory = [&](const ProvObjects::InventoryTag &T) -> bool {
// check the venue/entity for this device.
ProvObjects::InventoryTag NewTag{T};
bool modified=false;
if(!T.venue.empty() && !VenueDB().Exists("id",T.venue)) {
NewTag.venue.clear();
modified=true;
}
if(!T.entity.empty() && !EntityDB().Exists("id",T.entity)) {
NewTag.entity.clear();
modified=true;
}
if(!T.location.empty() && !LocationDB().Exists("id",T.location)) {
NewTag.location.clear();
modified=true;
}
if(!T.contact.empty() && !ContactDB().Exists("id",T.contact)) {
NewTag.contact.clear();
modified=true;
}
if(T.deviceRules.rrm=="yes") {
NewTag.deviceRules.rrm = "inherit";
modified=true;
}
if(modified) {
Logger().warning(fmt::format(" fixing entity: {}",T.info.name));
InventoryDB().UpdateRecord("id", T.info.id, NewTag);
}
return true;
};
auto FixConfiguration = [&](const ProvObjects::DeviceConfiguration &C) -> bool {
ProvObjects::DeviceConfiguration NewConfig{C};
bool modified = false;
if (C.deviceRules.rrm == "yes") {
NewConfig.deviceRules.rrm = "inherit";
modified = true;
}
if (modified) {
Logger().warning(fmt::format(" fixing configuration: {}", C.info.name));
ConfigurationDB().UpdateRecord("id", C.info.id, NewConfig);
}
return true;
};
auto FixOperator = [&](const ProvObjects::Operator &O) -> bool {
ProvObjects::Operator NewOp{O};
bool modified = false;
if (O.deviceRules.rrm == "yes") {
NewOp.deviceRules.rrm = "inherit";
modified = true;
}
if (modified) {
Logger().warning(fmt::format(" fixing operator: {}", O.info.name));
OperatorDB().UpdateRecord("id", O.info.id, NewOp);
}
return true;
};
auto FixSubscriber = [&](const ProvObjects::SubscriberDevice &O) -> bool {
ProvObjects::SubscriberDevice NewSub{O};
bool modified = false;
if (O.deviceRules.rrm == "yes") {
NewSub.deviceRules.rrm = "inherit";
modified = true;
}
if (modified) {
Logger().warning(fmt::format(" fixing subscriber: {}", O.info.name));
SubscriberDeviceDB().UpdateRecord("id", O.info.id, NewSub);
}
return true;
};
Logger().information("Checking DB consistency: venues"); Logger().information("Checking DB consistency: venues");
VenueDB().Iterate(FixVenueDevices); VenueDB().Iterate(FixVenueDevices);
Logger().information("Checking DB consistency: entities"); Logger().information("Checking DB consistency: entities");
EntityDB().Iterate(FixEntityDevices); EntityDB().Iterate(FixEntity);
Logger().information("Checking DB consistency: inventory");
InventoryDB().Iterate(FixInventory);
Logger().information("Checking DB consistency: configurations");
ConfigurationDB().Iterate(FixConfiguration);
Logger().information("Checking DB consistency: operators");
OperatorDB().Iterate(FixOperator);
Logger().information("Checking DB consistency: subscribers");
SubscriberDeviceDB().Iterate(FixSubscriber);
} }
void Storage::InitializeSystemDBs() { void Storage::InitializeSystemDBs() {

View File

@@ -21,7 +21,7 @@ namespace OpenWifi {
} }
void TagServer::run() { void TagServer::run() {
Utils::SetThreadName("tag-server");
} }
} }

View File

@@ -9,6 +9,7 @@
#include "APConfig.h" #include "APConfig.h"
#include "sdks/SDK_gw.h" #include "sdks/SDK_gw.h"
#include "framework/WebSocketClientNotifications.h" #include "framework/WebSocketClientNotifications.h"
#include "JobController.h"
namespace OpenWifi { namespace OpenWifi {
@@ -19,8 +20,6 @@ namespace OpenWifi {
auto Status = Results->get("status").extract<Poco::JSON::Object::Ptr>(); auto Status = Results->get("status").extract<Poco::JSON::Object::Ptr>();
auto Rejected = Status->getArray("rejected"); auto Rejected = Status->getArray("rejected");
std::transform(Rejected->begin(),Rejected->end(),std::back_inserter(Warnings), [](auto i) -> auto { return i.toString(); }); std::transform(Rejected->begin(),Rejected->end(),std::back_inserter(Warnings), [](auto i) -> auto { return i.toString(); });
// for(const auto &i:*Rejected)
// Warnings.push_back(i.toString());
} }
} catch (...) { } catch (...) {
} }
@@ -37,35 +36,42 @@ namespace OpenWifi {
void run() final { void run() final {
ProvObjects::InventoryTag Device; ProvObjects::InventoryTag Device;
started_=true; started_=true;
Utils::SetThreadName("venue-cfg");
if(StorageService()->InventoryDB().GetRecord("id",uuid_,Device)) { if(StorageService()->InventoryDB().GetRecord("id",uuid_,Device)) {
SerialNumber = Device.serialNumber; SerialNumber = Device.serialNumber;
// std::cout << "Starting push for " << Device.serialNumber << std::endl; // std::cout << "Starting push for " << Device.serialNumber << std::endl;
Logger().debug(fmt::format("{}: Computing configuration.",Device.serialNumber)); Logger().debug(fmt::format("{}: Computing configuration.",Device.serialNumber));
auto DeviceConfig = std::make_shared<APConfig>(Device.serialNumber, Device.deviceType, Logger(), false); auto DeviceConfig = std::make_shared<APConfig>(Device.serialNumber, Device.deviceType, Logger(), false);
auto Configuration = Poco::makeShared<Poco::JSON::Object>(); auto Configuration = Poco::makeShared<Poco::JSON::Object>();
if (DeviceConfig->Get(Configuration)) { try {
std::ostringstream OS; if (DeviceConfig->Get(Configuration)) {
Configuration->stringify(OS); std::ostringstream OS;
auto Response=Poco::makeShared<Poco::JSON::Object>(); Configuration->stringify(OS);
Logger().debug(fmt::format("{}: Pushing configuration.",Device.serialNumber)); auto Response = Poco::makeShared<Poco::JSON::Object>();
if (SDK::GW::Device::Configure(nullptr, Device.serialNumber, Configuration, Response)) { Logger().debug(fmt::format("{}: Pushing configuration.", Device.serialNumber));
Logger().debug(fmt::format("{}: Configuration pushed.",Device.serialNumber)); if (SDK::GW::Device::Configure(nullptr, Device.serialNumber, Configuration, Response)) {
Logger().information(fmt::format("{}: Updated.", Device.serialNumber)); Logger().debug(fmt::format("{}: Configuration pushed.", Device.serialNumber));
// std::cout << Device.serialNumber << ": Updated" << std::endl; Logger().information(fmt::format("{}: Updated.", Device.serialNumber));
updated_++; // std::cout << Device.serialNumber << ": Updated" << std::endl;
updated_++;
} else {
Logger().information(fmt::format("{}: Not updated.", Device.serialNumber));
// std::cout << Device.serialNumber << ": Failed" << std::endl;
failed_++;
}
} else { } else {
Logger().information(fmt::format("{}: Not updated.", Device.serialNumber)); Logger().debug(fmt::format("{}: Configuration is bad.", Device.serialNumber));
// std::cout << Device.serialNumber << ": Failed" << std::endl; bad_config_++;
failed_++; // std::cout << Device.serialNumber << ": Bad config" << std::endl;
} }
} else { } catch (...) {
Logger().debug(fmt::format("{}: Configuration is bad.",Device.serialNumber)); Logger().debug(fmt::format("{}: Configuration is bad (caused an exception).", Device.serialNumber));
bad_config_++; bad_config_++;
// std::cout << Device.serialNumber << ": Bad config" << std::endl;
} }
} }
done_ = true; done_ = true;
// std::cout << "Done push for " << Device.serialNumber << std::endl; // std::cout << "Done push for " << Device.serialNumber << std::endl;
Utils::SetThreadName("free");
} }
uint64_t updated_=0, failed_=0, bad_config_=0; uint64_t updated_=0, failed_=0, bad_config_=0;
@@ -80,133 +86,101 @@ namespace OpenWifi {
inline Poco::Logger & Logger() { return Logger_; } inline Poco::Logger & Logger() { return Logger_; }
}; };
class VenueConfigUpdater: public Poco::Runnable { class VenueConfigUpdater: public Job {
public: public:
explicit VenueConfigUpdater(const std::string & VenueUUID, const SecurityObjects::UserInfo &UI, uint64_t When, Poco::Logger &L) : VenueConfigUpdater(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) :
VenueUUID_(VenueUUID), Job(JobID, name, parameters, when, UI, L) {
UI_(UI),
When_(When),
Logger_(L)
{
} }
inline std::string Start() { inline virtual void run() {
JobId_ = MicroService::CreateUUID(); std::string VenueUUID_;
Worker_.start(*this);
return JobId_;
}
private: Utils::SetThreadName("venue-update");
std::string VenueUUID_; VenueUUID_ = Parameter(0);
SecurityObjects::UserInfo UI_;
uint64_t When_;
Poco::Logger &Logger_;
Poco::Thread Worker_;
std::string JobId_;
Poco::ThreadPool Pool_{2,16,300};
inline Poco::Logger & Logger() { return Logger_; }
inline void run() final {
if(When_ && When_>OpenWifi::Now())
Poco::Thread::trySleep( (long) (When_ - OpenWifi::Now()) * 1000 );
WebSocketNotification<WebSocketNotificationJobContent> N; WebSocketNotification<WebSocketNotificationJobContent> N;
Logger().information(fmt::format("Job {} Starting.", JobId_));
ProvObjects::Venue Venue; ProvObjects::Venue Venue;
uint64_t Updated = 0, Failed = 0 , BadConfigs = 0 ; uint64_t Updated = 0, Failed = 0 , BadConfigs = 0 ;
if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) {
const std::size_t MaxThreads=16;
struct tState {
Poco::Thread thr_;
VenueDeviceConfigUpdater *task= nullptr;
};
N.content.title = fmt::format("Updating {} configurations", Venue.info.name); N.content.title = fmt::format("Updating {} configurations", Venue.info.name);
N.content.jobId = JobId_; N.content.jobId = JobId();
Poco::ThreadPool Pool_;
std::list<VenueDeviceConfigUpdater*> JobList;
std::array<tState,MaxThreads> Tasks;
for(const auto &uuid:Venue.devices) { for(const auto &uuid:Venue.devices) {
auto NewTask = new VenueDeviceConfigUpdater(uuid, Venue.info.name, Logger()); auto NewTask = new VenueDeviceConfigUpdater(uuid, Venue.info.name, Logger());
// std::cout << "Scheduling config push for " << uuid << std::endl; bool TaskAdded=false;
bool found_slot = false; while(!TaskAdded) {
while (!found_slot) { if (Pool_.available()) {
for (auto &cur_task: Tasks) { JobList.push_back(NewTask);
if (cur_task.task == nullptr) { Pool_.start(*NewTask);
cur_task.task = NewTask; TaskAdded = true;
cur_task.thr_.start(*NewTask); continue;
found_slot = true;
break;
}
} }
}
// Let's look for a slot... for(auto job_it = JobList.begin(); job_it !=JobList.end();) {
if (!found_slot) { VenueDeviceConfigUpdater * current_job = *job_it;
for (auto &cur_task: Tasks) { if(current_job!= nullptr && current_job->done_) {
if (cur_task.task != nullptr && cur_task.task->started_) { Updated += current_job->updated_;
if (cur_task.thr_.isRunning()) Failed += current_job->failed_;
continue; BadConfigs += current_job->bad_config_;
if (!cur_task.thr_.isRunning() && cur_task.task->done_) { if(current_job->updated_) {
cur_task.thr_.join(); N.content.success.push_back(current_job->SerialNumber);
Updated += cur_task.task->updated_; } else if(current_job->failed_) {
Failed += cur_task.task->failed_; N.content.warning.push_back(current_job->SerialNumber);
BadConfigs += cur_task.task->bad_config_; } else {
cur_task.task->started_ = cur_task.task->done_ = false; N.content.error.push_back(current_job->SerialNumber);
delete cur_task.task;
cur_task.task = nullptr;
}
}
} }
job_it = JobList.erase(job_it);
delete current_job;
} else {
++job_it;
} }
} }
} }
Logger().debug("Waiting for outstanding update threads to finish."); Logger().debug("Waiting for outstanding update threads to finish.");
bool stillTasksRunning=true; Pool_.joinAll();
while(stillTasksRunning) { for(auto job_it = JobList.begin(); job_it !=JobList.end();) {
stillTasksRunning = false; VenueDeviceConfigUpdater * current_job = *job_it;
for(auto &cur_task:Tasks) { if(current_job!= nullptr && current_job->done_) {
if(cur_task.task!= nullptr && cur_task.task->started_) { Updated += current_job->updated_;
if(cur_task.thr_.isRunning()) { Failed += current_job->failed_;
stillTasksRunning = true; BadConfigs += current_job->bad_config_;
continue; if(current_job->updated_) {
} N.content.success.push_back(current_job->SerialNumber);
if(!cur_task.thr_.isRunning() && cur_task.task->done_) { } else if(current_job->failed_) {
cur_task.thr_.join(); N.content.warning.push_back(current_job->SerialNumber);
if(cur_task.task->updated_) { } else {
Updated++; N.content.error.push_back(current_job->SerialNumber);
N.content.success.push_back(cur_task.task->SerialNumber);
} else if(cur_task.task->failed_) {
Failed++;
N.content.warning.push_back(cur_task.task->SerialNumber);
} else {
BadConfigs++;
N.content.error.push_back(cur_task.task->SerialNumber);
}
cur_task.task->started_ = cur_task.task->done_ = false;
delete cur_task.task;
cur_task.task = nullptr;
}
} }
job_it = JobList.erase(job_it);
delete current_job;
} else {
++job_it;
} }
} }
N.content.details = fmt::format("Job {} Completed: {} updated, {} failed to update, {} bad configurations. ", N.content.details = fmt::format("Job {} Completed: {} updated, {} failed to update, {} bad configurations. ",
JobId_, Updated ,Failed, BadConfigs); JobId(), Updated ,Failed, BadConfigs);
} else { } else {
N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_);
Logger().warning(N.content.details); Logger().warning(N.content.details);
} }
WebSocketClientNotificationVenueUpdateJobCompletionToUser(UI_.email, N); // std::cout << N.content.details << std::endl;
WebSocketClientNotificationVenueUpdateJobCompletionToUser(UserInfo().email, N);
Logger().information(fmt::format("Job {} Completed: {} updated, {} failed to update , {} bad configurations.", Logger().information(fmt::format("Job {} Completed: {} updated, {} failed to update , {} bad configurations.",
JobId_, Updated ,Failed, BadConfigs)); JobId(), Updated ,Failed, BadConfigs));
delete this; Utils::SetThreadName("free");
Complete();
} }
}; };

View File

@@ -8,6 +8,7 @@
#include "StorageService.h" #include "StorageService.h"
#include "APConfig.h" #include "APConfig.h"
#include "sdks/SDK_gw.h" #include "sdks/SDK_gw.h"
#include "JobController.h"
namespace OpenWifi { namespace OpenWifi {
@@ -48,129 +49,90 @@ namespace OpenWifi {
inline Poco::Logger & Logger() { return Logger_; } inline Poco::Logger & Logger() { return Logger_; }
}; };
class VenueRebooter: public Poco::Runnable { class VenueRebooter: public Job {
public: public:
explicit VenueRebooter(const std::string & VenueUUID, const SecurityObjects::UserInfo &UI, uint64_t When, Poco::Logger &L) : VenueRebooter(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) :
VenueUUID_(VenueUUID), Job(JobID, name, parameters, when, UI, L) {
UI_(UI),
When_(When),
Logger_(L)
{
} }
inline std::string Start() { inline virtual void run() final {
JobId_ = MicroService::CreateUUID();
Worker_.start(*this);
return JobId_;
}
private: Utils::SetThreadName("venue-reboot");
std::string VenueUUID_;
SecurityObjects::UserInfo UI_;
uint64_t When_;
Poco::Logger &Logger_;
Poco::Thread Worker_;
std::string JobId_;
Poco::ThreadPool Pool_{2,16,300};
inline Poco::Logger & Logger() { return Logger_; }
inline void run() final {
if(When_ && When_>OpenWifi::Now())
Poco::Thread::trySleep( (long) (When_ - OpenWifi::Now()) * 1000 );
WebSocketClientNotificationVenueRebootList_t N; WebSocketClientNotificationVenueRebootList_t N;
auto VenueUUID_ = Parameter(0);
Logger().information(fmt::format("Job {} Starting.", JobId_));
ProvObjects::Venue Venue; ProvObjects::Venue Venue;
uint64_t rebooted_ = 0, failed_ = 0; uint64_t rebooted_ = 0, failed_ = 0;
if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) {
const std::size_t MaxThreads=16;
struct tState {
Poco::Thread thr_;
VenueDeviceRebooter *task= nullptr;
};
N.content.title = fmt::format("Rebooting {} devices.", Venue.info.name); N.content.title = fmt::format("Rebooting {} devices.", Venue.info.name);
N.content.jobId = JobId_; N.content.jobId = JobId();
std::array<tState,MaxThreads> Tasks; Poco::ThreadPool Pool_;
std::list<VenueDeviceRebooter*> JobList;
for(const auto &uuid:Venue.devices) { for(const auto &uuid:Venue.devices) {
auto NewTask = new VenueDeviceRebooter(uuid, Venue.info.name, Logger()); auto NewTask = new VenueDeviceRebooter(uuid, Venue.info.name, Logger());
// std::cout << "Scheduling config push for " << uuid << std::endl; bool TaskAdded=false;
bool found_slot = false; while(!TaskAdded) {
while (!found_slot) { if (Pool_.available()) {
for (auto &cur_task: Tasks) { JobList.push_back(NewTask);
if (cur_task.task == nullptr) { Pool_.start(*NewTask);
cur_task.task = NewTask; TaskAdded = true;
cur_task.thr_.start(*NewTask); continue;
found_slot = true;
break;
}
} }
}
// Let's look for a slot... for(auto job_it = JobList.begin(); job_it !=JobList.end();) {
if (!found_slot) { VenueDeviceRebooter * current_job = *job_it;
for (auto &cur_task: Tasks) { if(current_job!= nullptr && current_job->done_) {
if (cur_task.task != nullptr && cur_task.task->started_) { if(current_job->rebooted_)
if (cur_task.thr_.isRunning()) N.content.success.push_back(current_job->SerialNumber);
continue; else
if (!cur_task.thr_.isRunning() && cur_task.task->done_) { N.content.warning.push_back(current_job->SerialNumber);
cur_task.thr_.join(); rebooted_ += current_job->rebooted_;
rebooted_ += cur_task.task->rebooted_; failed_ += current_job->failed_;
failed_ += cur_task.task->failed_; job_it = JobList.erase(job_it);
cur_task.task->started_ = cur_task.task->done_ = false; delete current_job;
delete cur_task.task; } else {
cur_task.task = nullptr; ++job_it;
}
}
}
} }
} }
} }
Logger().debug("Waiting for outstanding update threads to finish."); Logger().debug("Waiting for outstanding update threads to finish.");
bool stillTasksRunning=true; Pool_.joinAll();
while(stillTasksRunning) { for(auto job_it = JobList.begin(); job_it !=JobList.end();) {
stillTasksRunning = false; VenueDeviceRebooter * current_job = *job_it;
for(auto &cur_task:Tasks) { if(current_job!= nullptr && current_job->done_) {
if(cur_task.task!= nullptr && cur_task.task->started_) { if(current_job->rebooted_)
if(cur_task.thr_.isRunning()) { N.content.success.push_back(current_job->SerialNumber);
stillTasksRunning = true; else
continue; N.content.warning.push_back(current_job->SerialNumber);
} rebooted_ += current_job->rebooted_;
if(!cur_task.thr_.isRunning() && cur_task.task->done_) { failed_ += current_job->failed_;
cur_task.thr_.join(); job_it = JobList.erase(job_it);
if(cur_task.task->rebooted_) { delete current_job;
rebooted_++; } else {
N.content.success.push_back(cur_task.task->SerialNumber); ++job_it;
} else if(cur_task.task->failed_) {
failed_++;
N.content.warning.push_back(cur_task.task->SerialNumber);
}
cur_task.task->started_ = cur_task.task->done_ = false;
delete cur_task.task;
cur_task.task = nullptr;
}
}
} }
} }
N.content.details = fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.", N.content.details = fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.",
JobId_, rebooted_ ,failed_); JobId(), rebooted_ ,failed_);
} else { } else {
N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_);
Logger().warning(N.content.details); Logger().warning(N.content.details);
} }
WebSocketClientNotificationVenueRebootCompletionToUser(UI_.email,N); // std::cout << N.content.details << std::endl;
WebSocketClientNotificationVenueRebootCompletionToUser(UserInfo().email,N);
Logger().information(fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.", Logger().information(fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.",
JobId_, rebooted_ ,failed_)); JobId(), rebooted_ ,failed_));
delete this; Utils::SetThreadName("free");
Complete();
} }
}; };

View File

@@ -11,6 +11,7 @@
#include "APConfig.h" #include "APConfig.h"
#include "sdks/SDK_gw.h" #include "sdks/SDK_gw.h"
#include "sdks/SDK_fms.h" #include "sdks/SDK_fms.h"
#include "JobController.h"
namespace OpenWifi { namespace OpenWifi {
class VenueDeviceUpgrade : public Poco::Runnable { class VenueDeviceUpgrade : public Poco::Runnable {
@@ -30,7 +31,7 @@ namespace OpenWifi {
Storage::ApplyRules(rules_,Device.deviceRules); Storage::ApplyRules(rules_,Device.deviceRules);
if(Device.deviceRules.firmwareUpgrade=="no") { if(Device.deviceRules.firmwareUpgrade=="no") {
std::cout << "Skipped Upgrade:" << Device.serialNumber << std::endl; poco_debug(Logger(),fmt::format("Skipped Upgrade: {}", Device.serialNumber));
skipped_++; skipped_++;
done_=true; done_=true;
return; return;
@@ -39,24 +40,25 @@ namespace OpenWifi {
FMSObjects::Firmware F; FMSObjects::Firmware F;
if(SDK::FMS::Firmware::GetLatest(Device.deviceType,Device.deviceRules.rcOnly=="yes",F)) { if(SDK::FMS::Firmware::GetLatest(Device.deviceType,Device.deviceRules.rcOnly=="yes",F)) {
if (SDK::GW::Device::Upgrade(nullptr, Device.serialNumber, 0, F.uri)) { if (SDK::GW::Device::Upgrade(nullptr, Device.serialNumber, 0, F.uri)) {
std::cout << "Upgraded:" << Device.serialNumber << " to " << F.uri << std::endl;
Logger().debug(fmt::format("{}: Upgraded.",Device.serialNumber)); Logger().debug(fmt::format("{}: Upgraded.",Device.serialNumber));
upgraded_++; upgraded_++;
} else { } else {
std::cout << "Did not Upgrade:" << Device.serialNumber << " to " << F.uri << std::endl;
Logger().information(fmt::format("{}: Not Upgraded.", Device.serialNumber)); Logger().information(fmt::format("{}: Not Upgraded.", Device.serialNumber));
failed_++; not_connected_++;
} }
} else { } else {
std::cout << "Did not Upgrade:" << Device.serialNumber << " to <unknown>" << std::endl; Logger().information(fmt::format("{}: Not Upgraded. No firmware available.", Device.serialNumber));
failed_++; no_firmware_++;
} }
} }
done_ = true; done_ = true;
// std::cout << "Done push for " << Device.serialNumber << std::endl; // std::cout << "Done push for " << Device.serialNumber << std::endl;
} }
uint64_t upgraded_=0, failed_=0, skipped_=0; std::uint64_t upgraded_ = 0,
not_connected_ = 0,
skipped_ = 0,
no_firmware_ = 0;
bool started_ = false, bool started_ = false,
done_ = false; done_ = false;
std::string SerialNumber; std::string SerialNumber;
@@ -69,132 +71,111 @@ namespace OpenWifi {
inline Poco::Logger & Logger() { return Logger_; } inline Poco::Logger & Logger() { return Logger_; }
}; };
class VenueUpgrade: public Poco::Runnable { class VenueUpgrade: public Job {
public: public:
explicit VenueUpgrade(const std::string & VenueUUID, const SecurityObjects::UserInfo &UI, uint64_t When, Poco::Logger &L) : VenueUpgrade(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) :
VenueUUID_(VenueUUID), Job(JobID, name, parameters, when, UI, L) {
UI_(UI),
When_(When),
Logger_(L)
{
} }
inline std::string Start() { inline virtual void run() final {
JobId_ = MicroService::CreateUUID();
Worker_.start(*this);
return JobId_;
}
private: Utils::SetThreadName("venue-upgr");
std::string VenueUUID_; auto VenueUUID_ = Parameter(0);
SecurityObjects::UserInfo UI_;
uint64_t When_;
Poco::Logger &Logger_;
Poco::Thread Worker_;
std::string JobId_;
Poco::ThreadPool Pool_{2,16,300};
inline Poco::Logger & Logger() { return Logger_; } WebSocketClientNotificationVenueUpgradeList_t N;
inline void run() final {
if(When_ && When_>OpenWifi::Now())
Poco::Thread::trySleep( (long) (When_ - OpenWifi::Now()) * 1000 );
WebSocketClientNotificationVenueRebootList_t N;
Logger().information(fmt::format("Job {} Starting.", JobId_));
ProvObjects::Venue Venue; ProvObjects::Venue Venue;
uint64_t upgraded_ = 0, failed_ = 0; uint64_t upgraded_ = 0,
not_connected_ = 0,
skipped_ = 0,
no_firmware_ = 0;
if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) {
const std::size_t MaxThreads=16;
struct tState {
Poco::Thread thr_;
VenueDeviceUpgrade *task= nullptr;
};
N.content.title = fmt::format("Upgrading {} devices.", Venue.info.name); N.content.title = fmt::format("Upgrading {} devices.", Venue.info.name);
N.content.jobId = JobId_; N.content.jobId = JobId();
std::array<tState,MaxThreads> Tasks; Poco::ThreadPool Pool_;
ProvObjects::DeviceRules Rules; std::list<VenueDeviceUpgrade*> JobList;
ProvObjects::DeviceRules Rules;
StorageService()->VenueDB().EvaluateDeviceRules(Venue.info.id, Rules); StorageService()->VenueDB().EvaluateDeviceRules(Venue.info.id, Rules);
for(const auto &uuid:Venue.devices) { for(const auto &uuid:Venue.devices) {
auto NewTask = new VenueDeviceUpgrade(uuid, Venue.info.name, Rules,Logger()); auto NewTask = new VenueDeviceUpgrade(uuid, Venue.info.name, Rules, Logger());
// std::cout << "Scheduling config push for " << uuid << std::endl; bool TaskAdded = false;
bool found_slot = false; while (!TaskAdded) {
while (!found_slot) { if (Pool_.available()) {
for (auto &cur_task: Tasks) { JobList.push_back(NewTask);
if (cur_task.task == nullptr) { Pool_.start(*NewTask);
cur_task.task = NewTask; TaskAdded = true;
cur_task.thr_.start(*NewTask); continue;
found_slot = true;
break;
}
}
// Let's look for a slot...
if (!found_slot) {
for (auto &cur_task: Tasks) {
if (cur_task.task != nullptr && cur_task.task->started_) {
if (cur_task.thr_.isRunning())
continue;
if (!cur_task.thr_.isRunning() && cur_task.task->done_) {
cur_task.thr_.join();
upgraded_ += cur_task.task->upgraded_;
failed_ += cur_task.task->failed_;
cur_task.task->started_ = cur_task.task->done_ = false;
delete cur_task.task;
cur_task.task = nullptr;
}
}
}
} }
} }
}
Logger().debug("Waiting for outstanding update threads to finish."); for (auto job_it = JobList.begin(); job_it != JobList.end();) {
bool stillTasksRunning=true; VenueDeviceUpgrade *current_job = *job_it;
while(stillTasksRunning) { if (current_job != nullptr && current_job->done_) {
stillTasksRunning = false; if (current_job->upgraded_)
for(auto &cur_task:Tasks) { N.content.success.push_back(current_job->SerialNumber);
if(cur_task.task!= nullptr && cur_task.task->started_) { else if (current_job->skipped_)
if(cur_task.thr_.isRunning()) { N.content.skipped.push_back(current_job->SerialNumber);
stillTasksRunning = true; else if (current_job->not_connected_)
continue; N.content.not_connected.push_back(current_job->SerialNumber);
} else if (current_job->no_firmware_)
if(!cur_task.thr_.isRunning() && cur_task.task->done_) { N.content.no_firmware.push_back(current_job->SerialNumber);
cur_task.thr_.join(); upgraded_ += current_job->upgraded_;
if(cur_task.task->upgraded_) { skipped_ += current_job->skipped_;
upgraded_++; no_firmware_ += current_job->no_firmware_;
N.content.success.push_back(cur_task.task->SerialNumber); not_connected_ += current_job->not_connected_;
} else if(cur_task.task->failed_) { job_it = JobList.erase(job_it);
failed_++; delete current_job;
N.content.warning.push_back(cur_task.task->SerialNumber); } else {
} ++job_it;
cur_task.task->started_ = cur_task.task->done_ = false;
delete cur_task.task;
cur_task.task = nullptr;
}
} }
} }
} }
N.content.details = fmt::format("Job {} Completed: {} upgraded, {} failed to upgrade.", Logger().debug("Waiting for outstanding upgrade threads to finish.");
JobId_, upgraded_ ,failed_); Pool_.joinAll();
for(auto job_it = JobList.begin(); job_it !=JobList.end();) {
VenueDeviceUpgrade * current_job = *job_it;
if(current_job!= nullptr && current_job->done_) {
if (current_job->upgraded_)
N.content.success.push_back(current_job->SerialNumber);
else if (current_job->skipped_)
N.content.skipped.push_back(current_job->SerialNumber);
else if (current_job->not_connected_)
N.content.not_connected.push_back(current_job->SerialNumber);
else if (current_job->no_firmware_)
N.content.no_firmware.push_back(current_job->SerialNumber);
upgraded_ += current_job->upgraded_;
skipped_ += current_job->skipped_;
no_firmware_ += current_job->no_firmware_;
not_connected_ += current_job->not_connected_;
job_it = JobList.erase(job_it);
delete current_job;
} else {
++job_it;
}
}
N.content.details = fmt::format("Job {} Completed: {} upgraded, {} not connected, {} skipped, {} no firmware.",
JobId(),
upgraded_ ,
not_connected_,
skipped_,
no_firmware_);
} else { } else {
N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_);
Logger().warning(N.content.details); Logger().warning(N.content.details);
} }
WebSocketClientNotificationVenueRebootCompletionToUser(UI_.email,N); // std::cout << N.content.details << std::endl;
Logger().information(fmt::format("Job {} Completed: {} upgraded, {} failed to upgrade.", WebSocketClientNotificationVenueUpgradeCompletionToUser(UserInfo().email,N);
JobId_, upgraded_ ,failed_)); Logger().information(N.content.details);
delete this; Utils::SetThreadName("free");
Complete();
} }
}; };
} }

View File

@@ -13,9 +13,10 @@
namespace OpenWifi { namespace OpenWifi {
static const std::string GitUCentralJSONSchemaFile{"https://raw.githubusercontent.com/blogic/ucentral-schema/main/ucentral.schema.json"}; static const std::string GitUCentralJSONSchemaFile{
"https://raw.githubusercontent.com/blogic/ucentral-schema/main/ucentral.schema.json"};
static json DefaultUCentralSchema = R"( static json DefaultUCentralSchema = R"(
{ {
"$id": "https://openwrt.org/ucentral.schema.json", "$id": "https://openwrt.org/ucentral.schema.json",
@@ -43,7 +44,7 @@ namespace OpenWifi {
"switch": { "switch": {
"$ref": "#/$defs/switch" "$ref": "#/$defs/switch"
}, },
"radios": { "radiosgrep": {
"type": "array", "type": "array",
"items": { "items": {
"$ref": "#/$defs/radio" "$ref": "#/$defs/radio"
@@ -518,7 +519,7 @@ namespace OpenWifi {
"maximum": 4050 "maximum": 4050
}, },
"proto": { "proto": {
"decription": "The L2 vlan tag that shall be added (1q,1ad) ", "decription": "The L2 vlan tag that shall be added (1q,1ad ) ",
"type": "string", "type": "string",
"enum": [ "enum": [
"802.1ad", "802.1ad",
@@ -669,6 +670,47 @@ namespace OpenWifi {
} }
} }
}, },
"interface.ipv4.port-forward": {
"type": "object",
"properties": {
"protocol": {
"type": "string",
"enum": [
"tcp",
"udp",
"any"
],
"default": "any"
},
"external-port": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
},
"internal-address": {
"type": "string",
"format": "ipv4",
"example": "0.0.0.120"
},
"internal-port": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
}
},
"required": [
"external-port",
"internal-address"
]
},
"interface.ipv4": { "interface.ipv4": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -722,6 +764,12 @@ namespace OpenWifi {
"items": { "items": {
"$ref": "#/$defs/interface.ipv4.dhcp-lease" "$ref": "#/$defs/interface.ipv4.dhcp-lease"
} }
},
"port-forward": {
"type": "array",
"items": {
"$ref": "#/$defs/interface.ipv4.port-forward"
}
} }
} }
}, },
@@ -751,6 +799,96 @@ namespace OpenWifi {
} }
} }
}, },
"interface.ipv6.port-forward": {
"type": "object",
"properties": {
"protocol": {
"type": "string",
"enum": [
"tcp",
"udp",
"any"
],
"default": "any"
},
"external-port": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
},
"internal-address": {
"type": "string",
"format": "ipv6",
"example": "::1234:abcd"
},
"internal-port": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
}
},
"required": [
"external-port",
"internal-address"
]
},
"interface.ipv6.traffic-allow": {
"type": "object",
"properties": {
"protocol": {
"type": "string",
"default": "any"
},
"source-address": {
"type": "string",
"format": "uc-cidr6",
"example": "2001:db8:1234:abcd::/64",
"default": "::/0"
},
"source-ports": {
"type": "array",
"minItems": 1,
"items": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
}
},
"destination-address": {
"type": "string",
"format": "ipv6",
"example": "::1000"
},
"destination-ports": {
"type": "array",
"minItems": 1,
"items": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
}
}
},
"required": [
"destination-address"
]
},
"interface.ipv6": { "interface.ipv6": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -782,6 +920,18 @@ namespace OpenWifi {
}, },
"dhcpv6": { "dhcpv6": {
"$ref": "#/$defs/interface.ipv6.dhcpv6" "$ref": "#/$defs/interface.ipv6.dhcpv6"
},
"port-forward": {
"type": "array",
"items": {
"$ref": "#/$defs/interface.ipv6.port-forward"
}
},
"traffic-allow": {
"type": "array",
"items": {
"$ref": "#/$defs/interface.ipv6.traffic-allow"
}
} }
} }
}, },
@@ -866,7 +1016,7 @@ namespace OpenWifi {
}, },
"gateway-fqdn": { "gateway-fqdn": {
"type": "string", "type": "string",
"format": "fqdn", "format": "uc-fqdn",
"default": "ucentral.splash" "default": "ucentral.splash"
}, },
"max-clients": { "max-clients": {
@@ -901,6 +1051,7 @@ namespace OpenWifi {
"psk", "psk",
"psk2", "psk2",
"psk-mixed", "psk-mixed",
"psk2-radius",
"wpa", "wpa",
"wpa2", "wpa2",
"wpa-mixed", "wpa-mixed",
@@ -961,6 +1112,10 @@ namespace OpenWifi {
"type": "boolean", "type": "boolean",
"default": false "default": false
}, },
"reduced-neighbor-reporting": {
"type": "boolean",
"default": false
},
"lci": { "lci": {
"type": "string" "type": "string"
}, },
@@ -1527,6 +1682,11 @@ namespace OpenWifi {
"decription": "This option allows embedding custom vendor specific IEs inside the beacons of a BSS in AP mode.", "decription": "This option allows embedding custom vendor specific IEs inside the beacons of a BSS in AP mode.",
"type": "string" "type": "string"
}, },
"fils-discovery-interval": {
"type": "integer",
"default": 20,
"maximum": 10000
},
"encryption": { "encryption": {
"$ref": "#/$defs/interface.ssid.encryption" "$ref": "#/$defs/interface.ssid.encryption"
}, },
@@ -2087,6 +2247,10 @@ namespace OpenWifi {
"auto-channel": { "auto-channel": {
"type": "boolean", "type": "boolean",
"default": false "default": false
},
"ipv6": {
"type": "boolean",
"default": false
} }
} }
}, },
@@ -2193,7 +2357,7 @@ namespace OpenWifi {
"properties": { "properties": {
"fqdn": { "fqdn": {
"type": "string", "type": "string",
"format": "fqdn" "format": "uc-fqdn"
}, },
"suffix-matching": { "suffix-matching": {
"type": "boolean", "type": "boolean",
@@ -2444,8 +2608,7 @@ namespace OpenWifi {
} }
} }
} }
)"_json;
)"_json;
class custom_error_handler : public nlohmann::json_schema::basic_error_handler class custom_error_handler : public nlohmann::json_schema::basic_error_handler
{ {
@@ -2460,9 +2623,18 @@ namespace OpenWifi {
void ConfigurationValidator::Init() { void ConfigurationValidator::Init() {
if(Initialized_) if(Initialized_)
return; return;
std::string GitSchema; std::string GitSchema;
if(MicroService::instance().ConfigGetBool("ucentral.datamodel.internal",true)) {
RootSchema_ = DefaultUCentralSchema;
Logger().information("Using uCentral validation from built-in default.");
Initialized_ = Working_ = true;
return;
}
try { try {
if(Utils::wgets(GitUCentralJSONSchemaFile, GitSchema)) { auto GitURI = MicroService::instance().ConfigGetString("ucentral.datamodel.uri",GitUCentralJSONSchemaFile);
if(Utils::wgets(GitURI, GitSchema)) {
RootSchema_ = json::parse(GitSchema); RootSchema_ = json::parse(GitSchema);
Logger().information("Using uCentral validation schema from GIT."); Logger().information("Using uCentral validation schema from GIT.");
} else { } else {
@@ -2528,6 +2700,17 @@ namespace OpenWifi {
return IsCIDRv4(value) || IsCIDRv6(value); return IsCIDRv4(value) || IsCIDRv6(value);
} }
static inline bool IsPortRangeIsValid(const std::string &r) {
const auto ports = Poco::StringTokenizer("-",r,Poco::StringTokenizer::TOK_TRIM);
for(const auto &port:ports) {
uint32_t port_num = std::stoul(port);
if(port_num==0 || port_num>65535)
return false;
}
return true;
}
void ConfigurationValidator::my_format_checker(const std::string &format, const std::string &value) void ConfigurationValidator::my_format_checker(const std::string &format, const std::string &value)
{ {
static const std::regex host_regex{"^(?=.{1,254}$)((?=[a-z0-9-]{1,63}\\.)(xn--+)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}$"}; static const std::regex host_regex{"^(?=.{1,254}$)((?=[a-z0-9-]{1,63}\\.)(xn--+)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}$"};
@@ -2578,6 +2761,14 @@ namespace OpenWifi {
} catch (...) { } catch (...) {
} }
throw std::invalid_argument(value + " is not a valid URI: should be something like https://hello.world.com."); throw std::invalid_argument(value + " is not a valid URI: should be something like https://hello.world.com.");
} else if(format == "uc-portrange") {
try {
if(IsPortRangeIsValid(value))
return;
throw std::invalid_argument(value + " is not a valid port range: should an integer between 1-65535 or a port range like post-port.");
} catch (...) {
}
throw std::invalid_argument(value + " is not a valid port range: should an integer between 1-65535 or a port range like post-port.");
} else if(format == "ip") { } else if(format == "ip") {
if (IsIP(value)) if (IsIP(value))
return; return;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,169 @@
//
// Created by stephane bourque on 2022-09-29.
//
#pragma once
#include "fmt/format.h"
#include "Poco/Util/Application.h"
#include "Poco/ErrorHandler.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/SSLException.h"
#include "Poco/JSON/Template.h"
#include "Poco/Thread.h"
namespace OpenWifi {
class MicroServiceErrorHandler : public Poco::ErrorHandler {
public:
explicit MicroServiceErrorHandler(Poco::Util::Application &App) : App_(App) {
}
inline void exception(const Poco::Exception & Base) override {
try {
if(Poco::Thread::current()!= nullptr) {
t_name = Poco::Thread::current()->getName();
t_id = Poco::Thread::current()->id();
} else {
t_name = "startup_code";
t_id = 0;
}
App_.logger().log(Base);
Base.rethrow();
} catch (const Poco::Net::InvalidCertificateException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidCertificateException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::InvalidSocketException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidSocketException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::WebSocketException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::WebSocketException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::ConnectionResetException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::ConnectionResetException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::CertificateValidationException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::CertificateValidationException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::SSLConnectionUnexpectedlyClosedException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::SSLContextException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::SSLContextException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::SSLException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::SSLException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::InvalidAddressException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidAddressException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::NetException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::NetException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::IOException &E) {
poco_error(App_.logger(), fmt::format("Poco::IOException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::RuntimeException &E) {
poco_error(App_.logger(), fmt::format("Poco::RuntimeException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::JSON::JSONTemplateException &E) {
poco_error(App_.logger(), fmt::format("Poco::JSON::JSONTemplateException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::JSON::JSONException &E) {
poco_error(App_.logger(), fmt::format("Poco::JSON::JSONException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::ApplicationException &E) {
poco_error(App_.logger(), fmt::format("Poco::ApplicationException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Exception &E) {
poco_error(App_.logger(), fmt::format("Poco::Exception thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (...) {
poco_error(App_.logger(), fmt::format("Poco:Generic thr_name={}",t_name, t_id));
}
}
inline void exception(const std::exception & E) override {
if(Poco::Thread::current()!= nullptr) {
t_name = Poco::Thread::current()->getName();
t_id = Poco::Thread::current()->id();
} else {
t_name = "startup_code";
t_id = 0;
}
poco_warning(App_.logger(), fmt::format("std::exception in {}: {} thr_id={}",
t_name,E.what(),
t_id));
}
inline void exception() override {
if(Poco::Thread::current()!= nullptr) {
t_name = Poco::Thread::current()->getName();
t_id = Poco::Thread::current()->id();
} else {
t_name = "startup_code";
t_id = 0;
}
poco_warning(App_.logger(), fmt::format("generic exception in {} thr_id={}",
t_name, t_id));
}
private:
Poco::Util::Application &App_;
std::string t_name;
int t_id=0;
};
}

View File

@@ -33,7 +33,6 @@ namespace OpenWifi {
int Start() override { int Start() override {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
Logger().setLevel(Poco::Message::PRIO_INFORMATION);
Logger().notice("Starting."); Logger().notice("Starting.");
std::string DBType = MicroService::instance().ConfigGetString("storage.type"); std::string DBType = MicroService::instance().ConfigGetString("storage.type");

View File

@@ -146,6 +146,10 @@ namespace OpenWifi {
WebSocketClientServer()->SendUserNotification(User,N); WebSocketClientServer()->SendUserNotification(User,N);
} }
/////
/////
/////
struct WebSocketNotificationRebootList { struct WebSocketNotificationRebootList {
std::string title, std::string title,
details, details,
@@ -189,5 +193,58 @@ namespace OpenWifi {
WebSocketClientServer()->SendUserNotification(User,N); WebSocketClientServer()->SendUserNotification(User,N);
} }
/////
/////
/////
struct WebSocketNotificationUpgradeList {
std::string title,
details,
jobId;
std::vector<std::string> success,
skipped,
no_firmware,
not_connected;
uint64_t timeStamp=OpenWifi::Now();
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
typedef WebSocketNotification<WebSocketNotificationUpgradeList> WebSocketClientNotificationVenueUpgradeList_t;
inline void WebSocketNotificationUpgradeList::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"title",title);
RESTAPI_utils::field_to_json(Obj,"jobId",jobId);
RESTAPI_utils::field_to_json(Obj,"success",success);
RESTAPI_utils::field_to_json(Obj,"notConnected",not_connected);
RESTAPI_utils::field_to_json(Obj,"noFirmware",no_firmware);
RESTAPI_utils::field_to_json(Obj,"skipped",skipped);
RESTAPI_utils::field_to_json(Obj,"timeStamp",timeStamp);
RESTAPI_utils::field_to_json(Obj,"details",details);
}
inline bool WebSocketNotificationUpgradeList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
RESTAPI_utils::field_from_json(Obj,"title",title);
RESTAPI_utils::field_from_json(Obj,"jobId",jobId);
RESTAPI_utils::field_from_json(Obj,"success",success);
RESTAPI_utils::field_from_json(Obj,"notConnected",not_connected);
RESTAPI_utils::field_from_json(Obj,"noFirmware",no_firmware);
RESTAPI_utils::field_from_json(Obj,"skipped",skipped);
RESTAPI_utils::field_from_json(Obj,"timeStamp",timeStamp);
RESTAPI_utils::field_from_json(Obj,"details",details);
return true;
} catch(...) {
}
return false;
}
inline void WebSocketClientNotificationVenueUpgradeCompletionToUser( const std::string & User, WebSocketClientNotificationVenueUpgradeList_t &N) {
N.type = "venue_upgrader";
WebSocketClientServer()->SendUserNotification(User,N);
}
} // namespace OpenWifi } // namespace OpenWifi

View File

@@ -133,6 +133,37 @@ namespace ORM {
return R; return R;
} }
inline std::string WHERE_AND_(std::string Result) {
return Result;
}
template <typename T, typename... Args> std::string WHERE_AND_(std::string Result, const char *fieldName, const T &Value, Args... args) {
if constexpr(std::is_same_v<T,std::string>)
{
if(!Value.empty()) {
if(!Result.empty())
Result += " and ";
Result += fieldName;
Result += '=';
Result += "'";
Result += Escape(Value);
Result += "'";
}
} else {
if(!Result.empty())
Result += " and ";
Result += fieldName ;
Result += '=';
Result += std::to_string(Value);
}
return WHERE_AND_(Result,args...);
}
template <typename... Args> std::string WHERE_AND(Args... args) {
std::string Result;
return WHERE_AND_(Result, args...);
}
enum SqlComparison { EQ = 0, NEQ, LT, LTE, GT, GTE }; enum SqlComparison { EQ = 0, NEQ, LT, LTE, GT, GTE };
enum SqlBinaryOp { AND = 0 , OR }; enum SqlBinaryOp { AND = 0 , OR };

View File

@@ -5,6 +5,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <cstring>
#include "Poco/String.h" #include "Poco/String.h"
#if defined(__GNUC__) #if defined(__GNUC__)
@@ -195,6 +196,8 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg InvalidRadiusServerEntry{1142,"RADIUS Server IP address invalid or port missing."}; static const struct msg InvalidRadiusServerEntry{1142,"RADIUS Server IP address invalid or port missing."};
static const struct msg InvalidRadiusServerWeigth{1143,"RADIUS Server IP weight cannot be 0."}; static const struct msg InvalidRadiusServerWeigth{1143,"RADIUS Server IP weight cannot be 0."};
static const struct msg MaximumRTTYSessionsReached{1144,"Too many RTTY sessions currently active"};
static const struct msg DeviceIsAlreadyBusy{1145,"Device is already executing a command. Please try later."};
} }
@@ -427,7 +430,9 @@ namespace OpenWifi::uCentralProtocol {
static const char *RADIUSDATA = "data"; static const char *RADIUSDATA = "data";
static const char *RADIUSACCT = "acct"; static const char *RADIUSACCT = "acct";
static const char *RADIUSAUTH = "auth"; static const char *RADIUSAUTH = "auth";
static const char *RADIUSCOA = "coa";
static const char *RADIUSDST = "dst"; static const char *RADIUSDST = "dst";
static const char *IES = "ies";
} }
namespace OpenWifi::uCentralProtocol::Events { namespace OpenWifi::uCentralProtocol::Events {
@@ -442,6 +447,7 @@ namespace OpenWifi::uCentralProtocol::Events {
static const char *RECOVERY = "recovery"; static const char *RECOVERY = "recovery";
static const char *TELEMETRY = "telemetry"; static const char *TELEMETRY = "telemetry";
static const char *DEVICEUPDATE = "deviceupdate"; static const char *DEVICEUPDATE = "deviceupdate";
static const char *VENUE_BROADCAST = "venue_broadcast";
enum EVENT_MSG { enum EVENT_MSG {
ET_UNKNOWN, ET_UNKNOWN,
@@ -454,28 +460,34 @@ namespace OpenWifi::uCentralProtocol::Events {
ET_CFGPENDING, ET_CFGPENDING,
ET_RECOVERY, ET_RECOVERY,
ET_DEVICEUPDATE, ET_DEVICEUPDATE,
ET_TELEMETRY ET_TELEMETRY,
ET_VENUEBROADCAST
}; };
inline static EVENT_MSG EventFromString(const std::string & Method) { inline EVENT_MSG EventFromString(const std::string & Method) {
static std::vector<std::pair<const char *,EVENT_MSG>> Values{ if(strcmp(STATE,Method.c_str())==0)
{ CFGPENDING , ET_CFGPENDING }, return ET_STATE;
{ CONNECT, ET_CONNECT }, else if(strcmp(HEALTHCHECK,Method.c_str())==0)
{ CRASHLOG, ET_CRASHLOG }, return ET_HEALTHCHECK;
{ DEVICEUPDATE, ET_DEVICEUPDATE }, else if(strcmp(CONNECT,Method.c_str())==0)
{ HEALTHCHECK, ET_HEALTHCHECK }, return ET_CONNECT;
{ LOG, ET_LOG }, else if(strcmp(CFGPENDING,Method.c_str())==0)
{ PING, ET_PING }, return ET_CFGPENDING;
{ RECOVERY, ET_RECOVERY }, else if(strcmp(CRASHLOG,Method.c_str())==0)
{ STATE, ET_STATE }, return ET_CRASHLOG;
{ TELEMETRY, ET_TELEMETRY } else if(strcmp(DEVICEUPDATE,Method.c_str())==0)
}; return ET_DEVICEUPDATE;
else if(strcmp(LOG,Method.c_str())==0)
std::string L = Poco::toLower(Method); return ET_LOG;
auto hint = std::find_if(cbegin(Values),cend(Values),[&](const std::pair<const char *,EVENT_MSG> &v) ->bool { return strcmp(v.first,L.c_str())==0; }); else if(strcmp(PING,Method.c_str())==0)
if(hint == cend(Values)) return ET_PING;
return ET_UNKNOWN; else if(strcmp(RECOVERY,Method.c_str())==0)
return hint->second; return ET_RECOVERY;
else if(strcmp(TELEMETRY,Method.c_str())==0)
return ET_TELEMETRY;
else if(strcmp(VENUE_BROADCAST,Method.c_str())==0)
return ET_VENUEBROADCAST;
return ET_UNKNOWN;
}; };
} }

937
src/libs/croncpp.h Normal file
View File

@@ -0,0 +1,937 @@
/*
MIT License
Copyright (c) 2018 Marius Bancila
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This file is from https://github.com/mariusbancila/croncpp.git.
*/
#pragma once
#include <vector>
#include <string>
#include <sstream>
#include <bitset>
#include <cctype>
#include <ctime>
#include <iomanip>
#include <algorithm>
#include <chrono>
#if __cplusplus > 201402L
#include <string_view>
#define CRONCPP_IS_CPP17
#endif
namespace cron
{
#ifdef CRONCPP_IS_CPP17
#define CRONCPP_STRING_VIEW std::string_view
#define CRONCPP_STRING_VIEW_NPOS std::string_view::npos
#define CRONCPP_CONSTEXPTR constexpr
#else
#define CRONCPP_STRING_VIEW std::string const &
#define CRONCPP_STRING_VIEW_NPOS std::string::npos
#define CRONCPP_CONSTEXPTR
#endif
using cron_int = uint8_t;
constexpr std::time_t INVALID_TIME = static_cast<std::time_t>(-1);
constexpr size_t INVALID_INDEX = static_cast<size_t>(-1);
class cronexpr;
namespace detail
{
enum class cron_field
{
second,
minute,
hour_of_day,
day_of_week,
day_of_month,
month,
year
};
template <typename Traits>
static bool find_next(cronexpr const & cex,
std::tm& date,
size_t const dot);
}
struct bad_cronexpr : public std::runtime_error
{
public:
explicit bad_cronexpr(CRONCPP_STRING_VIEW message) :
std::runtime_error(message.data())
{}
};
struct cron_standard_traits
{
static const cron_int CRON_MIN_SECONDS = 0;
static const cron_int CRON_MAX_SECONDS = 59;
static const cron_int CRON_MIN_MINUTES = 0;
static const cron_int CRON_MAX_MINUTES = 59;
static const cron_int CRON_MIN_HOURS = 0;
static const cron_int CRON_MAX_HOURS = 23;
static const cron_int CRON_MIN_DAYS_OF_WEEK = 0;
static const cron_int CRON_MAX_DAYS_OF_WEEK = 6;
static const cron_int CRON_MIN_DAYS_OF_MONTH = 1;
static const cron_int CRON_MAX_DAYS_OF_MONTH = 31;
static const cron_int CRON_MIN_MONTHS = 1;
static const cron_int CRON_MAX_MONTHS = 12;
static const cron_int CRON_MAX_YEARS_DIFF = 4;
#ifdef CRONCPP_IS_CPP17
static const inline std::vector<std::string> DAYS = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
static const inline std::vector<std::string> MONTHS = { "NIL", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
#else
static std::vector<std::string>& DAYS()
{
static std::vector<std::string> days = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
return days;
}
static std::vector<std::string>& MONTHS()
{
static std::vector<std::string> months = { "NIL", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
return months;
}
#endif
};
struct cron_oracle_traits
{
static const cron_int CRON_MIN_SECONDS = 0;
static const cron_int CRON_MAX_SECONDS = 59;
static const cron_int CRON_MIN_MINUTES = 0;
static const cron_int CRON_MAX_MINUTES = 59;
static const cron_int CRON_MIN_HOURS = 0;
static const cron_int CRON_MAX_HOURS = 23;
static const cron_int CRON_MIN_DAYS_OF_WEEK = 1;
static const cron_int CRON_MAX_DAYS_OF_WEEK = 7;
static const cron_int CRON_MIN_DAYS_OF_MONTH = 1;
static const cron_int CRON_MAX_DAYS_OF_MONTH = 31;
static const cron_int CRON_MIN_MONTHS = 0;
static const cron_int CRON_MAX_MONTHS = 11;
static const cron_int CRON_MAX_YEARS_DIFF = 4;
#ifdef CRONCPP_IS_CPP17
static const inline std::vector<std::string> DAYS = { "NIL", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
static const inline std::vector<std::string> MONTHS = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
#else
static std::vector<std::string>& DAYS()
{
static std::vector<std::string> days = { "NIL", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
return days;
}
static std::vector<std::string>& MONTHS()
{
static std::vector<std::string> months = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
return months;
}
#endif
};
struct cron_quartz_traits
{
static const cron_int CRON_MIN_SECONDS = 0;
static const cron_int CRON_MAX_SECONDS = 59;
static const cron_int CRON_MIN_MINUTES = 0;
static const cron_int CRON_MAX_MINUTES = 59;
static const cron_int CRON_MIN_HOURS = 0;
static const cron_int CRON_MAX_HOURS = 23;
static const cron_int CRON_MIN_DAYS_OF_WEEK = 1;
static const cron_int CRON_MAX_DAYS_OF_WEEK = 7;
static const cron_int CRON_MIN_DAYS_OF_MONTH = 1;
static const cron_int CRON_MAX_DAYS_OF_MONTH = 31;
static const cron_int CRON_MIN_MONTHS = 1;
static const cron_int CRON_MAX_MONTHS = 12;
static const cron_int CRON_MAX_YEARS_DIFF = 4;
#ifdef CRONCPP_IS_CPP17
static const inline std::vector<std::string> DAYS = { "NIL", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
static const inline std::vector<std::string> MONTHS = { "NIL", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
#else
static std::vector<std::string>& DAYS()
{
static std::vector<std::string> days = { "NIL", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
return days;
}
static std::vector<std::string>& MONTHS()
{
static std::vector<std::string> months = { "NIL", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" };
return months;
}
#endif
};
class cronexpr;
template <typename Traits = cron_standard_traits>
static cronexpr make_cron(CRONCPP_STRING_VIEW expr);
class cronexpr
{
std::bitset<60> seconds;
std::bitset<60> minutes;
std::bitset<24> hours;
std::bitset<7> days_of_week;
std::bitset<31> days_of_month;
std::bitset<12> months;
std::string expr;
friend bool operator==(cronexpr const & e1, cronexpr const & e2);
friend bool operator!=(cronexpr const & e1, cronexpr const & e2);
template <typename Traits>
friend bool detail::find_next(cronexpr const & cex,
std::tm& date,
size_t const dot);
friend std::string to_cronstr(cronexpr const& cex);
friend std::string to_string(cronexpr const & cex);
template <typename Traits>
friend cronexpr make_cron(CRONCPP_STRING_VIEW expr);
};
inline bool operator==(cronexpr const & e1, cronexpr const & e2)
{
return
e1.seconds == e2.seconds &&
e1.minutes == e2.minutes &&
e1.hours == e2.hours &&
e1.days_of_week == e2.days_of_week &&
e1.days_of_month == e2.days_of_month &&
e1.months == e2.months;
}
inline bool operator!=(cronexpr const & e1, cronexpr const & e2)
{
return !(e1 == e2);
}
inline std::string to_string(cronexpr const & cex)
{
return
cex.seconds.to_string() + " " +
cex.minutes.to_string() + " " +
cex.hours.to_string() + " " +
cex.days_of_month.to_string() + " " +
cex.months.to_string() + " " +
cex.days_of_week.to_string();
}
inline std::string to_cronstr(cronexpr const& cex)
{
return cex.expr;
}
namespace utils
{
inline std::time_t tm_to_time(std::tm& date)
{
return std::mktime(&date);
}
inline std::tm* time_to_tm(std::time_t const * date, std::tm* const out)
{
#ifdef _WIN32
errno_t err = localtime_s(out, date);
return 0 == err ? out : nullptr;
#else
return localtime_r(date, out);
#endif
}
inline std::tm to_tm(CRONCPP_STRING_VIEW time)
{
std::tm result;
#if __cplusplus > 201103L
std::istringstream str(time.data());
str.imbue(std::locale(setlocale(LC_ALL, nullptr)));
str >> std::get_time(&result, "%Y-%m-%d %H:%M:%S");
if (str.fail()) throw std::runtime_error("Parsing date failed!");
#else
int year = 1900;
int month = 1;
int day = 1;
int hour = 0;
int minute = 0;
int second = 0;
sscanf(time.data(), "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second);
result.tm_year = year - 1900;
result.tm_mon = month - 1;
result.tm_mday = day;
result.tm_hour = hour;
result.tm_min = minute;
result.tm_sec = second;
#endif
result.tm_isdst = -1; // DST info not available
return result;
}
inline std::string to_string(std::tm const & tm)
{
#if __cplusplus > 201103L
std::ostringstream str;
str.imbue(std::locale(setlocale(LC_ALL, nullptr)));
str << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
if (str.fail()) throw std::runtime_error("Writing date failed!");
return str.str();
#else
char buff[70] = {0};
strftime(buff, sizeof(buff), "%Y-%m-%d %H:%M:%S", &tm);
return std::string(buff);
#endif
}
inline std::string to_upper(std::string text)
{
std::transform(std::begin(text), std::end(text),
std::begin(text), [](char const c) { return static_cast<char>(std::toupper(c)); });
return text;
}
static std::vector<std::string> split(CRONCPP_STRING_VIEW text, char const delimiter)
{
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(text.data());
while (std::getline(tokenStream, token, delimiter))
{
tokens.push_back(token);
}
return tokens;
}
CRONCPP_CONSTEXPTR inline bool contains(CRONCPP_STRING_VIEW text, char const ch) noexcept
{
return CRONCPP_STRING_VIEW_NPOS != text.find_first_of(ch);
}
}
namespace detail
{
inline cron_int to_cron_int(CRONCPP_STRING_VIEW text)
{
try
{
return static_cast<cron_int>(std::stoul(text.data()));
}
catch (std::exception const & ex)
{
throw bad_cronexpr(ex.what());
}
}
static std::string replace_ordinals(
std::string text,
std::vector<std::string> const & replacement)
{
for (size_t i = 0; i < replacement.size(); ++i)
{
auto pos = text.find(replacement[i]);
if (std::string::npos != pos)
text.replace(pos, 3 ,std::to_string(i));
}
return text;
}
static std::pair<cron_int, cron_int> make_range(
CRONCPP_STRING_VIEW field,
cron_int const minval,
cron_int const maxval)
{
cron_int first = 0;
cron_int last = 0;
if (field.size() == 1 && field[0] == '*')
{
first = minval;
last = maxval;
}
else if (!utils::contains(field, '-'))
{
first = to_cron_int(field);
last = first;
}
else
{
auto parts = utils::split(field, '-');
if (parts.size() != 2)
throw bad_cronexpr("Specified range requires two fields");
first = to_cron_int(parts[0]);
last = to_cron_int(parts[1]);
}
if (first > maxval || last > maxval)
{
throw bad_cronexpr("Specified range exceeds maximum");
}
if (first < minval || last < minval)
{
throw bad_cronexpr("Specified range is less than minimum");
}
if (first > last)
{
throw bad_cronexpr("Specified range start exceeds range end");
}
return { first, last };
}
template <size_t N>
static void set_cron_field(
CRONCPP_STRING_VIEW value,
std::bitset<N>& target,
cron_int const minval,
cron_int const maxval)
{
if(value.length() > 0 && value[value.length()-1] == ',')
throw bad_cronexpr("Value cannot end with comma");
auto fields = utils::split(value, ',');
if (fields.empty())
throw bad_cronexpr("Expression parsing error");
for (auto const & field : fields)
{
if (!utils::contains(field, '/'))
{
#ifdef CRONCPP_IS_CPP17
auto[first, last] = detail::make_range(field, minval, maxval);
#else
auto range = detail::make_range(field, minval, maxval);
auto first = range.first;
auto last = range.second;
#endif
for (cron_int i = first - minval; i <= last - minval; ++i)
{
target.set(i);
}
}
else
{
auto parts = utils::split(field, '/');
if (parts.size() != 2)
throw bad_cronexpr("Incrementer must have two fields");
#ifdef CRONCPP_IS_CPP17
auto[first, last] = detail::make_range(parts[0], minval, maxval);
#else
auto range = detail::make_range(parts[0], minval, maxval);
auto first = range.first;
auto last = range.second;
#endif
if (!utils::contains(parts[0], '-'))
{
last = maxval;
}
auto delta = detail::to_cron_int(parts[1]);
if(delta <= 0)
throw bad_cronexpr("Incrementer must be a positive value");
for (cron_int i = first - minval; i <= last - minval; i += delta)
{
target.set(i);
}
}
}
}
template <typename Traits>
static void set_cron_days_of_week(
std::string value,
std::bitset<7>& target)
{
auto days = utils::to_upper(value);
auto days_replaced = detail::replace_ordinals(
days,
#ifdef CRONCPP_IS_CPP17
Traits::DAYS
#else
Traits::DAYS()
#endif
);
if (days_replaced.size() == 1 && days_replaced[0] == '?')
days_replaced[0] = '*';
set_cron_field(
days_replaced,
target,
Traits::CRON_MIN_DAYS_OF_WEEK,
Traits::CRON_MAX_DAYS_OF_WEEK);
}
template <typename Traits>
static void set_cron_days_of_month(
std::string value,
std::bitset<31>& target)
{
if (value.size() == 1 && value[0] == '?')
value[0] = '*';
set_cron_field(
value,
target,
Traits::CRON_MIN_DAYS_OF_MONTH,
Traits::CRON_MAX_DAYS_OF_MONTH);
}
template <typename Traits>
static void set_cron_month(
std::string value,
std::bitset<12>& target)
{
auto month = utils::to_upper(value);
auto month_replaced = replace_ordinals(
month,
#ifdef CRONCPP_IS_CPP17
Traits::MONTHS
#else
Traits::MONTHS()
#endif
);
set_cron_field(
month_replaced,
target,
Traits::CRON_MIN_MONTHS,
Traits::CRON_MAX_MONTHS);
}
template <size_t N>
inline size_t next_set_bit(
std::bitset<N> const & target,
size_t /*minimum*/,
size_t /*maximum*/,
size_t offset)
{
for (auto i = offset; i < N; ++i)
{
if (target.test(i)) return i;
}
return INVALID_INDEX;
}
inline void add_to_field(
std::tm& date,
cron_field const field,
int const val)
{
switch (field)
{
case cron_field::second:
date.tm_sec += val;
break;
case cron_field::minute:
date.tm_min += val;
break;
case cron_field::hour_of_day:
date.tm_hour += val;
break;
case cron_field::day_of_week:
case cron_field::day_of_month:
date.tm_mday += val;
break;
case cron_field::month:
date.tm_mon += val;
break;
case cron_field::year:
date.tm_year += val;
break;
}
if (INVALID_TIME == utils::tm_to_time(date))
throw bad_cronexpr("Invalid time expression");
}
inline void set_field(
std::tm& date,
cron_field const field,
int const val)
{
switch (field)
{
case cron_field::second:
date.tm_sec = val;
break;
case cron_field::minute:
date.tm_min = val;
break;
case cron_field::hour_of_day:
date.tm_hour = val;
break;
case cron_field::day_of_week:
date.tm_wday = val;
break;
case cron_field::day_of_month:
date.tm_mday = val;
break;
case cron_field::month:
date.tm_mon = val;
break;
case cron_field::year:
date.tm_year = val;
break;
}
if (INVALID_TIME == utils::tm_to_time(date))
throw bad_cronexpr("Invalid time expression");
}
inline void reset_field(
std::tm& date,
cron_field const field)
{
switch (field)
{
case cron_field::second:
date.tm_sec = 0;
break;
case cron_field::minute:
date.tm_min = 0;
break;
case cron_field::hour_of_day:
date.tm_hour = 0;
break;
case cron_field::day_of_week:
date.tm_wday = 0;
break;
case cron_field::day_of_month:
date.tm_mday = 1;
break;
case cron_field::month:
date.tm_mon = 0;
break;
case cron_field::year:
date.tm_year = 0;
break;
}
if (INVALID_TIME == utils::tm_to_time(date))
throw bad_cronexpr("Invalid time expression");
}
inline void reset_all_fields(
std::tm& date,
std::bitset<7> const & marked_fields)
{
for (size_t i = 0; i < marked_fields.size(); ++i)
{
if (marked_fields.test(i))
reset_field(date, static_cast<cron_field>(i));
}
}
inline void mark_field(
std::bitset<7> & orders,
cron_field const field)
{
if (!orders.test(static_cast<size_t>(field)))
orders.set(static_cast<size_t>(field));
}
template <size_t N>
static size_t find_next(
std::bitset<N> const & target,
std::tm& date,
unsigned int const minimum,
unsigned int const maximum,
unsigned int const value,
cron_field const field,
cron_field const next_field,
std::bitset<7> const & marked_fields)
{
auto next_value = next_set_bit(target, minimum, maximum, value);
if (INVALID_INDEX == next_value)
{
add_to_field(date, next_field, 1);
reset_field(date, field);
next_value = next_set_bit(target, minimum, maximum, 0);
}
if (INVALID_INDEX == next_value || next_value != value)
{
set_field(date, field, static_cast<int>(next_value));
reset_all_fields(date, marked_fields);
}
return next_value;
}
template <typename Traits>
static size_t find_next_day(
std::tm& date,
std::bitset<31> const & days_of_month,
size_t day_of_month,
std::bitset<7> const & days_of_week,
size_t day_of_week,
std::bitset<7> const & marked_fields)
{
unsigned int count = 0;
unsigned int maximum = 366;
while (
(!days_of_month.test(day_of_month - Traits::CRON_MIN_DAYS_OF_MONTH) ||
!days_of_week.test(day_of_week - Traits::CRON_MIN_DAYS_OF_WEEK))
&& count++ < maximum)
{
add_to_field(date, cron_field::day_of_month, 1);
day_of_month = date.tm_mday;
day_of_week = date.tm_wday;
reset_all_fields(date, marked_fields);
}
return day_of_month;
}
template <typename Traits>
static bool find_next(cronexpr const & cex,
std::tm& date,
size_t const dot)
{
bool res = true;
std::bitset<7> marked_fields{ 0 };
std::bitset<7> empty_list{ 0 };
unsigned int second = date.tm_sec;
auto updated_second = find_next(
cex.seconds,
date,
Traits::CRON_MIN_SECONDS,
Traits::CRON_MAX_SECONDS,
second,
cron_field::second,
cron_field::minute,
empty_list);
if (second == updated_second)
{
mark_field(marked_fields, cron_field::second);
}
unsigned int minute = date.tm_min;
auto update_minute = find_next(
cex.minutes,
date,
Traits::CRON_MIN_MINUTES,
Traits::CRON_MAX_MINUTES,
minute,
cron_field::minute,
cron_field::hour_of_day,
marked_fields);
if (minute == update_minute)
{
mark_field(marked_fields, cron_field::minute);
}
else
{
res = find_next<Traits>(cex, date, dot);
if (!res) return res;
}
unsigned int hour = date.tm_hour;
auto updated_hour = find_next(
cex.hours,
date,
Traits::CRON_MIN_HOURS,
Traits::CRON_MAX_HOURS,
hour,
cron_field::hour_of_day,
cron_field::day_of_week,
marked_fields);
if (hour == updated_hour)
{
mark_field(marked_fields, cron_field::hour_of_day);
}
else
{
res = find_next<Traits>(cex, date, dot);
if (!res) return res;
}
unsigned int day_of_week = date.tm_wday;
unsigned int day_of_month = date.tm_mday;
auto updated_day_of_month = find_next_day<Traits>(
date,
cex.days_of_month,
day_of_month,
cex.days_of_week,
day_of_week,
marked_fields);
if (day_of_month == updated_day_of_month)
{
mark_field(marked_fields, cron_field::day_of_month);
}
else
{
res = find_next<Traits>(cex, date, dot);
if (!res) return res;
}
unsigned int month = date.tm_mon;
auto updated_month = find_next(
cex.months,
date,
Traits::CRON_MIN_MONTHS,
Traits::CRON_MAX_MONTHS,
month,
cron_field::month,
cron_field::year,
marked_fields);
if (month != updated_month)
{
if (date.tm_year - dot > Traits::CRON_MAX_YEARS_DIFF)
return false;
res = find_next<Traits>(cex, date, dot);
if (!res) return res;
}
return res;
}
}
template <typename Traits>
static cronexpr make_cron(CRONCPP_STRING_VIEW expr)
{
cronexpr cex;
if (expr.empty())
throw bad_cronexpr("Invalid empty cron expression");
auto fields = utils::split(expr, ' ');
fields.erase(
std::remove_if(std::begin(fields), std::end(fields),
[](CRONCPP_STRING_VIEW s) {return s.empty(); }),
std::end(fields));
if (fields.size() != 6)
throw bad_cronexpr("cron expression must have six fields");
detail::set_cron_field(fields[0], cex.seconds, Traits::CRON_MIN_SECONDS, Traits::CRON_MAX_SECONDS);
detail::set_cron_field(fields[1], cex.minutes, Traits::CRON_MIN_MINUTES, Traits::CRON_MAX_MINUTES);
detail::set_cron_field(fields[2], cex.hours, Traits::CRON_MIN_HOURS, Traits::CRON_MAX_HOURS);
detail::set_cron_days_of_week<Traits>(fields[5], cex.days_of_week);
detail::set_cron_days_of_month<Traits>(fields[3], cex.days_of_month);
detail::set_cron_month<Traits>(fields[4], cex.months);
cex.expr = expr;
return cex;
}
template <typename Traits = cron_standard_traits>
static std::tm cron_next(cronexpr const & cex, std::tm date)
{
time_t original = utils::tm_to_time(date);
if (INVALID_TIME == original) return {};
if (!detail::find_next<Traits>(cex, date, date.tm_year))
return {};
time_t calculated = utils::tm_to_time(date);
if (INVALID_TIME == calculated) return {};
if (calculated == original)
{
add_to_field(date, detail::cron_field::second, 1);
if (!detail::find_next<Traits>(cex, date, date.tm_year))
return {};
}
return date;
}
template <typename Traits = cron_standard_traits>
static std::time_t cron_next(cronexpr const & cex, std::time_t const & date)
{
std::tm val;
std::tm* dt = utils::time_to_tm(&date, &val);
if (dt == nullptr) return INVALID_TIME;
time_t original = utils::tm_to_time(*dt);
if (INVALID_TIME == original) return INVALID_TIME;
if(!detail::find_next<Traits>(cex, *dt, dt->tm_year))
return INVALID_TIME;
time_t calculated = utils::tm_to_time(*dt);
if (INVALID_TIME == calculated) return calculated;
if (calculated == original)
{
add_to_field(*dt, detail::cron_field::second, 1);
if(!detail::find_next<Traits>(cex, *dt, dt->tm_year))
return INVALID_TIME;
}
return utils::tm_to_time(*dt);
}
template <typename Traits = cron_standard_traits>
static std::chrono::system_clock::time_point cron_next(cronexpr const & cex, std::chrono::system_clock::time_point const & time_point) {
return std::chrono::system_clock::from_time_t(cron_next<Traits>(cex, std::chrono::system_clock::to_time_t(time_point)));
}
}

13
src/ow_version.h Normal file
View File

@@ -0,0 +1,13 @@
//
// Created by stephane bourque on 2021-12-06.
//
#pragma once
#include <string>
namespace OW_VERSION {
inline static const std::string VERSION{"2.6.0"};
inline static const std::string BUILD{"128"};
inline static const std::string HASH{"3b0f2a0"};
}

View File

@@ -96,40 +96,42 @@ namespace OpenWifi {
void EntityDB::AddVenues(Poco::JSON::Object &Tree, const std::string & Node) { void EntityDB::AddVenues(Poco::JSON::Object &Tree, const std::string & Node) {
ProvObjects::Venue E; ProvObjects::Venue E;
// std::cout << "Adding venue:" << Node << std::endl; // std::cout << "Adding venue:" << Node << std::endl;
StorageService()->VenueDB().GetRecord("id",Node,E); if(StorageService()->VenueDB().GetRecord("id",Node,E)) {
Poco::JSON::Array Venues; Poco::JSON::Array Venues;
for(const auto &i:E.children) { for (const auto &i: E.children) {
Poco::JSON::Object Venue; Poco::JSON::Object Venue;
AddVenues(Venue, i); AddVenues(Venue, i);
Venues.add(Venue); Venues.add(Venue);
}
Tree.set("type", "venue");
Tree.set("name", E.info.name);
Tree.set("uuid", E.info.id);
Tree.set("children", Venues);
} }
Tree.set("type","venue");
Tree.set("name",E.info.name);
Tree.set("uuid",E.info.id);
Tree.set("children",Venues);
} }
void EntityDB::BuildTree(Poco::JSON::Object &Tree, const std::string & Node) { void EntityDB::BuildTree(Poco::JSON::Object &Tree, const std::string & Node) {
ProvObjects::Entity E; ProvObjects::Entity E;
// std::cout << "Adding node:" << Node << std::endl; // std::cout << "Adding node:" << Node << std::endl;
StorageService()->EntityDB().GetRecord("id",Node,E); if(StorageService()->EntityDB().GetRecord("id",Node,E)) {
Poco::JSON::Array Children; Poco::JSON::Array Children;
for(const auto &i:E.children) { for (const auto &i: E.children) {
Poco::JSON::Object Child; Poco::JSON::Object Child;
BuildTree(Child,i); BuildTree(Child, i);
Children.add(Child); Children.add(Child);
}
Poco::JSON::Array Venues;
for (const auto &i: E.venues) {
Poco::JSON::Object Venue;
AddVenues(Venue, i);
Venues.add(Venue);
}
Tree.set("type", "entity");
Tree.set("name", E.info.name);
Tree.set("uuid", E.info.id);
Tree.set("children", Children);
Tree.set("venues", Venues);
} }
Poco::JSON::Array Venues;
for(const auto &i:E.venues) {
Poco::JSON::Object Venue;
AddVenues(Venue, i);
Venues.add(Venue);
}
Tree.set("type","entity");
Tree.set("name",E.info.name);
Tree.set("uuid",E.info.id);
Tree.set("children",Children);
Tree.set("venues", Venues);
} }
void EntityDB::ImportVenues(const Poco::JSON::Object::Ptr &O, const std::string &Parent) { void EntityDB::ImportVenues(const Poco::JSON::Object::Ptr &O, const std::string &Parent) {

View File

@@ -83,12 +83,13 @@ namespace OpenWifi {
InventoryDB::InventoryDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) : InventoryDB::InventoryDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) :
DB(T, "inventory", InventoryDB_Fields, InventoryDB_Indexes, P, L, "inv") {} DB(T, "inventory", InventoryDB_Fields, InventoryDB_Indexes, P, L, "inv") {}
bool InventoryDB::CreateFromConnection( const std::string &SerialNumber, bool InventoryDB::CreateFromConnection( const std::string &SerialNumberRaw,
const std::string &ConnectionInfo, const std::string &ConnectionInfo,
const std::string &DeviceType, const std::string &DeviceType,
const std::string &Locale) { const std::string &Locale) {
ProvObjects::InventoryTag ExistingDevice; ProvObjects::InventoryTag ExistingDevice;
auto SerialNumber = Poco::toLower(SerialNumberRaw);
if(!GetRecord("serialNumber",SerialNumber,ExistingDevice)) { if(!GetRecord("serialNumber",SerialNumber,ExistingDevice)) {
ProvObjects::InventoryTag NewDevice; ProvObjects::InventoryTag NewDevice;
uint64_t Now = OpenWifi::Now(); uint64_t Now = OpenWifi::Now();
@@ -223,7 +224,7 @@ namespace OpenWifi {
ProvObjects::DeviceRules Rules; ProvObjects::DeviceRules Rules;
std::string SerialNumber = Utils::IntToSerialNumber(i); std::string SerialNumber = Utils::IntToSerialNumber(i);
if(EvaluateDeviceSerialNumberRules(SerialNumber,Rules)) { if(EvaluateDeviceSerialNumberRules(SerialNumber,Rules)) {
if(Rules.rrm=="yes") if(Rules.rrm!="no" && Rules.rrm!="inherit")
DeviceList.push_back(SerialNumber); DeviceList.push_back(SerialNumber);
} }
} }

View File

@@ -1,51 +0,0 @@
//
// Created by stephane bourque on 2021-10-28.
//
#include "storage_jobs.h"
#include "framework/OpenWifiTypes.h"
#include "framework/MicroService.h"
namespace OpenWifi {
static ORM::FieldVec JobDB_Fields{
// object info
ORM::Field{"id",64, true},
ORM::Field{"name",ORM::FieldType::FT_TEXT},
ORM::Field{"description",ORM::FieldType::FT_TEXT},
ORM::Field{"type",ORM::FieldType::FT_TEXT},
ORM::Field{"progress",ORM::FieldType::FT_BIGINT},
ORM::Field{"total",ORM::FieldType::FT_BIGINT},
ORM::Field{"parameters",ORM::FieldType::FT_TEXT}
};
static ORM::IndexVec JobDB_Indexes{
{ std::string("job_name_index"),
ORM::IndexEntryVec{
{std::string("name"),
ORM::Indextype::ASC} } }
};
JobDB::JobDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) :
DB(T, "jobs", JobDB_Fields, JobDB_Indexes, P, L, "job") {}
}
template<> void ORM::DB<OpenWifi::JobDBRecordType, OpenWifi::JobRecord>::Convert(const OpenWifi::JobDBRecordType &In, OpenWifi::JobRecord &Out) {
Out.id = In.get<0>();
Out.name = In.get<1>();
Out.description = In.get<2>();
Out.type = In.get<3>();
Out.progress = In.get<4>();
Out.total = In.get<5>();
Out.parameters = OpenWifi::RESTAPI_utils::to_array_of_array_of_object<OpenWifi::Job::Parameter>(In.get<3>());
}
template<> void ORM::DB<OpenWifi::JobDBRecordType, OpenWifi::JobRecord>::Convert(const OpenWifi::JobRecord &In, OpenWifi::JobDBRecordType &Out) {
Out.set<0>(In.id);
Out.set<1>(In.name);
Out.set<2>(In.description);
Out.set<3>(In.type);
Out.set<4>(In.progress);
Out.set<5>(In.total);
Out.set<6>(OpenWifi::RESTAPI_utils::to_string(In.parameters));
}

View File

@@ -1,40 +0,0 @@
//
// Created by stephane bourque on 2021-10-28.
//
#pragma once
#include "framework/orm.h"
#include "JobController.h"
namespace OpenWifi {
typedef Poco::Tuple<
std::string,
std::string,
std::string,
std::string,
uint64_t,
uint64_t,
std::string
> JobDBRecordType;
struct JobRecord {
Types::UUID_t id;
std::string name;
std::string description;
std::string type;
uint64_t progress;
uint64_t total;
Job::ParametersVec parameters;
// void from_string(const std::string &S);
// std::string to_string() const;
};
class JobDB : public ORM::DB<JobDBRecordType, JobRecord> {
public:
JobDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L);
virtual ~JobDB() {};
private:
};
}

View File

@@ -97,7 +97,7 @@ if [ -z ${OWPROV_OVERRIDE+x} ]; then
port="$(echo $hostport | sed -e 's,^.*:,:,g' -e 's,.*:\([0-9]*\).*,\1,g' -e 's,[^0-9],,g')" port="$(echo $hostport | sed -e 's,^.*:,:,g' -e 's,.*:\([0-9]*\).*,\1,g' -e 's,[^0-9],,g')"
path="$(echo $url | grep / | cut -d/ -f2-)" path="$(echo $url | grep / | cut -d/ -f2-)"
export OWPROV=${url} export OWPROV=${url}
echo "Using ${OWPROV}..." echo "Using PROV=${OWPROV}..."
else else
echo "OWPROV endpoint is not found:" echo "OWPROV endpoint is not found:"
jq < ${result_file} jq < ${result_file}
@@ -108,6 +108,33 @@ else
fi fi
} }
setrrm() {
if [ -z ${OWRRM_OVERRIDE+x} ]; then
curl ${FLAGS} -X GET "https://${OWSEC}/api/v1/systemEndpoints" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
rawurl="$(cat ${result_file} | jq -r '.endpoints[] | select( .type == "owrrm" ) | .uri')"
if [[ ! -z "${rawurl}" ]]; then
proto="$(echo $rawurl | grep :// | sed -e's,^\(.*://\).*,\1,g')"
url="$(echo ${rawurl/$proto/})"
user="$(echo $url | grep @ | cut -d@ -f1)"
hostport="$(echo ${url/$user@/} | cut -d/ -f1)"
host="$(echo $hostport | sed -e 's,:.*,,g')"
port="$(echo $hostport | sed -e 's,^.*:,:,g' -e 's,.*:\([0-9]*\).*,\1,g' -e 's,[^0-9],,g')"
path="$(echo $url | grep / | cut -d/ -f2-)"
export OWRRM=${url}
echo "Using RRM=${OWRRM}..."
else
echo "OWRRM endpoint is not found:"
jq < ${result_file}
exit 1
fi
else
export OWRRM=${OWRRM_OVERRIDE}
fi
}
logout() { logout() {
curl ${FLAGS} -X DELETE "https://${OWSEC}/api/v1/oauth2/${token}" \ curl ${FLAGS} -X DELETE "https://${OWSEC}/api/v1/oauth2/${token}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
@@ -499,6 +526,32 @@ listvenues() {
jq < ${result_file} jq < ${result_file}
} }
getvenuedevices() {
curl ${FLAGS} -X GET "https://${OWPROV}/api/v1/venue/$1?getDevices=true&getChildren=true" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${token}" \
-H "Accept: application/json" > ${result_file}
jq < ${result_file}
}
listrrmalgos() {
setrrm
curl ${FLAGS} -X GET "http://${OWRRM}/api/v1/algorithms" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${token}" \
-H "Accept: application/json" > ${result_file}
jq < ${result_file}
}
rrmprovider() {
setrrm
curl ${FLAGS} -X GET "http://${OWRRM}/api/v1/provider" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${token}" \
-H "Accept: application/json" > ${result_file}
jq < ${result_file}
}
shopt -s nocasematch shopt -s nocasematch
case "$1" in case "$1" in
"login") login; echo "You are logged in..." ; logout ;; "login") login; echo "You are logged in..." ; logout ;;
@@ -546,6 +599,9 @@ case "$1" in
"getsignup") login; getsignup $2; logout;; "getsignup") login; getsignup $2; logout;;
"getsubdevs") login; getsubdevs $2; logout;; "getsubdevs") login; getsubdevs $2; logout;;
"listvenues") login; listvenues $2; logout;; "listvenues") login; listvenues $2; logout;;
"getvenuedevices") login; getvenuedevices $2; logout;;
"listrrmalgos") login; listrrmalgos; logout;;
"rrmprovider") login; rrmprovider; logout;;
*) help ;; *) help ;;
esac esac

24
test_scripts/update_objects.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
dst=~/Desktop/Dropbox/clion/last_obj_update
src=~/Desktop/Dropbox/clion
rm -rf ${dst}
mkdir ${dst}
cp ${src}/wlan-cloud-ucentralgw/src/RESTObjects/RESTAPI_GWobjects.* ${dst}/.
cp ${src}/wlan-cloud-ucentralsec/src/RESTObjects/RESTAPI_SecurityObjects.* ${dst}/.
cp ${src}/wlan-cloud-ucentralfms/src/RESTObjects/RESTAPI_FMSObjects.* ${dst}/.
cp ${src}/wlan-cloud-prov/src/RESTObjects/RESTAPI_ProvObjects.* ${dst}/.
cp ${src}/wlan-cloud-analytics/src/RESTObjects/RESTAPI_AnalyticsObjects.* ${dst}/.
cp ${src}/wlan-cloud-certportal/src/RESTObjects/RESTAPI_CertObjects.* ${dst}/.
cp ${src}/wlan-cloud-userportal/src/RESTObjects/RESTAPI_SubObjects.* ${dst}/.
cp ${src}/ucentralsim/src/RESTObjects/RESTAPI_OWLSobjects.* ${dst}/.
cp ${dst}/*.* ${src}/wlan-cloud-ucentralgw/src/RESTObjects/.
cp ${dst}/*.* ${src}/wlan-cloud-ucentralsec/src/RESTObjects/.
cp ${dst}/*.* ${src}/wlan-cloud-ucentralfms/src/RESTObjects/.
cp ${dst}/*.* ${src}/wlan-cloud-prov/src/RESTObjects/.
cp ${dst}/*.* ${src}/wlan-cloud-analytics/src/RESTObjects/.
cp ${dst}/*.* ${src}/wlan-cloud-certportal/src/RESTObjects/.
cp ${dst}/*.* ${src}/wlan-cloud-userportal/src/RESTObjects/.
cp ${dst}/*.* ${src}/ucentralsim/src/RESTObjects/.

View File

@@ -1,4 +1,4 @@
#!/bin/sh #!/bin/bash
# wait-for-postgres.sh # wait-for-postgres.sh
set -e set -e
@@ -20,7 +20,7 @@ if [ "$1" = '/openwifi/owprov' -a "$(id -u)" = '0' ]; then
if [ "$RUN_CHOWN" = 'true' ]; then if [ "$RUN_CHOWN" = 'true' ]; then
chown -R "$OWPROV_USER": "$OWPROV_ROOT" "$OWPROV_CONFIG" chown -R "$OWPROV_USER": "$OWPROV_ROOT" "$OWPROV_CONFIG"
fi fi
exec su-exec "$OWPROV_USER" "$@" exec gosu "$OWPROV_USER" "$@"
fi fi
exec "$@" exec "$@"