Compare commits

..

1 Commits

Author SHA1 Message Date
oblom0v
5f7b13a401 Remove duplicate ucentralgw-ui entry and adapt Docker Compose CI job to microservice structure
Adapt new config file changes

Fix script name

Add working-directory

Run docker-compose exec in the background

Test Github actions working-directory behaviour

Revert previous test

Change shebang path

Add some debug information to workflow

Disable pseudo-tty allocation

Fix variable name
2021-07-14 13:08:38 +02:00
208 changed files with 10722 additions and 18003 deletions

View File

@@ -7,12 +7,11 @@ on:
- '**.md'
branches:
- master
- 'release/*'
tags:
- 'v*'
- dev-microservice
pull_request:
branches:
- master
- dev-microservice
defaults:
run:
@@ -27,97 +26,81 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Build Docker image
run: docker build -t wlan-cloud-owgw:${{ github.sha }} .
- name: build Docker image
run: docker build -t wlan-cloud-ucentralgw:${{ github.sha }} .
- name: Tag Docker image
run: |
TAGS="${{ github.sha }}"
if [[ ${GITHUB_REF} == "refs/heads/"* ]]
then
CURRENT_TAG=$(echo ${GITHUB_REF#refs/heads/} | tr '/' '-')
TAGS="$TAGS $CURRENT_TAG"
else
if [[ ${GITHUB_REF} == "refs/tags/"* ]]
then
CURRENT_TAG=$(echo ${GITHUB_REF#refs/tags/} | tr '/' '-')
TAGS="$TAGS $CURRENT_TAG"
else # PR build
CURRENT_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
TAGS="$TAGS $CURRENT_TAG"
fi
fi
echo "Result tags: $TAGS"
for tag in $TAGS; do
docker tag wlan-cloud-owgw:${{ github.sha }} ${{ env.DOCKER_REGISTRY_URL }}/owgw:$tag
done
- name: Log into Docker registry
if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/master'
- name: log into Docker registry
uses: docker/login-action@v1
with:
registry: ${{ env.DOCKER_REGISTRY_URL }}
username: ${{ env.DOCKER_REGISTRY_USERNAME }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
- name: Push Docker images
if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/master'
- name: push Docker image
run: |
docker images | grep ${{ env.DOCKER_REGISTRY_URL }}/owgw | awk -F ' ' '{print $1":"$2}' | xargs -I {} docker push {}
TAGS="${{ github.sha }}"
if [ ${GITHUB_REF} == "refs/heads/master" ]
then
TAGS="$TAGS ${GITHUB_REF#refs/heads/}"
else # PR build
CURRENT_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
TAGS="$TAGS $CURRENT_TAG"
fi
echo "Pushing tags $TAGS"
for tag in $TAGS; do
docker tag wlan-cloud-ucentralgw:${{ github.sha }} ${{ env.DOCKER_REGISTRY_URL }}/ucentralgw:$tag
docker push ${{ env.DOCKER_REGISTRY_URL }}/ucentralgw:$tag
done
docker-compose:
if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/master'
runs-on: ubuntu-20.04
needs: docker
steps:
- name: Check out wlan-cloud-ucentral-deploy repository
- name: Check out repository
uses: actions/checkout@v2
with:
repository: Telecominfraproject/wlan-cloud-ucentral-deploy
path: wlan-cloud-ucentral-deploy
- name: Instantiate Docker Compose deployment
working-directory: ./wlan-cloud-ucentral-deploy/docker-compose
working-directory: ./docker-compose
env:
OWGW_TAG: ${{ github.sha }}
UCENTRALGW_TAG: ${{ github.sha }}
run: |
docker-compose up -d
- name: Wait for OWSec to be alive and kicking
- name: Wait for uCentralSec to be alive and kicking
run: |
n=0
until [ "$n" -ge 3 ]
do
curl -s 127.0.0.1:16102 && break
n=$((n+1))
if [ "$n" -eq 3]; then
n=$((n+1))
if [ "$n" -eq 3]; then
exit 1
else
sleep 3
fi
done
- name: Check out wlan-cloud-ucentralgw repository
uses: actions/checkout@v2
with:
path: wlan-cloud-ucentralgw
- name: Add self-signed certificates to system trust store of containers
working-directory: ./docker-compose
run: |
./add-ca-cert.sh
- name: Check functionality of microservices
env:
OWSEC: "openwifi.wlan.local:16001"
FLAGS: "-s --cacert ./wlan-cloud-ucentral-deploy/docker-compose/certs/restapi-ca.pem --resolve openwifi.wlan.local:16001:127.0.0.1"
UCENTRALSEC: "ucentral.wlan.local:16001"
FLAGS: "-s --cacert docker-compose/certs/restapi-ca.pem --resolve ucentral.wlan.local:16001:127.0.0.1"
run: |
./wlan-cloud-ucentralgw/test_scripts/curl/cli listdevices
./test_scripts/curl/cli listdevices
- name: Display information about running containers and log ucentralgw output
working-directory: ./wlan-cloud-ucentral-deploy/docker-compose
working-directory: ./docker-compose
if: always()
run: |
docker-compose ps -a
docker-compose logs
docker-compose logs
# disable until repo is public
#- name: export Docker image

View File

@@ -4,6 +4,7 @@ on:
pull_request:
branches:
- master
- dev-microservice
types: [ closed ]
defaults:
@@ -17,4 +18,4 @@ jobs:
- name: Cleanup Docker image with PR branch tag
run: |
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/owgw/$PR_BRANCH_TAG"
curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/ucentralgw/$PR_BRANCH_TAG"

3
.gitignore vendored
View File

@@ -25,6 +25,3 @@ _deps
test_scripts/curl/token.json
.vscode/c_cpp_properties.json
test_scripts/curl/result.json
*.swp
helm/charts/*
!helm/charts/.gitkeep

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(owgw VERSION 2.4.0)
project(ucentralgw VERSION 0.4.0)
set(CMAKE_CXX_STANDARD 17)
@@ -29,20 +29,7 @@ else()
set(BUILD_NUM 1)
file(WRITE build ${BUILD_NUM})
endif()
find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --tags
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_RESULT
OUTPUT_VARIABLE GIT_HASH)
if(NOT GIT_RESULT EQUAL "0")
message(FATAL_ERROR "git describe --always --tags failed with ${GIT_RESULT}")
endif()
string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}")
endif()
add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT)
add_definitions(-DAPP_VERSION="${CMAKE_PROJECT_VERSION}" -DBUILD_NUMBER="${BUILD_NUM}")
add_definitions(-DTIP_GATEWAY_SERVICE="1")
set(Boost_USE_STATIC_LIBS OFF)
@@ -51,8 +38,6 @@ set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost REQUIRED system)
find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED)
find_package(nlohmann_json REQUIRED)
find_package(nlohmann_json_schema_validator REQUIRED)
if(SMALL_BUILD)
find_package(Poco REQUIRED COMPONENTS Crypto JWT Net Util NetSSL Data DataSQLite)
@@ -60,85 +45,67 @@ else()
find_package(CppKafka REQUIRED)
find_package(PostgreSQL REQUIRED)
find_package(MySQL REQUIRED)
find_package(Poco REQUIRED COMPONENTS JSON Crypto JWT Net Util NetSSL Data DataSQLite DataPostgreSQL DataMySQL)
find_package(ODBC REQUIRED)
find_package(Poco REQUIRED COMPONENTS JSON Crypto JWT Net Util NetSSL Data DataSQLite DataPostgreSQL DataMySQL DataODBC)
endif()
include_directories(/usr/local/include /usr/local/opt/openssl/include src include/kafka /usr/local/opt/mysql-client/include)
configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY)
add_executable( owgw
build
src/ow_version.h.in
src/framework/CountryCodes.h
src/framework/KafkaTopics.h
src/framework/MicroService.h
src/framework/OpenWifiTypes.h
src/framework/orm.h
src/framework/RESTAPI_errors.h
src/framework/RESTAPI_protocol.h
src/framework/StorageClass.h
src/framework/uCentral_Protocol.h
src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp
src/RESTObjects/RESTAPI_ProvObjects.cpp src/RESTObjects/RESTAPI_ProvObjects.h
src/RESTObjects/RESTAPI_GWobjects.h src/RESTObjects/RESTAPI_GWobjects.cpp
src/RESTObjects/RESTAPI_FMSObjects.h src/RESTObjects/RESTAPI_FMSObjects.cpp
src/RESTAPI/RESTAPI_devices_handler.cpp src/RESTAPI/RESTAPI_devices_handler.h
src/RESTAPI/RESTAPI_device_handler.cpp src/RESTAPI/RESTAPI_device_handler.h
src/RESTAPI/RESTAPI_device_commandHandler.cpp src/RESTAPI/RESTAPI_device_commandHandler.h
src/RESTAPI/RESTAPI_default_configuration.cpp
src/RESTAPI/RESTAPI_default_configuration.h src/RESTAPI/RESTAPI_default_configurations.cpp src/RESTAPI/RESTAPI_default_configurations.h
src/RESTAPI/RESTAPI_commands.cpp src/RESTAPI/RESTAPI_commands.h
src/RESTAPI/RESTAPI_command.cpp src/RESTAPI/RESTAPI_command.h
src/RESTAPI/RESTAPI_file.cpp src/RESTAPI/RESTAPI_file.h
src/RESTAPI/RESTAPI_blacklist.cpp src/RESTAPI/RESTAPI_blacklist.h
src/RESTAPI/RESTAPI_ouis.cpp src/RESTAPI/RESTAPI_ouis.h
src/RESTAPI/RESTAPI_blacklist_list.cpp src/RESTAPI/RESTAPI_blacklist_list.h
src/RESTAPI/RESTAPI_capabilities_handler.cpp src/RESTAPI/RESTAPI_capabilities_handler.h
src/RESTAPI/RESTAPI_RPC.cpp src/RESTAPI/RESTAPI_RPC.h
src/RESTAPI/RESTAPI_deviceDashboardHandler.cpp src/RESTAPI/RESTAPI_deviceDashboardHandler.h
src/RESTAPI/RESTAPI_TelemetryWebSocket.cpp src/RESTAPI/RESTAPI_TelemetryWebSocket.h
src/RESTAPI/RESTAPI_webSocketServer.cpp src/RESTAPI/RESTAPI_webSocketServer.h
src/storage/storage_blacklist.cpp src/storage/storage_tables.cpp src/storage/storage_logs.cpp
src/storage/storage_command.cpp src/storage/storage_healthcheck.cpp src/storage/storage_statistics.cpp
src/storage/storage_device.cpp src/storage/storage_capabilities.cpp src/storage/storage_defconfig.cpp
src/storage/storage_tables.cpp
src/APIServers.cpp
src/Daemon.cpp src/Daemon.h
src/StateProcessor.cpp src/StateProcessor.h
src/storage/storage_lifetime_stats.cpp
src/WebSocketServer.cpp src/WebSocketServer.h
src/StorageService.cpp src/StorageService.h
src/DeviceRegistry.cpp src/DeviceRegistry.h
src/CommandManager.cpp src/CommandManager.h
src/CentralConfig.cpp src/CentralConfig.h
src/FileUploader.cpp src/FileUploader.h
src/OUIServer.cpp src/OUIServer.h
src/StorageArchiver.cpp src/StorageArchiver.h
src/Dashboard.cpp src/Dashboard.h
src/SerialNumberCache.cpp src/SerialNumberCache.h
src/TelemetryStream.cpp src/TelemetryStream.h
src/framework/ConfigurationValidator.cpp src/framework/ConfigurationValidator.h
src/ConfigurationCache.cpp src/ConfigurationCache.h
)
add_executable( ucentralgw
build
src/Daemon.cpp src/Daemon.h
src/RESTAPI_server.cpp src/RESTAPI_server.h
src/WebSocketServer.cpp src/WebSocketServer.h
src/SubSystemServer.cpp src/SubSystemServer.h
src/StorageService.cpp src/StorageService.h
src/RESTAPI_SecurityObjects.cpp src/RESTAPI_SecurityObjects.h
src/DeviceRegistry.cpp src/DeviceRegistry.h
src/RESTAPI_devices_handler.cpp src/RESTAPI_devices_handler.h
src/RESTAPI_device_handler.cpp src/RESTAPI_device_handler.h
src/RESTAPI_handler.cpp src/RESTAPI_handler.h
src/RESTAPI_device_commandHandler.cpp src/RESTAPI_device_commandHandler.h
src/RESTAPI_GWobjects.h src/RESTAPI_GWobjects.cpp
src/CentralConfig.cpp src/CentralConfig.h
src/RESTAPI_default_configuration.cpp
src/RESTAPI_InternalServer.cpp src/RESTAPI_InternalServer.h
src/RESTAPI_default_configuration.h src/RESTAPI_default_configurations.cpp src/RESTAPI_default_configurations.h
src/RESTAPI_commands.cpp src/RESTAPI_commands.h
src/CommandManager.cpp src/CommandManager.h
src/RESTAPI_command.cpp src/RESTAPI_command.h
src/FileUploader.cpp src/FileUploader.h
src/RESTAPI_file.cpp src/RESTAPI_file.h
src/CommandChannel.cpp src/CommandChannel.h
src/RESTAPI_system_command.cpp src/RESTAPI_system_command.h
src/RESTAPI_BlackList.cpp src/RESTAPI_BlackList.h
src/Utils.h src/Utils.cpp src/storage_blacklist.cpp
src/storage_command.cpp src/storage_healthcheck.cpp src/storage_statistics.cpp src/storage_logs.cpp
src/storage_device.cpp src/storage_capabilities.cpp src/storage_defconfig.cpp src/storage_sqlite.cpp
src/storage_mysql.cpp src/storage_pgql.cpp src/storage_odbc.cpp src/storage_tables.cpp src/RESTAPI_callback.cpp
src/RESTAPI_callback.h src/CallbackManager.cpp src/CallbackManager.h
src/StateProcessor.cpp src/StateProcessor.h
src/storage_lifetime_stats.cpp src/uCentralProtocol.h src/RESTAPI_protocol.h
src/ALBHealthCheckServer.h src/Kafka_topics.h src/uCentralTypes.h
src/OUIServer.cpp src/OUIServer.h
src/RESTAPI_ouis.cpp src/RESTAPI_ouis.h
src/MicroService.cpp src/MicroService.h
src/RESTAPI_RPC.cpp src/RESTAPI_RPC.h src/AuthClient.cpp src/AuthClient.h src/OpenAPIRequest.cpp src/OpenAPIRequest.h src/RESTAPI_utils.h src/RESTAPI_utils.cpp src/StorageArchiver.cpp src/StorageArchiver.h)
if(NOT SMALL_BUILD)
target_sources(ucentralgw PUBLIC src/KafkaManager.cpp src/KafkaManager.h)
endif()
INSTALL(TARGETS owgw
INSTALL(TARGETS ucentralgw
RUNTIME DESTINATION /usr/bin
)
target_link_libraries(owgw PUBLIC
target_link_libraries(ucentralgw PUBLIC
${Poco_LIBRARIES} ${Boost_LIBRARIES} ${ZLIB_LIBRARIES})
if(NOT SMALL_BUILD)
target_link_libraries(owgw PUBLIC
${MySQL_LIBRARIES} ${ZLIB_LIBRARIES}
CppKafka::cppkafka
nlohmann_json_schema_validator
target_link_libraries(ucentralgw PUBLIC
${MySQL_LIBRARIES} ${ODBC_LIBRARIES} ${ZLIB_LIBRARIES}
CppKafka::cppkafka
)
if(UNIX AND NOT APPLE)
target_link_libraries(owgw PUBLIC PocoJSON)
target_link_libraries(ucentralgw PUBLIC PocoJSON)
endif()
endif()

View File

@@ -1,18 +1,16 @@
FROM alpine AS builder
RUN apk add --update --no-cache \
openssl openssh \
ncurses-libs \
bash util-linux coreutils curl \
make cmake gcc g++ libstdc++ libgcc git zlib-dev yaml-cpp-dev \
openssl-dev boost-dev unixodbc-dev postgresql-dev mariadb-dev \
apache2-utils yaml-dev apr-util-dev \
lua-dev librdkafka-dev \
nlohmann-json
RUN apk update && \
apk add --no-cache openssl openssh && \
apk add --no-cache ncurses-libs && \
apk add --no-cache bash util-linux coreutils curl && \
apk add --no-cache make cmake gcc g++ libstdc++ libgcc git zlib-dev yaml-cpp-dev && \
apk add --no-cache openssl-dev boost-dev unixodbc-dev postgresql-dev mariadb-dev && \
apk add --no-cache apache2-utils yaml-dev apr-util-dev && \
apk add --no-cache lua-dev librdkafka-dev
RUN git clone https://github.com/stephb9959/poco /poco
RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator
WORKDIR /cppkafka
RUN mkdir cmake-build
@@ -28,51 +26,30 @@ RUN cmake ..
RUN cmake --build . --config Release -j8
RUN cmake --build . --target install
WORKDIR /json-schema-validator
RUN mkdir cmake-build
WORKDIR cmake-build
RUN cmake ..
RUN make
RUN make install
ADD CMakeLists.txt /ucentralgw/
ADD cmake /ucentralgw/cmake
ADD src /ucentralgw/src
ADD CMakeLists.txt build /owgw/
ADD cmake /owgw/cmake
ADD src /owgw/src
ADD .git /owgw/.git
WORKDIR /owgw
WORKDIR /ucentralgw
RUN mkdir cmake-build
WORKDIR /owgw/cmake-build
WORKDIR /ucentralgw/cmake-build
RUN cmake ..
RUN cmake --build . --config Release -j8
FROM alpine
ENV OWGW_USER=owgw \
OWGW_ROOT=/owgw-data \
OWGW_CONFIG=/owgw-data
RUN mkdir /ucentral
RUN mkdir /ucentralgw-data
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc
RUN addgroup -S "$OWGW_USER" && \
adduser -S -G "$OWGW_USER" "$OWGW_USER"
RUN mkdir /openwifi
RUN mkdir -p "$OWGW_ROOT" "$OWGW_CONFIG" && \
chown "$OWGW_USER": "$OWGW_ROOT" "$OWGW_CONFIG"
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec gettext ca-certificates bash jq curl postgresql-client
COPY --from=builder /owgw/cmake-build/owgw /openwifi/owgw
COPY --from=builder /ucentralgw/cmake-build/ucentralgw /ucentral/ucentralgw
COPY --from=builder /cppkafka/cmake-build/src/lib/* /lib/
COPY --from=builder /poco/cmake-build/lib/* /lib/
COPY owgw.properties.tmpl /
COPY docker-entrypoint.sh /
COPY wait-for-postgres.sh /
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
EXPOSE 15002
EXPOSE 16002
EXPOSE 16003
EXPOSE 17002
EXPOSE 16102
COPY readiness_check /readiness_check
EXPOSE 15002 16002 16003 17002 16102
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/openwifi/owgw"]
ENTRYPOINT /ucentral/ucentralgw

View File

@@ -2,7 +2,7 @@
This document will describe how the API is built and how to use it.
## Where is the OpenAPI.
This uses OpenAPI definition 3.0 and can be found [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/owgw.yaml).
This uses OpenAPI definition 3.0 and can be found [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/ucentral.yaml).
All endpoints begin with `/api/v1`.
## The flow

View File

@@ -155,22 +155,6 @@ which version it is running. The Controller may decide to send the device a newe
}
```
#### Recovery Event
Device may decide it has to do into recovery mode. This event should be used.
```
{ "jsonrpc" : "2.0" ,
"method" : "recovery" ,
"params" : {
"serial" : <serial number> ,
"uuid" : <the UUID of the configuration that generated the crash log>,
"firmware: <the string describing the current firmware>,
"reboot" : true/false (shoudld the device be instructed to reboot after loggin the information),
"loglines" : [ an array of strings representing the logs from the log file ]
}
}
```
### Controller commands
Most controller commands include a `when` member. This is a UTC clock time asking the AP
to perform the command at that time. This is a suggestion only. The AP may ignore this
@@ -534,48 +518,6 @@ The device should answer:
}
```
#### Controller requesting telemetry stream information
Controller sends this command when it needs the device to telemetry streaming.
```
{ "jsonrpc" : "2.0" ,
"method" : "telemetry" ,
"params" : {
"serial" : <serial number> ,
"interval" : 0-60, # number of seconds for polling information. 0 means to shutdown the stream
"types" : [ "dhcp", "rrm"], <this must be an array: array of 1 or 2 elements, right now only "rrm" and "dhcp" are supported
},
"id" : <some number>
}
```
The device should answer:
```
{ "jsonrpc" : "2.0" ,
"result" : {
"serial" : <serial number> ,
"status" : {
"error" : 0 or an error number,
"text" : <description of the error or success>
}
},
"id" : <same number>
}
```
When the interval is greater than 0, the gateway will start to receive messages
```
{ "jsonrpc" : "2.0" ,
"method" : "telemetry" ,
"params" : {
"serial" : <serial number> ,
"data" : <A JSON document describing the information coming from the device>
}
}
```
The device will stop sending data after 30 minutes or if it receives a `telemetry` command with an interval of 0.
#### Controller requesting an `rtty` session
Controller sends this command an administrator requests to start an `rtty` session with the AP.
```

148
README.md
View File

@@ -26,9 +26,9 @@ Poco may take several minutes depending on the platform you are building on.
### Ubuntu
These instructions have proven to work on Ubuntu 20.4.
```
sudo apt install git cmake g++ libssl-dev libmariadb-dev
sudo apt install git cmake g++ libssl-dev libmariabd-dev unixodbc-dev
sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev
sudo apt install librdkafka-dev libmysqlclient-dev default-libmysqlclient-dev
sudo apt install librdkafka-dev liblua5.3-dev
git clone https://github.com/stephb9959/poco
cd poco
@@ -153,8 +153,8 @@ cmake -DSMALL_BUILD=1 ..
make
```
### After completing the build
After completing the build, you can remove the Poco source as it is no longer needed.
### After the build step is completed
Once your build is done. You can remove the Poco source as it is no longer needed.
#### Expected directory layout
From the directory where your cloned source is, you will need to create the `certs`, `logs`, and `uploads` directories.
@@ -179,7 +179,7 @@ You should now have the following:
+-- test_scripts
+-- openapi
+-- uploads
+-- owgw.properties
+-- ucentralgw.properties
```
### Certificates
@@ -218,15 +218,15 @@ document. Once you have these files, you need to renamed them `restapi-key.pem`,
in your browner
#### Configuration
The configuration for this service is kept in a properties file. This file is called `owgw.properties` and you can
see the latest version [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/owgw.properties). The file will be loaded from
the directory set by the environment variable `UCENTRALGW_CONFIG`. To use environment variables in the configuration,
The configuration for this service is kept in a properties file. This file is called `ucentralgw.properties` and you can
see the latest version [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/ucentralgw.properties). The file will be loaded from
the directory set by the environment variable `UCENTRAL_CONFIG`. To use environment variables in the configuration,
you must use `$<varname>`. Only `path names` support the use of environment variables. The sample configuration requires very
little changes if you keep the suggested directory structure. For the sample configuration to work, you need to define 2
environment variables.
```
export OWGW_ROOT=`pwd`
export UCENTRALGW_CONFIG=`pwd`
export UCENTRAL_ROOT=`pwd`
export UCENTRAL_CONFIG=`pwd`
```
If you current working directory is the root of the project, this will set the variables properly. Otherwise, you can set the variables
to point to wherever is necessary.
@@ -234,7 +234,7 @@ to point to wherever is necessary.
##### Important config entries
###### This is the logging directory
```
logging.channels.c2.path = $OWGW_ROOT/logs/sample.log
logging.channels.c2.path = $UCENTRAL_ROOT/logs/sample.log
```
###### This is the type of storage in use
@@ -244,23 +244,23 @@ storage.type = sqlite
###### Autoprovisioning settings
```asm
openwifi.autoprovisioning = true
openwifi.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
openwifi.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
openwifi.devicetypes.2 = IOT:esp32
ucentral.autoprovisioning = true
ucentral.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
ucentral.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
ucentral.devicetypes.2 = IOT:esp32
```
###### This is the RESTAPI endpoint
```asm
openwifi.restapi.host.0.backlog = 100
openwifi.restapi.host.0.security = relaxed
openwifi.restapi.host.0.rootca = $OWGW_ROOT/certs/restapi-ca.pem
openwifi.restapi.host.0.address = *
openwifi.restapi.host.0.port = 16002
openwifi.restapi.host.0.cert = $OWGW_ROOT/certs/restapi-cert.pem
openwifi.restapi.host.0.key = $OWGW_ROOT/certs/restapi-key.pem
openwifi.restapi.host.0.key.password = mypassword
ucentral.restapi.host.0.backlog = 100
ucentral.restapi.host.0.security = relaxed
ucentral.restapi.host.0.rootca = $UCENTRAL_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address = *
ucentral.restapi.host.0.port = 16002
ucentral.restapi.host.0.cert = $UCENTRAL_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key = $UCENTRAL_ROOT/certs/restapi-key.pem
ucentral.restapi.host.0.key.password = mypassword
```
##### This is the end point for the devices to connect with
@@ -309,12 +309,12 @@ You will need to get the `cert.pem` and `key.pem` from Digicert. The rest is her
```asm
ucentral.websocket.host.0.backlog = 500
ucentral.websocket.host.0.rootca = $OWGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer = $OWGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert = $OWGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key = $OWGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas = $OWGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas = $OWGW_ROOT/certs/cas
ucentral.websocket.host.0.rootca = $UCENTRAL_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer = $UCENTRAL_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert = $UCENTRAL_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key = $UCENTRAL_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas = $UCENTRAL_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas = $UCENTRAL_ROOT/certs/cas
ucentral.websocket.host.0.address = *
ucentral.websocket.host.0.port = 15002
ucentral.websocket.host.0.security = strict
@@ -324,17 +324,17 @@ ucentral.websocket.maxreactors = 20
###### This is the end point for the devices when uploading files
```asm
openwifi.fileuploader.host.0.backlog = 100
openwifi.fileuploader.host.0.rootca = $OWGW_ROOT/certs/restapi-ca.pem
openwifi.fileuploader.host.0.security = relaxed
openwifi.fileuploader.host.0.address = *
openwifi.fileuploader.host.0.name = 192.168.1.176
openwifi.fileuploader.host.0.port = 16003
openwifi.fileuploader.host.0.cert = $OWGW_ROOT/certs/restapi-cert.pem
openwifi.fileuploader.host.0.key = $OWGW_ROOT/certs/restapi-key.pem
openwifi.fileuploader.host.0.key.password = mypassword
openwifi.fileuploader.path = $OWGW_ROOT/uploads
openwifi.fileuploader.maxsize = 10000
ucentral.fileuploader.host.0.backlog = 100
ucentral.fileuploader.host.0.rootca = $UCENTRAL_ROOT/certs/restapi-ca.pem
ucentral.fileuploader.host.0.security = relaxed
ucentral.fileuploader.host.0.address = *
ucentral.fileuploader.host.0.name = 192.168.1.176
ucentral.fileuploader.host.0.port = 16003
ucentral.fileuploader.host.0.cert = $UCENTRAL_ROOT/certs/restapi-cert.pem
ucentral.fileuploader.host.0.key = $UCENTRAL_ROOT/certs/restapi-key.pem
ucentral.fileuploader.host.0.key.password = mypassword
ucentral.fileuploader.path = $UCENTRAL_ROOT/uploads
ucentral.fileuploader.maxsize = 10000
```
###### host.0.address entries
@@ -343,7 +343,7 @@ the `*`. Using the `*` means all interfaces will be able to accept connections.
by changing the `0` to another index. You need to repeat the whole configuration block for each index. Indexes must be sequential
start at `0`.
###### openwifi.fileuploader.host.0.name
###### ucentral.fileuploader.host.0.name
This must point to the IP or FQDN of your uCentralGW.
#### Running the gateway
@@ -369,7 +369,7 @@ can be any of the keys you are already using. You must keep that keep secret and
this is the entry
```asm
openwifi.service.key = $OWGW_ROOT/certs/websocket-key.pem
ucentral.service.key = $UCENTRAL_ROOT/certs/websocket-key.pem
```
#### Command line options
@@ -391,7 +391,7 @@ A uCentral gateway implementation for TIP.
```
##### file
This allows you to point to another file without specifying the UCENTRALGW_CONFIG variable. The file name must end in `.properties`.
This allows you to point to another file without specifying the UCENTRAL_CONFIG variable. The file name must end in `.properties`.
##### daemon
Run this as a UNIX service
##### pidfile
@@ -440,9 +440,9 @@ then
exit 1
fi
if [[ ! -f owgw.properties ]]
if [[ ! -f ucentralgw.properties ]]
then
echo "Configuration file owgw.properties is missing in the current directory"
echo "Configuration file ucentralgw.properties is missing in the current directory"
exit 2
fi
@@ -452,15 +452,15 @@ docker run -d -p 15002:15002 \
--init \
--volume="$PWD:/ucentral-data" \
-e UCENTRAL_ROOT="/ucentral-data" \
-e UCENTRALGW_CONFIG="/ucentral-data" \
-e UCENTRAL_CONFIG="/ucentral-data" \
--name="ucentralgw" $DOCKER_NAME
```
Create yourself a directory and copy that script which you can also get from [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/docker_run.sh).
You must have the basic configuration file copied in the directory. This file must be called `owgw.properties`. You can bring your own or
copy it from [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/owgw.properties). Please look at [this](#certificates-with-docker) to have the right
certificates. You need to make sure that the names match the content of the `owgw.properties`
You must have the basic configuration file copied in the directory. This file must be called `ucentralgw.properties`. You can bring your own or
copy it from [here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/ucentralgw.properties). Please look at [this](#certificates-with-docker) to have the right
certificates. You need to make sure that the names match the content of the `ucentralgw.properties`
file. Once all this is done, you can simply run `docker_run.sh`.
#### Docker installation directory layout
@@ -472,15 +472,15 @@ Run-time root
----- certs (same as above)
+---- logs (dir)
+---- uploads (dir)
+---- owgw.properties (file)
+---- ucentralgw.properties (file)
```
#### `owgw.properties` for Docker
#### `ucentralgw.properties` for Docker
If you use the pre-made configuration file, and you follow the directory layout, the only line you must change
is the following line:
```asm
openwifi.fileuploader.host.0.name = 192.168.1.176
ucentral.fileuploader.host.0.name = 192.168.1.176
```
This line should reflect the IP of your gateway or its FQDN. You must make sure that this name or IP is accessible
@@ -491,45 +491,63 @@ Please refer to the `certs` directory from the sections above.
#### Configuration with Docker
The configuration for this service is kept in a properties file. Currently, this configuration file must be kept in the
current directory of uCentral or one level up. This file is called `owgw.properties` and you can see the latest version
[here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/owgw.properties). The file will be loaded from
the directory set by the environment variable `UCENTRALGW_CONFIG`. To use environment variables in the configuration,
current directory of uCentral or one level up. This file is called `ucentralgw.properties` and you can see the latest version
[here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/ucentralgw.properties). The file will be loaded from
the directory set by the environment variable `UCENTRAL_CONFIG`. To use environment variables in the configuration,
you must use `$<varname>`. The path for the logs for the service must exist prior to starting the
service. The path is defined under `logging.channels.c2.path`. Only `path names` support the use of
environment variables. Here is a sample configuration:
### Docker Compose
The repository also contains a Docker Compose file, which you can use to instantiate a complete deployment of the uCentral microservices and related components for local development purposes. To spin up a local development environment:
1. Switch into the project directory with `cd docker-compose/`.
2. This repository contains a gateway certificate signed by TIP and a self-signed certificate for the REST API and other components which are used by default in the Compose deployment. The certificates are valid for the `*.wlan.local` domain and the Docker Compose uCentral microservice configs use `ucentral.wlan.local` as a hostname, so make sure you add an entry in your hosts file (or in your local DNS solution) which points to `127.0.0.1`.
3. If you have your own certificates and want to use the deployment for anything other than local development copy your certs into the `certs/` directory and reference them in the appropriate sections of the microservice configuration files. Make sure to also adapt the sections which reference the hostname. For more information on certificates please see the [certificates section](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw#certificates) of this README and/or [CERTIFICATES.md](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/CERTIFICATES.md).
4. Docker Compose pulls the microservice images from the JFrog repository. If you want to change the image tag or some of the image versions which are used for the other services, have a look into the `.env` file. You'll also find service specific `.env` files in this directory. Edit them if you want to change database passwords (highly recommended!) or other configuration data. Don't forget to adapt your changes in the application configuration files.
5. Open `docker-compose/ucentralgw-data/ucentral.properties` to change [authentication data](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw#default-username-and-password) for uCentralGW (again highly recommended!).
6. Spin up the deployment with `docker-compose up -d`.
7. Navigate to the UI which listens to `127.0.0.1` and login with your uCentralGW authentication data.
8. To use the [curl test script](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/TEST_CURL.md) to talk to the API set the following environment variables:
```
export UCENTRALSEC="ucentral.wlan.local:16001"
export FLAGS="-s --cacert docker-compose/ucentral-data/certs/restapi-ca.pem"
```
The `--cacert` option is necessary since the REST API certificates are self-signed. Omit the option if you provide your own signed certificates.
PS: The Docker Compose deployment creates five local volumes to persist mostly database data and data for Zookeeper and Kafka. If you want re-create the deployment and remove all persistent application and database data just delete the volumes with `docker volume rm $(docker volume ls -qf name=ucentral)` after you stopped the services with `docker-compose down`.
## uCentral communication protocol
The communication protocol between the device and the controller is detailed in this [document](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/PROTOCOL.md).
## OpenAPI
The service supports an OpenAPI REST based interface for management. You can find the [definition here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/owgw.yaml).
The service supports an OpenAPI REST based interface for management. You can find the [definition here](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/openapi/ucentral/ucentral.yaml).
And here is [how to use it](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/OPENAPI.md)
## Using the API
In the `test_scripts` directory, you will find a series of scripts that will show you how to use the API
with [curl](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/CLI.md)
with [curl](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/TEST_CURL.md)
or [python](https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/main/TEST_PYTHON.md).
More scripts will be added in the future.
## Firewall Considerations
- The protocol uses TCP port 15002 between the devices and the gateway. This port must be opened.
- Devices use the TCP port 16003 to upload files. This port is configurable in the `owgw.properties` file. Look for `openwifi.fileuploader.host.0.port`.
- The RESTAPI is accessed through TCP port 16002 by default. This port is configurable in the `owgw.properties` file. Look for the entry `openwifi.restapi.host.0.port`.
- Devices use the TCP port 16003 to upload files. This port is configurable in the `ucentralgw.properties` file. Look for `ucentral.fileuploader.host.0.port`.
- The RESTAPI is accessed through TCP port 16002 by default. This port is configurable in the `ucentralgw.properties` file. Look for the entry `ucentral.restapi.host.0.port`.
## Kafka integration
So what about Kafka? Well, the gateway has basic integration with Kafka. It is turned off by default, to turn it on, in the configuration:
```asm
openwifi.kafka.enable = false
openwifi.kafka.brokerlist = 127.0.0.1:9092
openwifi.kafka.commit = false
openwifi.kafka.queue.buffering.max.ms = 50
ucentral.kafka.enable = false
ucentral.kafka.brokerlist = 127.0.0.1:9092
ucentral.kafka.commit = false
ucentral.kafka.queue.buffering.max.ms = 50
```
#### `openwifi.kafka.enable`
#### `ucentral.kafka.enable`
Kind of obvious but hey, set `true` or `false`. Default is `false`
#### `openwifi.kafka.brokerlist`
#### `ucentral.kafka.brokerlist`
This is a comma separator list of the brokers in your `kafka` deployment.
#### Kafka topics

View File

@@ -82,9 +82,6 @@ Do wifiscan for a device.
- `serial`: device serial number
- `verbose`: verbose=true/false
### telemetry <serial>
Start `telemetry` stream for a device.
### trace <serial> <duration> <network>
Launch a remote trace for a device.
- `serial`: device serial number
@@ -164,23 +161,12 @@ Get a list of devices based on a list.
### deviceswithstatus
Get devices with their status.
### setloglevel <subsystem> <loglevel>
Set the log level for s specific subsystem.
### setloglevel <sys> <level>
Set the logging system level for individual subsystems.
- `sys`: ufileuploader/websocket/storage/restapi/commandmanager/auth/deviceregistry/all
- `level`: level:none/fatal/critical/error/warning/notice/information/debug/trace
### getloglevels
Get the current log levels for all subsystems.
### getloglevelnames
Get the log level names available.
### getsubsystemnames
Get the list of subsystems.
### systeminfo
Get basic system information.
### reloadsubsystem <subsystem name>
Reload the configuration for a subsystem.### getfile <uuid>
### getfile <uuid>
Get the file associated with trace command <uuid>.
- `uuid`: UUID of file to retrieve

2
build
View File

@@ -1 +1 @@
44
113

View File

@@ -84,9 +84,8 @@
<Option type="1"/>
<Option compiler="gcc"/>
<Compiler>
<Add option="-DAPP_VERSION=&quot;0.7.0&quot;"/>
<Add option="-DBUILD_NUMBER=&quot;120&quot;"/>
<Add option="-DTIP_GATEWAY_SERVICE=&quot;1&quot;"/>
<Add option="-DAPP_VERSION=&quot;0.4.0&quot;"/>
<Add option="-DBUILD_NUMBER=&quot;61&quot;"/>
<Add option="-D_DEBUG"/>
<Add option="-DPOCO_ENABLE_CPP14"/>
<Add option="-DPOCO_ENABLE_CPP11"/>
@@ -99,7 +98,6 @@
<Add option="-DBOOST_ALL_NO_LIB"/>
<Add directory="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src"/>
<Add directory="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/include/kafka"/>
<Add directory="/usr/local/opt/mysql-client/include"/>
<Add directory="/usr/local/include"/>
<Add directory="/usr/local/opt/openssl/include"/>
<Add directory="/usr/local/opt/mysql-client/include/mysql"/>
@@ -123,9 +121,8 @@
<Option type="1"/>
<Option compiler="gcc"/>
<Compiler>
<Add option="-DAPP_VERSION=&quot;0.7.0&quot;"/>
<Add option="-DBUILD_NUMBER=&quot;120&quot;"/>
<Add option="-DTIP_GATEWAY_SERVICE=&quot;1&quot;"/>
<Add option="-DAPP_VERSION=&quot;0.4.0&quot;"/>
<Add option="-DBUILD_NUMBER=&quot;61&quot;"/>
<Add option="-D_DEBUG"/>
<Add option="-DPOCO_ENABLE_CPP14"/>
<Add option="-DPOCO_ENABLE_CPP11"/>
@@ -138,7 +135,6 @@
<Add option="-DBOOST_ALL_NO_LIB"/>
<Add directory="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src"/>
<Add directory="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/include/kafka"/>
<Add directory="/usr/local/opt/mysql-client/include"/>
<Add directory="/usr/local/include"/>
<Add directory="/usr/local/opt/openssl/include"/>
<Add directory="/usr/local/opt/mysql-client/include/mysql"/>
@@ -159,106 +155,16 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/build">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/ALBHealthCheckServer.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/AuthClient.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/AuthClient.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/CentralConfig.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/CentralConfig.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/CommandChannel.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/CommandChannel.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/CommandManager.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/CommandManager.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/Daemon.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/Daemon.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/DeviceRegistry.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/DeviceRegistry.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/FileUploader.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/FileUploader.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/KafkaManager.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/KafkaManager.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/Kafka_topics.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/MicroService.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/MicroService.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/OUIServer.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/OUIServer.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/OpenAPIRequest.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/OpenAPIRequest.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_BlackList.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_BlackList.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_GWobjects.cpp">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_callback.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_GWobjects.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_InternalServer.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_InternalServer.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_RPC.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_RPC.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_SecurityObjects.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_SecurityObjects.h">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_callback.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_command.cpp">
@@ -315,13 +221,16 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_handler.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_ouis.cpp">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_oauth2Handler.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_ouis.h">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_oauth2Handler.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_protocol.h">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_objects.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_objects.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_server.cpp">
@@ -336,46 +245,16 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_system_command.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_utils.cpp">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_unknownRequestHandler.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_utils.h">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/RESTAPI_unknownRequestHandler.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/StateProcessor.cpp">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/kafka_service.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/StateProcessor.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/StorageArchiver.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/StorageArchiver.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/StorageService.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/StorageService.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/SubSystemServer.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/SubSystemServer.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/Utils.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/Utils.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/WebSocketServer.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/WebSocketServer.h">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/kafka_service.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_blacklist.cpp">
@@ -393,10 +272,13 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_device.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_firmware_updates.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_healthcheck.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_lifetime_stats.cpp">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_identity.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_logs.cpp">
@@ -405,6 +287,9 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_mysql.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_odbc.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_pgql.cpp">
<Option target="ucentralgw"/>
</Unit>
@@ -417,10 +302,82 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/storage_tables.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCentralProtocol.h">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uAuthService.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCentralTypes.h">
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uAuthService.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCallbackManager.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCallbackManager.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCentral.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCentral.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCentralConfig.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCentralConfig.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCentralWebSocketServer.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCentralWebSocketServer.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCommandChannel.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCommandChannel.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCommandManager.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uCommandManager.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uDeviceRegistry.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uDeviceRegistry.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uFileUploader.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uFileUploader.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uFirmwareManager.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uFirmwareManager.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uStorageService.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uStorageService.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uSubSystemServer.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uSubSystemServer.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uUtils.cpp">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/src/uUtils.h">
<Option target="ucentralgw"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/CMakeLists.txt">
@@ -483,6 +440,12 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoCryptoConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoCryptoTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoCryptoTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoCryptoTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
@@ -501,18 +464,48 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataMySQLConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataMySQLTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataMySQLTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataMySQLTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataMySQLTargets.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataODBCConfig.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataODBCConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataODBCTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataODBCTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataODBCTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataODBCTargets.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataPostgreSQLConfig.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataPostgreSQLConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataPostgreSQLTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataPostgreSQLTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataPostgreSQLTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
@@ -525,12 +518,24 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataSQLiteConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataSQLiteTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataSQLiteTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataSQLiteTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataSQLiteTargets.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoDataTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
@@ -543,6 +548,12 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoFoundationConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoFoundationTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoFoundationTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoFoundationTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
@@ -555,6 +566,12 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoJSONConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoJSONTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoJSONTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoJSONTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
@@ -567,6 +584,12 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoJWTConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoJWTTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoJWTTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoJWTTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
@@ -585,12 +608,24 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoNetSSLConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoNetSSLTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoNetSSLTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoNetSSLTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoNetSSLTargets.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoNetTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoNetTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoNetTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
@@ -603,6 +638,12 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoUtilConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoUtilTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoUtilTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoUtilTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
@@ -615,6 +656,12 @@
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoXMLConfigVersion.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoXMLTargets-debug.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoXMLTargets-release.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>
<Unit filename="/Users/stephb/Desktop/Dropbox/clion/wlan-cloud-ucentralgw/../../../../../../usr/local/lib/cmake/Poco/PocoXMLTargets-relwithdebinfo.cmake">
<Option virtualFolder="CMake Files\..\..\..\..\..\..\usr\local\lib\cmake\Poco\"/>
</Unit>

9
docker-compose/.env Normal file
View File

@@ -0,0 +1,9 @@
COMPOSE_PROJECT_NAME=ucentral
POSTGRES_TAG=latest
MYSQL_TAG=latest
UCENTRALGW_TAG=master
UCENTRALGWUI_TAG=main
UCENTRALSEC_TAG=main
RTTYS_TAG=3.6.0
KAFKA_TAG=latest
ZOOKEEPER_TAG=latest

View File

@@ -0,0 +1,2 @@
KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
ALLOW_PLAINTEXT_LISTENER=yes

View File

@@ -0,0 +1,4 @@
MYSQL_ROOT_PASSWORD=root
MYSQL_USER=rttys
MYSQL_PASSWORD=rttys
MYSQL_DATABASE=rttys

View File

@@ -0,0 +1,5 @@
POSTGRES_PASSWORD=ucentralgw
POSTGRES_USER=ucentralgw
UCENTRALSEC_DB=ucentralsec
UCENTRALSEC_DB_USER=ucentralsec
UCENTRALSEC_DB_PASSWORD=ucentralsec

View File

@@ -0,0 +1,2 @@
UCENTRALGW_ROOT=/ucentralgw-data
UCENTRALGW_CONFIG=/ucentralgw-data

View File

@@ -0,0 +1,2 @@
DEFAULT_UCENTRALSEC_URL=https://ucentral.wlan.local:16001
ALLOW_UCENTRALSEC_CHANGE=false

View File

@@ -0,0 +1,2 @@
UCENTRALSEC_ROOT=/ucentralsec-data
UCENTRALSEC_CONFIG=/ucentralsec-data

10
docker-compose/add-ca-cert.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -e
SERVICES="ucentralgw.wlan.local ucentralsec.wlan.local"
for i in $SERVICES; do
docker-compose exec -T $i apk add ca-certificates
docker cp certs/restapi-ca.pem ucentral_$i\_1:/usr/local/share/ca-certificates/
docker-compose exec -T $i update-ca-certificates
done

3
docker-compose/certs/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*
!.gitignore
!cas/

2
docker-compose/certs/cas/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

View File

@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC4DCCAcgCCQC7oc+4dT4WlTANBgkqhkiG9w0BAQsFADAyMQswCQYDVQQGEwJD
QTEMMAoGA1UECgwDVElQMRUwEwYDVQQDDAwqLndsYW4ubG9jYWwwHhcNMjEwNzA3
MDkyOTAxWhcNMzEwNzA1MDkyOTAxWjAyMQswCQYDVQQGEwJDQTEMMAoGA1UECgwD
VElQMRUwEwYDVQQDDAwqLndsYW4ubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQD67KEKKHj1xyj0Sc+/WSFeXluhp+76V/8njnGcTus8IsaHWeAj
O1T1/PnqNMNP3CSgCpAZRn7Eom33HH89pC7iIE5t3aGrFzxZ6AxFgECUCkby1j9D
j7PawapJ7XNqT4P4ZGEGOWlLGE9oUpF2pr3B3jBwmV9t9d/Zp8na23K7rnsr5kNn
RXp6iPNPpynppNQFBwzsovyhu9tzk/zz3gohSY9f6oyNNaKcZwN/yrG4B8FnRfa7
WFNvkPi5zAjJ3oEXMp+Im2/SvSqzptYwZhplb14ILZ5ClkSwAslG8FiOAzXr887r
hgEPzqP6SNIOwy/B/AMOFQl6wPvXBwz9eNW1AgMBAAEwDQYJKoZIhvcNAQELBQAD
ggEBAA8Oa8jannqNRdqOuY460Pum1B61kGmf2OK2ZiMaddlxqL3ZBdXPqF02hwSd
q6uxCVP5NgvqSm+pTHaDcODJiCBrMmGQqHT82LuoCyk1BMqH/PYm+kfazPhKF31x
Me7E47DQzk4tMyV28HBCHH6UicQ05ryT1yBfmj8JmYNx9ezmJcanu0/eyI2Lv8Ar
Y7mrgblfOUnsif2w/aUaOsoY1t6/ThgTBc3BTMtUXXAcMiPLu4mSdN6nCm75Qp5q
4zl/SNPjLnmtpHhLDtr4swf6vZw0RG7ECCf6Av8lv8mJG6g53YM8jfe0EzLqbAFf
iSuQbt5n6lMWVgv+FKwXjwAda+Q=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC4DCCAcgCCQC7oc+4dT4WlTANBgkqhkiG9w0BAQsFADAyMQswCQYDVQQGEwJD
QTEMMAoGA1UECgwDVElQMRUwEwYDVQQDDAwqLndsYW4ubG9jYWwwHhcNMjEwNzA3
MDkyOTAxWhcNMzEwNzA1MDkyOTAxWjAyMQswCQYDVQQGEwJDQTEMMAoGA1UECgwD
VElQMRUwEwYDVQQDDAwqLndsYW4ubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQD67KEKKHj1xyj0Sc+/WSFeXluhp+76V/8njnGcTus8IsaHWeAj
O1T1/PnqNMNP3CSgCpAZRn7Eom33HH89pC7iIE5t3aGrFzxZ6AxFgECUCkby1j9D
j7PawapJ7XNqT4P4ZGEGOWlLGE9oUpF2pr3B3jBwmV9t9d/Zp8na23K7rnsr5kNn
RXp6iPNPpynppNQFBwzsovyhu9tzk/zz3gohSY9f6oyNNaKcZwN/yrG4B8FnRfa7
WFNvkPi5zAjJ3oEXMp+Im2/SvSqzptYwZhplb14ILZ5ClkSwAslG8FiOAzXr887r
hgEPzqP6SNIOwy/B/AMOFQl6wPvXBwz9eNW1AgMBAAEwDQYJKoZIhvcNAQELBQAD
ggEBAA8Oa8jannqNRdqOuY460Pum1B61kGmf2OK2ZiMaddlxqL3ZBdXPqF02hwSd
q6uxCVP5NgvqSm+pTHaDcODJiCBrMmGQqHT82LuoCyk1BMqH/PYm+kfazPhKF31x
Me7E47DQzk4tMyV28HBCHH6UicQ05ryT1yBfmj8JmYNx9ezmJcanu0/eyI2Lv8Ar
Y7mrgblfOUnsif2w/aUaOsoY1t6/ThgTBc3BTMtUXXAcMiPLu4mSdN6nCm75Qp5q
4zl/SNPjLnmtpHhLDtr4swf6vZw0RG7ECCf6Av8lv8mJG6g53YM8jfe0EzLqbAFf
iSuQbt5n6lMWVgv+FKwXjwAda+Q=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQD67KEKKHj1xyj0
Sc+/WSFeXluhp+76V/8njnGcTus8IsaHWeAjO1T1/PnqNMNP3CSgCpAZRn7Eom33
HH89pC7iIE5t3aGrFzxZ6AxFgECUCkby1j9Dj7PawapJ7XNqT4P4ZGEGOWlLGE9o
UpF2pr3B3jBwmV9t9d/Zp8na23K7rnsr5kNnRXp6iPNPpynppNQFBwzsovyhu9tz
k/zz3gohSY9f6oyNNaKcZwN/yrG4B8FnRfa7WFNvkPi5zAjJ3oEXMp+Im2/SvSqz
ptYwZhplb14ILZ5ClkSwAslG8FiOAzXr887rhgEPzqP6SNIOwy/B/AMOFQl6wPvX
Bwz9eNW1AgMBAAECggEAZdJT3u1heEqjAc5Z8QnYEpUzlbuxrAC9V23kCEu2BScP
bKk53NIcvd00BKf4gZWRfygKJVeH5X8MJHR55aeUJsp5SPfgvK6nHMye/iz3B5vM
AoqSDXZow2JHGcyzQvaVVNxWytHNOl3ZCzpGMOGkquDgwzBZmyNk/Muri5X1TtbH
DgeYdht2YiHqHdGWsLNU1vZAgzlwD8fXg65XOmNehjWnowhpNRCgpcDeJCtEuNzt
6iXFWffjO6YTbVnoM5xhLROjLv6gYP4wxsQSZc/NGz9Jow7VxlYZg9wCE75bduFn
7D5O4OgVgPgYbyCutpB/o4PMNURb4V/5p2OAEgLX2QKBgQD+kHYRAaawRbaY4jGf
isj0oh2C/Z99Mqf/nnpPwmUwrhpmnQ+pRdWBw940tPrEpVoOcCPWQ5hO1zUET18d
xQqs3zd6lEhJogmMqkjOT670YBEX/wyALd3M5F3HT/K2aixL1XaCCpAl97JB9RyB
zGIr5c+mIOVK/uYrlFO28thXzwKBgQD8VumZIYZpWeE7pTyCg0PcDYlNATA/VKoD
9YrGqEEHGgFNJEWj8Xj8aqBzaPoUk+eGp7NfSoOchVM+Bf3ktWy5doZCmNuxlOyq
Ix5yrB2jyYceaSf2nxHqlD2VhKB/YJx0yTU1UkB5dG4nYnqiUg7c5JeQOVzwFKm1
t6/Hk/cXOwKBgGT+yWjL3+cVcXFMZGWouTudSdobZ3hTbaWTqXEVbfIXUPAfJgSB
aUi3feQpXUhBVe5efUlXvgihhy4zk0gLUcXuNWOTiu5ztBgzwvjfUkkwB/geP0Zn
bBULEU2vIVtP2k0n3oGPUUtO71ENvwacIOLLpUuCx5WudYEasu/lfwGvAoGBAOiE
manuF3HaTU3tu20z0YLiwkK/tpqUxDjzuBXIEmudzdcsdjNUHbzR79mIwO/XPf95
ZjKHcfD3dbXwRXzKpE3dZmfVfJMM/GrmA3d9G67B04z1Lsr01siGIp004cOd3W1L
vojMqvZ/j8Ug3InX/TQUO4i9IuNi1uLISOQpdwTjAoGAG33swIFnH/mz7ubu8wfE
9nwe8NNf56kbFBG2FMuHvo8GYj0sqylwtZnh4TCwlTzqUO8e6oFdK8Ot6z7H9Fa3
vnDD2WRwEFydRP5fbW5eFmGbzLfHlzUY+Do81qrUMF47LEN94X7yaXdb/vNW57lp
K9hGF1Bdk8089Knm3l1Fc4w=
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEgDCCA2igAwIBAgIUaKVB2xg9gr/sS6FvzMex0xSbEzswDQYJKoZIhvcNAQEL
BQAwbDELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG1RlbGVjb20gSW5mcmEgUHJvamVj
dCwgSW5jLjEMMAoGA1UECxMDVElQMSkwJwYDVQQDEyBUZWxlY29tIEluZnJhIFBy
b2plY3QgSXNzdWluZyBDQTAeFw0yMTA3MDgxMDQ5MTVaFw0yNTA3MDgxMDQ5MTVa
MDIxCzAJBgNVBAYTAlVTMQwwCgYDVQQKEwNUSVAxFTATBgNVBAMMDCoud2xhbi5s
b2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2rlMfV7/Si2Svx
J1YOEz6KJLvey995/0MkQvAG0RM6TpFwgUNnpYFFozcWME8MGSxws+6hOzDoMmHC
pgpP/KZ/Fyu9iUdzTxsJMyMxIW9sYbBMkQgBmvjkBlXDk5NfHh+yJBVxb7JlJ6vJ
oT7EJMzgKpYpFnO+bddalUVsDp3qQIjSvJIxl77vwgZQUJx0qCm17VTBhyM2RTJ3
jtr7kcWDm3jyyTVUvlM9g3DM9g0hUPMN0R5PP2HuqDdtYoY51krsm2mmVIYYnyAN
BDawmwYnZJfcC4gFzZJ5wK5NFjSKmd1mYp0damlSh0/uHxPyd4rm2QhUCQH92yKM
+9qYU70CAwEAAaOCAVIwggFOMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFM0mIZuE
6aly7ZKXl0KWjprcO9/uMB8GA1UdIwQYMBaAFLMbVLjgR6s98ziA5Dzl/QBhbdHo
MA4GA1UdDwEB/wQEAwIFoDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATCBhgYIKwYB
BQUHAQEEejB4MCgGCCsGAQUFBzABhhxodHRwOi8vb2NzcC5vbmUuZGlnaWNlcnQu
Y29tMEwGCCsGAQUFBzAChkBodHRwOi8vY2FjZXJ0cy5vbmUuZGlnaWNlcnQuY29t
L1RlbGVjb21JbmZyYVByb2plY3RJc3N1aW5nQ0EuY3J0ME0GA1UdHwRGMEQwQqBA
oD6GPGh0dHA6Ly9jcmwub25lLmRpZ2ljZXJ0LmNvbS9UZWxlY29tSW5mcmFQcm9q
ZWN0SXNzdWluZ0NBLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAAyb7X9qW0z0QJrl2
oAalMCh/gSJy5oER3L7iu/pnP3GREbr6bh6+1/MAf2bgnN2CUOKQHbozB7yCkM6V
8m5RnL4ePKVP5yIrbs48uM5Hl14QFLU4ZtFao6js0haoWWEgMo3sfbeyfOU0ScyW
ET5zfbDub3gUbWYmlz6hyV5aJoznaFjJTNP7SRQ9CHMTMHh3wAPfVlvG2TdcwwbM
ZKkdAHpl1NwRxyiBPJfkejGWrY3ZAs10te7u9Lsc9yZZKL8SU9J/mrO9tM5HLeUr
nCJN4RI7RyTuDw4LdMZW1Ju5QBXoZL9mj4KXIbUkDwryhbAxdQ1OnwD4O/avMChk
TNJzIw==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC9q5TH1e/0otkr
8SdWDhM+iiS73svfef9DJELwBtETOk6RcIFDZ6WBRaM3FjBPDBkscLPuoTsw6DJh
wqYKT/ymfxcrvYlHc08bCTMjMSFvbGGwTJEIAZr45AZVw5OTXx4fsiQVcW+yZSer
yaE+xCTM4CqWKRZzvm3XWpVFbA6d6kCI0rySMZe+78IGUFCcdKgpte1UwYcjNkUy
d47a+5HFg5t48sk1VL5TPYNwzPYNIVDzDdEeTz9h7qg3bWKGOdZK7JtpplSGGJ8g
DQQ2sJsGJ2SX3AuIBc2SecCuTRY0ipndZmKdHWppUodP7h8T8neK5tkIVAkB/dsi
jPvamFO9AgMBAAECggEBAJgYoaRmcJfShyhvp8WgX9pE2RQ2o3I/2Gy1BWCJdtte
ZGbIuz+cO+IgP7QK/Q5Ge2Fht0hizp53dP9kIdYfMlEplSEkSpObahIaHIHaAh/h
36yKmbq73tQ7tsDLpuoE2pk8Nydi4dlCuL9PXxiAHaqVEFF9/V0vldGd+BnFfyst
retXgockCH+fqddM5Kp+H0bmjXzLke/b8T9KsdSBz7lg1Z67kmMrHLe14Q4Hgmr/
pFBkGGWKTFn48OXfncrv+oQAGED7r9c5UEdpOB6SBDxuddfzgkw9urnpKrYC/KOs
HLBTaGew73O81BsbaZlUiVxTdewrmFk2nG6UIPoGaxkCgYEA7IYOjIfNJOEPIWYP
zj4eipTy6zFk4L7tX3wX4wsor93rz8ArlF8sgNoyUhbKm6H++ZfVezLs2jcjJJ8Q
sXLwQ6L/D8aVb6AOVeC1WYJu5+wXIDX0H+1318a5+3bKVPn+hktJGEgCBvplVRnh
yzpQ+2v1SBp9qEzoSl1sV6gm1tsCgYEAzUnZcjUhHvoXLXJ1lfagCC6QsmjqzpJv
VdTKJlDuZ0qQGC6Ts+wKfM3MoiOsXW0pByC5lWwE43c/KU8J358j3OSSNafIFeD1
cxtYzJlMgnw5Y2Zt9tj+QW/1BOMdOftnPSOnsk6rpdCBMW6a2tYubJjbAuge+a2O
939XGnV0R0cCgYEA0bvmNtNNJAC2LAWWymnnJzgBWHFKZMipMNyXSethPuHo8yYS
/tSOYAwcRxKSwwMZWDY9RavYv3/ZF+Y9JT0otLFav6B2bq9dRuWlqiOxONLvhs6R
Faa7eIlt7gBeVpAAFRG5VWC0+38aUCZNRKsHmIsYy8FB3/Winh7NrcUb+7UCgYBi
egCTZqUixPmFVZjOfWY7Rosm6mlo+pnp5I+sXbpfVkdVMlKsRpipUdfOF6rBjnHV
937PDOgzbaqg2Ed2PFLpzcPNdVToGefkdcPdMdSf65Nj+WjatzEQlvJEi+YjQFQ/
4fC5+j8g5apz2gjy3Teb5J96/3qMbxNb6nwQNzO2VQKBgHyHUJOrhvv9+vs7v8nu
9DgV0b5eNO0g6Q4Ji7oqs24PssPQRA4gMtwmPT8Ha+wWGVzQt2U5LmjsLlrqAO6O
+Fa3c63sgmt672A8BJ3PL8LI8E2keZiH6rwADSUFp3TZoU2SHamw5NEruNRMIF1R
0LMsuAs2KEdnwAth2ZmUF2+S
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,110 @@
version: '3'
volumes:
postgresql_data:
driver: local
mysql_data:
driver: local
zookeeper_data:
driver: local
zookeeper_datalog:
driver: local
kafka_data:
driver: local
services:
postgresql:
image: "postgres:${POSTGRES_TAG}"
env_file:
- .env_postgresql
restart: unless-stopped
volumes:
- postgresql_data:/var/lib/postgresql/data
- ./init-ucentralsec-db.sh:/docker-entrypoint-initdb.d/init-ucentralsec-db.sh
mysql:
image: "mysql:${MYSQL_TAG}"
env_file:
- .env_mysql
restart: unless-stopped
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- mysql_data:/var/lib/mysql
ucentralgw.wlan.local:
image: "tip-tip-wlan-cloud-ucentral.jfrog.io/ucentralgw:${UCENTRALGW_TAG}"
env_file:
- .env_ucentralgw
depends_on:
- postgresql
- kafka
- rttys
restart: unless-stopped
ports:
- "127.0.0.1:15002:15002"
- "127.0.0.1:16002:16002"
- "127.0.0.1:16003:16003"
- "127.0.0.1:16102:16102"
volumes:
- ./ucentralgw-data:/ucentralgw-data
- ./certs:/ucentralgw-data/certs
- ../certificates/root.pem:/ucentralgw-data/certs/root.pem
- ../certificates/issuer.pem:/ucentralgw-data/certs/issuer.pem
- ../certificates/clientcas.pem:/ucentralgw-data/certs/clientcas.pem
ucentralgw-ui:
image: "tip-tip-wlan-cloud-ucentral.jfrog.io/ucentralgw-ui:${UCENTRALGWUI_TAG}"
env_file:
- .env_ucentralgw-ui
depends_on:
- ucentralgw.wlan.local
restart: unless-stopped
ports:
- "127.0.0.1:80:80"
ucentralsec.wlan.local:
image: "tip-tip-wlan-cloud-ucentral.jfrog.io/ucentralsec:${UCENTRALSEC_TAG}"
env_file:
- .env_ucentralsec
depends_on:
- postgresql
- kafka
- rttys
- ucentralgw.wlan.local
restart: unless-stopped
ports:
- "127.0.0.1:16001:16001"
- "127.0.0.1:16101:16101"
volumes:
- ./ucentralsec-data:/ucentralsec-data
- ./certs:/ucentralsec-data/certs
- ../certificates/root.pem:/ucentralsec-data/certs/root.pem
- ../certificates/issuer.pem:/ucentralsec-data/certs/issuer.pem
- ../certificates/clientcas.pem:/ucentralsec-data/certs/clientcas.pem
rttys:
image: "tip-tip-wlan-cloud-ucentral.jfrog.io/rttys:${RTTYS_TAG}"
depends_on:
- mysql
restart: unless-stopped
volumes:
- ./certs/restapi-cert.pem:/etc/rttys/restapi-cert.pem
- ./certs/restapi-key.pem:/etc/rttys/restapi-key.pem
- ./rttys/rttys.conf:/rttys/rttys.conf
zookeeper:
image: "zookeeper:${ZOOKEEPER_TAG}"
restart: unless-stopped
volumes:
- zookeeper_data:/data
- zookeeper_datalog:/datalog
kafka:
image: "docker.io/bitnami/kafka:${KAFKA_TAG}"
env_file:
- .env_kafka
restart: unless-stopped
depends_on:
- zookeeper
volumes:
- kafka_data:/bitnami/kafka

View File

@@ -0,0 +1,8 @@
#!/bin/bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
CREATE USER $UCENTRALSEC_DB_USER WITH ENCRYPTED PASSWORD '$UCENTRALSEC_DB_PASSWORD';
CREATE DATABASE $UCENTRALSEC_DB;
GRANT ALL PRIVILEGES ON DATABASE $UCENTRALSEC_DB TO $UCENTRALSEC_DB_USER;
EOSQL

View File

@@ -0,0 +1,18 @@
addr-dev: :5912
addr-user: :5913
#addr-web: :5914
#web-redir-url:# Auth for http
http-username: rttys
http-password: rttys
ssl-cert: /etc/rttys/restapi-cert.pem
ssl-key: /etc/rttys/restapi-key.pem
token: 96181c567b4d0d98c50f127230068fa8
# font-size: 16
# No login required to connect device.
# Values can be device IDs separated by spaces,
# or a "*" indicates that all devices do not require login
# http://localhost:5913/connect/rtty1
white-list: "*"
#white-list: rtty1 rtty2
# mysql database source
db: rttys:rttys@tcp(mysql)/rttys

View File

@@ -0,0 +1,194 @@
#
# uCentral protocol server for devices. This is where you point
# all your devices. You can replace the * for address by the specific
# address of one of your interfaces
#
ucentral.websocket.host.0.backlog = 500
ucentral.websocket.host.0.rootca = $UCENTRALGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer = $UCENTRALGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert = $UCENTRALGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key = $UCENTRALGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas = $UCENTRALGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas = $UCENTRALGW_ROOT/certs/cas
ucentral.websocket.host.0.address = *
ucentral.websocket.host.0.port = 15002
ucentral.websocket.host.0.security = strict
ucentral.websocket.host.0.key.password = mypassword
ucentral.websocket.maxreactors = 20
#
# REST API access
#
ucentral.restapi.host.0.backlog = 100
ucentral.restapi.host.0.security = relaxed
ucentral.restapi.host.0.rootca = $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address = *
ucentral.restapi.host.0.port = 16002
ucentral.restapi.host.0.cert = $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.restapi.host.0.key.password = mypassword
ucentral.internal.restapi.host.0.backlog = 100
ucentral.internal.restapi.host.0.security = relaxed
ucentral.internal.restapi.host.0.rootca = $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.internal.restapi.host.0.address = *
ucentral.internal.restapi.host.0.port = 17002
ucentral.internal.restapi.host.0.cert = $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.internal.restapi.host.0.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.internal.restapi.host.0.key.password = mypassword
#
# Used to upload files to the service.
# You should replace the 'name' vaalue with the IP address of your gateway or an FQDN
# that your devices can reach
#
ucentral.fileuploader.host.0.backlog = 100
ucentral.fileuploader.host.0.rootca = $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.fileuploader.host.0.security = relaxed
ucentral.fileuploader.host.0.address = *
ucentral.fileuploader.host.0.name = ucentral.wlan.local
ucentral.fileuploader.host.0.port = 16003
ucentral.fileuploader.host.0.cert = $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.fileuploader.host.0.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.fileuploader.host.0.key.password = mypassword
ucentral.fileuploader.path = $UCENTRALGW_ROOT/uploads
ucentral.fileuploader.maxsize = 10000
#
# Generic section that all microservices must have
#
ucentral.service.key = $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.system.data = $UCENTRALGW_ROOT/data
ucentral.system.debug = true
#ucentral.system.uri.private = https://localhost:17002
#ucentral.system.uri.public = https://local.dpaas.arilia.com:16002
#ucentral.system.uri.ui = https://ucentral-ui.arilia.com
ucentral.system.uri.private = https://ucentralgw.wlan.local:17002
ucentral.system.uri.public = https://ucentral.wlan.local:16002
ucentral.system.uri.ui = http://127.0.0.1
ucentral.system.commandchannel = /tmp/app.ucentralgw
#
# Gateway Microservice Specific Section
#
ucentral.autoprovisioning = true
ucentral.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
ucentral.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
ucentral.devicetypes.2 = IOT:esp32
oui.download.uri = https://linuxnet.ca/ieee/oui.txt
firmware.autoupdate.policy.default = auto
#
# rtty
#
rtty.enabled = true
rtty.server = rttys
rtty.port = 5912
rtty.token = 96181c567b4d0d98c50f127230068fa8
rtty.timeout = 60
rtty.viewport = 5913
#############################
# Generic information for all micro services
#############################
#
# NLB Support
#
alb.enable = true
alb.port = 16102
#
# Kafka
#
ucentral.kafka.group.id = gateway
ucentral.kafka.client.id = gateway1
ucentral.kafka.enable = true
ucentral.kafka.brokerlist = kafka:9092
# ucentral.kafka.brokerlist = debfarm1-node-c.arilia.com:9092
ucentral.kafka.auto.commit = false
ucentral.kafka.queue.buffering.max.ms = 50
#
# This section select which form of persistence you need
# Only one selected at a time. If you select multiple, this service will die if a horrible
# death and might make your beer flat.
#
#storage.type = sqlite
storage.type = postgresql
#storage.type = mysql
#storage.type = odbc
storage.type.sqlite.db = devices.db
storage.type.sqlite.idletime = 120
storage.type.sqlite.maxsessions = 128
storage.type.postgresql.maxsessions = 64
storage.type.postgresql.idletime = 60
storage.type.postgresql.host = postgresql
storage.type.postgresql.username = ucentralgw
storage.type.postgresql.password = ucentralgw
storage.type.postgresql.database = ucentralgw
storage.type.postgresql.port = 5432
storage.type.postgresql.connectiontimeout = 60
storage.type.mysql.maxsessions = 64
storage.type.mysql.idletime = 60
storage.type.mysql.host = localhost
storage.type.mysql.username = stephb
storage.type.mysql.password = snoopy99
storage.type.mysql.database = ucentral
storage.type.mysql.port = 3306
storage.type.mysql.connectiontimeout = 60
archiver.enabled = true
archiver.schedule = 03:00
archiver.db.0.name = healthchecks
archiver.db.0.keep = 7
archiver.db.1.name = statistics
archiver.db.1.keep = 7
archiver.db.2.name = devicelogs
archiver.db.2.keep = 7
archiver.db.3.name = commandlist
archiver.db.3.keep = 7
########################################################################
########################################################################
#
# Logging: please leave as is for now.
#
########################################################################
logging.formatters.f1.class = PatternFormatter
logging.formatters.f1.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.formatters.f1.times = UTC
logging.channels.c1.class = ConsoleChannel
logging.channels.c1.formatter = f1
# This is where the logs will be written. This path MUST exist
logging.channels.c2.class = FileChannel
logging.channels.c2.path = $UCENTRALGW_ROOT/logs/log
logging.channels.c2.formatter.class = PatternFormatter
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.channels.c2.rotation = 20 M
logging.channels.c2.archive = timestamp
logging.channels.c2.purgeCount = 20
logging.channels.c3.class = ConsoleChannel
logging.channels.c3.pattern = %s: [%p] %t
# External Channel
logging.loggers.root.channel = c1
logging.loggers.root.level = debug
# Inline Channel with PatternFormatter
# logging.loggers.l1.name = logger1
# logging.loggers.l1.channel.class = ConsoleChannel
# logging.loggers.l1.channel.pattern = %s: [%p] %t
# logging.loggers.l1.level = information
# SplitterChannel
# logging.channels.splitter.class = SplitterChannel
# logging.channels.splitter.channels = l1,l2
# logging.loggers.l2.name = logger2
# logging.loggers.l2.channel = splitter

View File

@@ -0,0 +1,145 @@
#
# uCentral protocol server for devices. This is where you point
# all your devices. You can replace the * for address by the specific
# address of one of your interfaces
#
#
# REST API access
#
ucentral.restapi.host.0.backlog = 100
ucentral.restapi.host.0.security = relaxed
ucentral.restapi.host.0.rootca = $UCENTRALSEC_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address = *
ucentral.restapi.host.0.port = 16001
ucentral.restapi.host.0.cert = $UCENTRALSEC_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem
ucentral.restapi.host.0.key.password = mypassword
ucentral.restapi.wwwassets = $UCENTRALSEC_ROOT/wwwassets
ucentral.internal.restapi.host.0.backlog = 100
ucentral.internal.restapi.host.0.security = relaxed
ucentral.internal.restapi.host.0.rootca = $UCENTRALSEC_ROOT/certs/restapi-ca.pem
ucentral.internal.restapi.host.0.address = *
ucentral.internal.restapi.host.0.port = 17001
ucentral.internal.restapi.host.0.cert = $UCENTRALSEC_ROOT/certs/restapi-cert.pem
ucentral.internal.restapi.host.0.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem
ucentral.internal.restapi.host.0.key.password = mypassword
#
# Generic section that all microservices must have
#
authentication.enabled = true
authentication.default.username = tip@ucentral.com
authentication.default.password = 13268b7daa751240369d125e79c873bd8dd3bef7981bdfd38ea03dbb1fbe7dcf
ucentral.system.data = $UCENTRALSEC_ROOT/data
ucentral.system.uri.private = https://ucentralsec.wlan.local:17001
ucentral.system.uri.public = https://ucentral.wlan.local:16001
ucentral.system.uri.ui = http://127.0.0.1
ucentral.system.commandchannel = /tmp/app.ucentralsec
ucentral.service.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem
#
# Security Microservice Specific Section
#
mailer.hostname = smtp.gmail.com
mailer.username = no-reply@arilia.com
mailer.password = pink-elephants-play-hockey
mailer.loginmethod = login
mailer.port = 587
mailer.templates = $UCENTRALSEC_ROOT/templates
#############################
# Generic information for all micro services
#############################
#
# NLB Support
#
alb.enable = true
alb.port = 16101
#
# Kafka
#
ucentral.kafka.group.id = security
ucentral.kafka.client.id = security1
ucentral.kafka.enable = true
# ucentral.kafka.brokerlist = a1.arilia.com:9092
ucentral.kafka.brokerlist = kafka:9092
ucentral.kafka.auto.commit = false
ucentral.kafka.queue.buffering.max.ms = 50
#
# This section select which form of persistence you need
# Only one selected at a time. If you select multiple, this service will die if a horrible
# death and might make your beer flat.
#
#storage.type = sqlite
storage.type = postgresql
#storage.type = mysql
#storage.type = odbc
storage.type.sqlite.db = security.db
storage.type.sqlite.idletime = 120
storage.type.sqlite.maxsessions = 128
storage.type.postgresql.maxsessions = 64
storage.type.postgresql.idletime = 60
storage.type.postgresql.host = postgresql
storage.type.postgresql.username = ucentralsec
storage.type.postgresql.password = ucentralsec
storage.type.postgresql.database = ucentralsec
storage.type.postgresql.port = 5432
storage.type.postgresql.connectiontimeout = 60
storage.type.mysql.maxsessions = 64
storage.type.mysql.idletime = 60
storage.type.mysql.host = localhost
storage.type.mysql.username = stephb
storage.type.mysql.password = snoopy99
storage.type.mysql.database = ucentral
storage.type.mysql.port = 3306
storage.type.mysql.connectiontimeout = 60
########################################################################
########################################################################
#
# Logging: please leave as is for now.
#
########################################################################
logging.formatters.f1.class = PatternFormatter
logging.formatters.f1.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.formatters.f1.times = UTC
logging.channels.c1.class = ConsoleChannel
logging.channels.c1.formatter = f1
# This is where the logs will be written. This path MUST exist
logging.channels.c2.class = FileChannel
logging.channels.c2.path = $UCENTRALSEC_ROOT/logs/log
logging.channels.c2.formatter.class = PatternFormatter
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.channels.c2.rotation = 20 M
logging.channels.c2.archive = timestamp
logging.channels.c2.purgeCount = 20
logging.channels.c3.class = ConsoleChannel
logging.channels.c3.pattern = %s: [%p] %t
# External Channel
logging.loggers.root.channel = c1
logging.loggers.root.level = debug
# Inline Channel with PatternFormatter
# logging.loggers.l1.name = logger1
# logging.loggers.l1.channel.class = ConsoleChannel
# logging.loggers.l1.channel.pattern = %s: [%p] %t
# logging.loggers.l1.level = information
# SplitterChannel
# logging.channels.splitter.class = SplitterChannel
# logging.channels.splitter.channels = l1,l2
# logging.loggers.l2.name = logger2
# logging.loggers.l2.channel = splitter

View File

@@ -1,71 +0,0 @@
#!/bin/sh
set -e
if [ "$SELFSIGNED_CERTS" = 'true' ]; then
update-ca-certificates
fi
if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWGW_CONFIG"/owgw.properties ]]; then
WEBSOCKET_HOST_ROOTCA=${WEBSOCKET_HOST_ROOTCA:-"\$OWGW_ROOT/certs/root.pem"} \
WEBSOCKET_HOST_ISSUER=${WEBSOCKET_HOST_ISSUER:-"\$OWGW_ROOT/certs/issuer.pem"} \
WEBSOCKET_HOST_CERT=${WEBSOCKET_HOST_CERT:-"\$OWGW_ROOT/certs/websocket-cert.pem"} \
WEBSOCKET_HOST_KEY=${WEBSOCKET_HOST_KEY:-"\$OWGW_ROOT/certs/websocket-key.pem"} \
WEBSOCKET_HOST_CLIENTCAS=${WEBSOCKET_HOST_CLIENTCAS:-"\$OWGW_ROOT/certs/clientcas.pem"} \
WEBSOCKET_HOST_CAS=${WEBSOCKET_HOST_CAS:-"\$OWGW_ROOT/certs/cas"} \
WEBSOCKET_HOST_PORT=${WEBSOCKET_HOST_PORT:-"15002"} \
WEBSOCKET_HOST_KEY_PASSWORD=${WEBSOCKET_HOST_KEY_PASSWORD:-"mypassword"} \
RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWGW_ROOT/certs/restapi-ca.pem"} \
RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16002"} \
RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWGW_ROOT/certs/restapi-cert.pem"} \
RESTAPI_HOST_KEY=${RESTAPI_HOST_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
RESTAPI_HOST_KEY_PASSWORD=${RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \
INTERNAL_RESTAPI_HOST_ROOTCA=${INTERNAL_RESTAPI_HOST_ROOTCA:-"\$OWGW_ROOT/certs/restapi-ca.pem"} \
INTERNAL_RESTAPI_HOST_PORT=${INTERNAL_RESTAPI_HOST_PORT:-"17002"} \
INTERNAL_RESTAPI_HOST_CERT=${INTERNAL_RESTAPI_HOST_CERT:-"\$OWGW_ROOT/certs/restapi-cert.pem"} \
INTERNAL_RESTAPI_HOST_KEY=${INTERNAL_RESTAPI_HOST_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
INTERNAL_RESTAPI_HOST_KEY_PASSWORD=${INTERNAL_RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \
FILEUPLOADER_HOST_ROOTCA=${FILEUPLOADER_HOST_ROOTCA:-"\$OWGW_ROOT/certs/restapi-ca.pem"} \
FILEUPLOADER_HOST_NAME=${FILEUPLOADER_HOST_NAME:-"localhost"} \
FILEUPLOADER_HOST_PORT=${FILEUPLOADER_HOST_PORT:-"16003"} \
FILEUPLOADER_HOST_CERT=${FILEUPLOADER_HOST_CERT:-"\$OWGW_ROOT/certs/restapi-cert.pem"} \
FILEUPLOADER_HOST_KEY=${FILEUPLOADER_HOST_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
FILEUPLOADER_HOST_KEY_PASSWORD=${FILEUPLOADER_HOST_KEY_PASSWORD:-"mypassword"} \
FILEUPLOADER_PATH=${FILEUPLOADER_PATH:-"\$OWGW_ROOT/uploads"} \
FILEUPLOADER_URI=${FILEUPLOADER_URI:-"https://localhost:16003"} \
SERVICE_KEY=${SERVICE_KEY:-"\$OWGW_ROOT/certs/restapi-key.pem"} \
SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
SYSTEM_DATA=${SYSTEM_DATA:-"\$OWGW_ROOT/data"} \
SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17002"} \
SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16002"} \
SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
SIMULATORID=${SIMULATORID:-""} \
RTTY_ENABLED=${RTTY_ENABLED:-"false"} \
RTTY_SERVER=${RTTY_SERVER:-"localhost"} \
RTTY_PORT=${RTTY_PORT:-"5912"} \
RTTY_TOKEN=${RTTY_TOKEN:-"96181c567b4d0d98c50f127230068fa8"} \
RTTY_TIMEOUT=${RTTY_TIMEOUT:-"60"} \
RTTY_VIEWPORT=${RTTY_VIEWPORT:-"5913"} \
KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \
KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \
STORAGE_TYPE=${STORAGE_TYPE:-"sqlite"} \
STORAGE_TYPE_POSTGRESQL_HOST=${STORAGE_TYPE_POSTGRESQL_HOST:-"localhost"} \
STORAGE_TYPE_POSTGRESQL_USERNAME=${STORAGE_TYPE_POSTGRESQL_USERNAME:-"owgw"} \
STORAGE_TYPE_POSTGRESQL_PASSWORD=${STORAGE_TYPE_POSTGRESQL_PASSWORD:-"owgw"} \
STORAGE_TYPE_POSTGRESQL_DATABASE=${STORAGE_TYPE_POSTGRESQL_DATABASE:-"owgw"} \
STORAGE_TYPE_POSTGRESQL_PORT=${STORAGE_TYPE_POSTGRESQL_PORT:-"5432"} \
STORAGE_TYPE_MYSQL_HOST=${STORAGE_TYPE_MYSQL_HOST:-"localhost"} \
STORAGE_TYPE_MYSQL_USERNAME=${STORAGE_TYPE_MYSQL_USERNAME:-"owgw"} \
STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"owgw"} \
STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"owgw"} \
STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \
envsubst < /owgw.properties.tmpl > $OWGW_CONFIG/owgw.properties
fi
if [ "$1" = '/openwifi/owgw' -a "$(id -u)" = '0' ]; then
if [ "$RUN_CHOWN" = 'true' ]; then
chown -R "$OWGW_USER": "$OWGW_ROOT" "$OWGW_CONFIG"
fi
exec su-exec "$OWGW_USER" "$@"
fi
exec "$@"

View File

@@ -26,7 +26,7 @@ then
exit 1
fi
if [[ ! -f owgw.properties ]]
if [[ ! -f ucentral.properties ]]
then
echo "Configuration file ucentral.properties is missing in the current directory"
exit 2
@@ -37,7 +37,7 @@ docker run -d -p 15002:15002 \
-p 16003:16003 \
--init \
--volume="$PWD:/ucentral-data" \
-e UCENTRALGW_ROOT="/ucentral-data" \
-e UCENTRALGW_CONFIG="/ucentral-data" \
-e UCENTRAL_ROOT="/ucentral-data" \
-e UCENTRAL_CONFIG="/ucentral-data" \
--name="ucentralgw" $DOCKER_NAME

View File

View File

@@ -1,12 +0,0 @@
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 10.9.2
- name: mysql
repository: https://charts.bitnami.com/bitnami
version: 8.8.3
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.4.2
digest: sha256:1fdae7cbea906e41dccd8618ff9e2c68d0c684724ae27c79a12bb6089968df5c
generated: "2021-08-17T12:18:40.341427893+03:00"

View File

@@ -1,18 +1,5 @@
apiVersion: v2
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: owgw
name: ucentralgw
version: 0.1.0
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 10.9.2
condition: postgresql.enabled
- name: mysql
repository: https://charts.bitnami.com/bitnami
version: 8.8.3
condition: mysql.enabled
- name: mariadb
repository: https://charts.bitnami.com/bitnami
version: 9.4.2
condition: mariadb.enabled

View File

@@ -1,102 +0,0 @@
# owgw
This Helm chart helps to deploy OpenWIFI Gateway (further on refered as __Gateway__) to the Kubernetes clusters. It is mainly used in [assembly chart](https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart) as Gateway requires other services as dependencies that are considered in that Helm chart. This chart is purposed to define deployment logic close to the application code itself and define default values that could be overriden during deployment.
## TL;DR;
```bash
$ helm install .
```
## Introduction
This chart bootstraps the Gateway on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.
## Installing the Chart
Currently this chart is not assembled in charts archives, so [helm-git](https://github.com/aslafy-z/helm-git) is required for remote the installation
To install the chart with the release name `my-release`:
```bash
$ helm install --name my-release git+https://github.com/Telecominfraproject/wlan-cloud-ucentralgw@helm/owgw-0.1.0.tgz?ref=master
```
The command deploys the Gateway on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation.
> **Tip**: List all releases using `helm list`
## Uninstalling the Chart
To uninstall/delete the `my-release` deployment:
```bash
$ helm delete my-release
```
The command removes all the Kubernetes components associated with the chart and deletes the release.
## Configuration
The following table lists the configurable parameters of the chart and their default values. If Default value is not listed in the table, please refer to the [Values](values.yaml) files for details.
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| replicaCount | number | Amount of replicas to be deployed | `1` |
| strategyType | string | Application deployment strategy | `'Recreate'` |
| nameOverride | string | Override to be used for application deployment | |
| fullnameOverride | string | Override to be used for application deployment (has priority over nameOverride) | |
| images.owgw.repository | string | Docker image repository | |
| images.owgw.tag | string | Docker image tag | `'master'` |
| images.owgw.pullPolicy | string | Docker image pull policy | `'Always'` |
| services.owgw.type | string | OpenWIFI Gateway service type | `'LoadBalancer'` |
| services.owgw.ports.websocket.servicePort | number | Websocket endpoint port to be exposed on service | `15002` |
| services.owgw.ports.websocket.targetPort | number | Websocket endpoint port to be targeted by service | `15002` |
| services.owgw.ports.websocket.protocol | string | Websocket endpoint protocol | `'TCP'` |
| services.owgw.ports.restapi.servicePort | number | REST API endpoint port to be exposed on service | `16002` |
| services.owgw.ports.restapi.targetPort | number | REST API endpoint port to be targeted by service | `16002` |
| services.owgw.ports.restapi.protocol | string | REST API endpoint protocol | `'TCP'` |
| services.owgw.ports.restapiinternal.servicePort | string | Internal REST API endpoint port to be exposed on service | `17002` |
| services.owgw.ports.restapiinternal.targetPort | number | Internal REST API endpoint port to be targeted by service | `17002` |
| services.owgw.ports.restapiinternal.protocol | string | Internal REST API endpoint protocol | `'TCP'` |
| services.owgw.ports.fileuploader.servicePort | string | Fileuploader endpoint port to be exposed on service | `16003` |
| services.owgw.ports.fileuploader.targetPort | number | Fileuploader endpoint port to be targeted by service | `16003` |
| services.owgw.ports.fileuploader.protocol | string | Fileuploader endpoint protocol | `'TCP'` |
| checks.owgw.liveness.httpGet.path | string | Liveness check path to be used | `'/'` |
| checks.owgw.liveness.httpGet.port | number | Liveness check port to be used (should be pointint to ALB endpoint) | `16102` |
| checks.owgw.readiness.httpGet.path | string | Readiness check path to be used | `'/'` |
| checks.owgw.readiness.httpGet.port | number | Readiness check port to be used (should be pointint to ALB endpoint) | `16102` |
| ingresses.restapi.enabled | boolean | Defines if REST API endpoint should be exposed via Ingress controller | `False` |
| ingresses.restapi.hosts | array | List of hosts for exposed REST API | |
| ingresses.restapi.paths | array | List of paths to be exposed for REST API | |
| ingresses.fileuploader.enabled | boolean | Defines if Fileuploader endpoint should be exposed via Ingress controller | `False` |
| ingresses.fileuploader.hosts | array | List of hosts for exposed Fileuploader | |
| ingresses.fileuploader.paths | array | List of paths for exposed Fileuploader | |
| volumes.owgw | array | Defines list of volumes to be attached to the Gateway | |
| persistence.enabled | boolean | Defines if the Gateway requires Persistent Volume (required for permanent files storage and SQLite DB if enabled) | `True` |
| persistence.accessModes | array | Defines PV access modes | |
| persistence.size | string | Defines PV size | `'10Gi'` |
| public_env_variables | hash | Defines list of environment variables to be passed to the Gateway | |
| configProperties | hash | Configuration properties that should be passed to the application in `owgw.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 Gateway (PEM format is adviced to be used) (see `volumes.owgw` on where it is mounted) | |
| certsCAs | hash | Defines files with CAs that should be passed to the Gateway (see `volumes.owgw` on where it is mounted) | |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,
```bash
$ helm install --name my-release \
--set replicaCount=1 \
.
```
The above command sets that only 1 instance of your app should be running
Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example,
```bash
$ helm install --name my-release -f values.yaml .
```
> **Tip**: You can use the default [values.yaml](values.yaml) as a base for customization.

View File

@@ -1,4 +1,4 @@
{{- define "owgw.config" -}}
{{- define "ucentralgw.config" -}}
{{- range $key, $value := .Values.configProperties }}
{{ $key }} = {{ $value }}
{{- end }}

View File

@@ -2,7 +2,7 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "owgw.name" -}}
{{- define "ucentralgw.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
@@ -11,7 +11,7 @@ Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "owgw.fullname" -}}
{{- define "ucentralgw.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
@@ -27,6 +27,6 @@ If release name contains chart name it will be used as a full name.
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "owgw.chart" -}}
{{- define "ucentralgw.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

View File

@@ -3,10 +3,10 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "owgw.fullname" . }}
name: {{ include "ucentralgw.fullname" . }}
labels:
app.kubernetes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kubernetes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
@@ -15,34 +15,28 @@ spec:
type: {{ .Values.strategyType }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "owgw.name" . }}
app.kubernetes.io/name: {{ include "ucentralgw.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- with .Values.services.owgw.labels }}
{{- with .Values.services.ucentralgw.labels }}
{{- toYaml . | nindent 6 }}
{{- end }}
template:
metadata:
annotations:
checksum/config: {{ include "owgw.config" . | sha256sum }}
{{- if .Values.podSecurityPolicy.enabled }}
kubernetes.io/psp: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
{{- end }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
checksum/config: {{ include "ucentralgw.config" . | sha256sum }}
labels:
app.kubernetes.io/name: {{ include "owgw.name" . }}
app.kubernetes.io/name: {{ include "ucentralgw.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- with .Values.services.owgw.labels }}
{{- with .Values.services.ucentralgw.labels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
containers:
- name: owgw
image: "{{ .Values.images.owgw.repository }}:{{ .Values.images.owgw.tag }}"
imagePullPolicy: {{ .Values.images.owgw.pullPolicy }}
- name: ucentralgw
image: "{{ .Values.images.ucentralgw.repository }}:{{ .Values.images.ucentralgw.tag }}"
imagePullPolicy: {{ .Values.images.ucentralgw.pullPolicy }}
env:
- name: KUBERNETES_DEPLOYED
@@ -55,19 +49,19 @@ spec:
- name: {{ $key }}
valueFrom:
secretKeyRef:
name: {{ include "owgw.fullname" $root }}-env
name: {{ include "ucentralgw.fullname" $root }}-env
key: {{ $key }}
{{- end }}
ports:
{{- range $port, $portValue := .Values.services.owgw.ports }}
{{- range $port, $portValue := .Values.services.ucentralgw.ports }}
- name: {{ $port }}
containerPort: {{ $portValue.targetPort }}
protocol: {{ $portValue.protocol }}
{{- end }}
volumeMounts:
{{- range .Values.volumes.owgw }}
{{- range .Values.volumes.ucentralgw }}
- name: {{ .name }}
mountPath: {{ .mountPath }}
{{- if .subPath }}
@@ -75,13 +69,13 @@ spec:
{{- end }}
{{- end }}
{{- if .Values.checks.owgw.liveness }}
{{- if .Values.checks.ucentralgw.liveness }}
livenessProbe:
{{- toYaml .Values.checks.owgw.liveness | nindent 12 }}
{{- toYaml .Values.checks.ucentralgw.liveness | nindent 12 }}
{{- end }}
{{- if .Values.checks.owgw.readiness }}
{{- if .Values.checks.ucentralgw.readiness }}
readinessProbe:
{{- toYaml .Values.checks.owgw.readiness | nindent 12 }}
{{- toYaml .Values.checks.ucentralgw.readiness | nindent 12 }}
{{- end }}
{{- with .Values.resources }}
@@ -89,15 +83,10 @@ spec:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.securityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
imagePullSecrets:
{{- range $image, $imageValue := .Values.images }}
{{- if $imageValue.regcred }}
- name: {{ include "owgw.fullname" $root }}-{{ $image }}-regcred
- name: {{ include "ucentralgw.fullname" $root }}-{{ $image }}-regcred
{{- end }}
{{- end }}

View File

@@ -5,10 +5,10 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ include "owgw.fullname" $root }}-{{ $ingress }}
name: {{ include "ucentralgw.fullname" $root }}-{{ $ingress }}
labels:
app.kubernetes.io/name: {{ include "owgw.name" $root }}
helm.sh/chart: {{ include "owgw.chart" $root }}
app.kubernetes.io/name: {{ include "ucentralgw.name" $root }}
helm.sh/chart: {{ include "ucentralgw.chart" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
app.kubernetes.io/managed-by: {{ $root.Release.Service }}
{{- with $ingressValue.annotations }}
@@ -37,7 +37,7 @@ spec:
{{- range $ingressValue.paths }}
- path: {{ .path }}
backend:
serviceName: {{ include "owgw.fullname" $root }}-{{ .serviceName }}
serviceName: {{ include "ucentralgw.fullname" $root }}-{{ .serviceName }}
servicePort: {{ .servicePort }}
{{- end }}
{{- end }}

View File

@@ -1,28 +0,0 @@
{{- if .Values.podSecurityPolicy.enabled }}
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
labels:
app.kubernetes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
allowedUnsafeSysctls:
{{- range $unsafeSysctl := .Values.securityContext.sysctls }}
- {{ $unsafeSysctl.name }}
{{- end }}
privileged: false
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
{{- end }}

View File

@@ -3,10 +3,10 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ template "owgw.fullname" . }}-pvc
name: {{ template "ucentralgw.fullname" . }}-pvc
labels:
app.kubernetes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kubernetes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- with .Values.persistence.annotations }}

View File

@@ -1,16 +0,0 @@
{{- if .Values.podSecurityPolicy.enabled }}
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl
rules:
- apiGroups:
- policy
resources:
- podsecuritypolicies
verbs:
- use
resourceNames:
- {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl
{{- end }}

View File

@@ -1,15 +0,0 @@
{{- if .Values.podSecurityPolicy.enabled }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl-to-default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl
subjects:
- kind: ServiceAccount
name: default
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -2,11 +2,11 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kuberentes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "owgw.fullname" . }}-certs-cas
name: {{ include "ucentralgw.fullname" . }}-certs-cas
kind: Secret
type: Opaque
data:

View File

@@ -2,11 +2,11 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kuberentes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "owgw.fullname" . }}-certs
name: {{ include "ucentralgw.fullname" . }}-certs
kind: Secret
type: Opaque
data:

View File

@@ -2,12 +2,12 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kuberentes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "owgw.fullname" . }}-config
name: {{ include "ucentralgw.fullname" . }}-config
kind: Secret
type: Opaque
data:
owgw.properties: {{ include "owgw.config" . | b64enc }}
ucentralgw.properties: {{ include "ucentralgw.config" . | b64enc }}

View File

@@ -2,11 +2,11 @@
apiVersion: v1
metadata:
labels:
app.kuberentes.io/name: {{ include "owgw.name" . }}
helm.sh/chart: {{ include "owgw.chart" . }}
app.kuberentes.io/name: {{ include "ucentralgw.name" . }}
helm.sh/chart: {{ include "ucentralgw.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
name: {{ include "owgw.fullname" . }}-env
name: {{ include "ucentralgw.fullname" . }}-env
kind: Secret
type: Opaque
data:

View File

@@ -10,11 +10,11 @@ kind: Secret
type: kubernetes.io/dockerconfigjson
metadata:
labels:
app.kuberentes.io/name: {{ include "owgw.name" $root }}
helm.sh/chart: {{ include "owgw.chart" $root }}
app.kuberentes.io/name: {{ include "ucentralgw.name" $root }}
helm.sh/chart: {{ include "ucentralgw.chart" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
app.kubernetes.io/managed-by: {{ $root.Release.Service }}
name: {{ include "owgw.fullname" $root }}-{{ $image }}-regcred
name: {{ include "ucentralgw.fullname" $root }}-{{ $image }}-regcred
data:
.dockerconfigjson: {{ template "imagePullSecret" $imageValue.regcred }}
{{- end }}

View File

@@ -4,14 +4,14 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "owgw.fullname" $root }}-{{ $service }}
name: {{ include "ucentralgw.fullname" $root }}-{{ $service }}
{{- with $serviceValue.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
labels:
app.kubernetes.io/name: {{ include "owgw.name" $root }}
helm.sh/chart: {{ include "owgw.chart" $root }}
app.kubernetes.io/name: {{ include "ucentralgw.name" $root }}
helm.sh/chart: {{ include "ucentralgw.chart" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
app.kubernetes.io/managed-by: {{ $root.Release.Service }}
@@ -39,7 +39,7 @@ spec:
{{- end }}
{{- end }}
selector:
app.kubernetes.io/name: {{ include "owgw.name" $root }}
app.kubernetes.io/name: {{ include "ucentralgw.name" $root }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
{{- with $serviceValue.labels }}
{{- toYaml . | nindent 4 }}

View File

@@ -6,9 +6,9 @@ nameOverride: ""
fullnameOverride: ""
images:
owgw:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owgw
tag: v2.4.0
ucentralgw:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/ucentralgw
tag: master
pullPolicy: Always
# regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
@@ -16,7 +16,7 @@ images:
# password: password
services:
owgw:
ucentralgw:
type: LoadBalancer
ports:
websocket:
@@ -37,16 +37,15 @@ services:
protocol: TCP
checks:
owgw:
ucentralgw:
liveness:
httpGet:
path: /
port: 16102
readiness:
exec:
command:
- /readiness_check
failureThreshold: 1
httpGet:
path: /
port: 16102
ingresses:
restapi:
@@ -58,7 +57,7 @@ ingresses:
- restapi.chart-example.local
paths:
- path: /
serviceName: owgw
serviceName: ucentralgw
servicePort: restapi
fileuploader:
enabled: false
@@ -69,34 +68,34 @@ ingresses:
- fileuploader.chart-example.local
paths:
- path: /
serviceName: owgw
serviceName: ucentralgw
servicePort: fileuploader
volumes:
owgw:
ucentralgw:
- name: config
mountPath: /owgw-data/owgw.properties
subPath: owgw.properties
mountPath: /ucentralgw-data/ucentralgw.properties
subPath: ucentralgw.properties
# Template below will be rendered in template
volumeDefinition: |
secret:
secretName: {{ include "owgw.fullname" . }}-config
secretName: {{ include "ucentralgw.fullname" . }}-config
- name: certs
mountPath: /owgw-data/certs
mountPath: /ucentralgw-data/certs
volumeDefinition: |
secret:
secretName: {{ include "owgw.fullname" . }}-certs
secretName: {{ include "ucentralgw.fullname" . }}-certs
- name: certs-cas
mountPath: /owgw-data/certs/cas
mountPath: /ucentralgw-data/certs/cas
volumeDefinition: |
secret:
secretName: {{ include "owgw.fullname" . }}-certs-cas
secretName: {{ include "ucentralgw.fullname" . }}-certs-cas
# Change this if you want to use another volume type
- name: persist
mountPath: /owgw-data/persist
mountPath: /ucentralgw-data/persist
volumeDefinition: |
persistentVolumeClaim:
claimName: {{ template "owgw.fullname" . }}-pvc
claimName: {{ template "ucentralgw.fullname" . }}-pvc
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
@@ -110,31 +109,12 @@ resources: {}
# cpu: 100m
# memory: 128Mi
securityContext:
fsGroup: 101
# Usage of unsafe sysctls requires multiple things:
# - allow these unsafe sysctls on kubelet level (by adding --allowed-unsafe-sysctls flag)
# - enabling addition of PodSecurityContext setting podSecurityPolicy.enabled to "true" below
# - uncommenting parameters below
#sysctls:
#- name: net.ipv4.tcp_keepalive_intvl
# value: "5"
#- name: net.ipv4.tcp_keepalive_probes
# value: "2"
#- name: net.ipv4.tcp_keepalive_time
# value: "45"
nodeSelector: {}
tolerations: []
affinity: {}
podAnnotations: {}
podSecurityPolicy:
enabled: false
persistence:
enabled: true
# storageClassName: "-"
@@ -145,71 +125,63 @@ persistence:
# Application
public_env_variables:
OWGW_ROOT: /owgw-data
OWGW_CONFIG: /owgw-data
# Environment variables required for the readiness checks using script
FLAGS: "-s --connect-timeout 3"
# NOTE in order for readiness check to use system info you need to set READINESS_METHOD to "systeminfo" and set OWSEC to the OWSEC's REST API endpoint
#READINESS_METHOD: systeminfo
#OWSEC: gw-qa01.cicd.lab.wlan.tip.build:16001
UCENTRALGW_ROOT: /ucentralgw-data
UCENTRALGW_CONFIG: /ucentralgw-data
secret_env_variables:
# NOTE in order for readiness check to use system info method you need to override these values to the real OWSEC credentials
OWSEC_USERNAME: tip@ucentral.com
OWSEC_PASSWORD: openwifi
secret_env_variables: {}
configProperties:
# -> Public part
# Websocket
ucentral.websocket.host.0.backlog: 500
ucentral.websocket.host.0.rootca: $OWGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer: $OWGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert: $OWGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key: $OWGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas: $OWGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas: $OWGW_ROOT/certs/cas
ucentral.websocket.host.0.rootca: $UCENTRALGW_ROOT/certs/root.pem
ucentral.websocket.host.0.issuer: $UCENTRALGW_ROOT/certs/issuer.pem
ucentral.websocket.host.0.cert: $UCENTRALGW_ROOT/certs/websocket-cert.pem
ucentral.websocket.host.0.key: $UCENTRALGW_ROOT/certs/websocket-key.pem
ucentral.websocket.host.0.clientcas: $UCENTRALGW_ROOT/certs/clientcas.pem
ucentral.websocket.host.0.cas: $UCENTRALGW_ROOT/certs/cas
ucentral.websocket.host.0.address: "*"
ucentral.websocket.host.0.port: 15002
ucentral.websocket.host.0.security: strict
ucentral.websocket.maxreactors: 20
# REST API
openwifi.restapi.host.0.backlog: 100
openwifi.restapi.host.0.security: relaxed
openwifi.restapi.host.0.rootca: $OWGW_ROOT/certs/restapi-ca.pem
openwifi.restapi.host.0.address: "*"
openwifi.restapi.host.0.port: 16002
openwifi.restapi.host.0.cert: $OWGW_ROOT/certs/restapi-cert.pem
openwifi.restapi.host.0.key: $OWGW_ROOT/certs/restapi-key.pem
openwifi.internal.restapi.host.0.backlog: 100
openwifi.internal.restapi.host.0.security: relaxed
openwifi.internal.restapi.host.0.rootca: $OWGW_ROOT/certs/restapi-ca.pem
openwifi.internal.restapi.host.0.address: "*"
openwifi.internal.restapi.host.0.port: 17002
openwifi.internal.restapi.host.0.cert: $OWGW_ROOT/certs/restapi-cert.pem
openwifi.internal.restapi.host.0.key: $OWGW_ROOT/certs/restapi-key.pem
ucentral.restapi.host.0.backlog: 100
ucentral.restapi.host.0.security: relaxed
ucentral.restapi.host.0.rootca: $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.restapi.host.0.address: "*"
ucentral.restapi.host.0.port: 16002
ucentral.restapi.host.0.cert: $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.restapi.host.0.key: $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.internal.restapi.host.0.backlog: 100
ucentral.internal.restapi.host.0.security: relaxed
ucentral.internal.restapi.host.0.rootca: $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.internal.restapi.host.0.address: "*"
ucentral.internal.restapi.host.0.port: 17002
ucentral.internal.restapi.host.0.cert: $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.internal.restapi.host.0.key: $UCENTRALGW_ROOT/certs/restapi-key.pem
# File uploader
openwifi.fileuploader.host.0.backlog: 100
openwifi.fileuploader.host.0.rootca: $OWGW_ROOT/certs/restapi-ca.pem
openwifi.fileuploader.host.0.security: relaxed
openwifi.fileuploader.host.0.address: "*"
openwifi.fileuploader.host.0.name: localhost
openwifi.fileuploader.host.0.port: 16003
openwifi.fileuploader.host.0.cert: $OWGW_ROOT/certs/restapi-cert.pem
openwifi.fileuploader.host.0.key: $OWGW_ROOT/certs/restapi-key.pem
openwifi.fileuploader.path: $OWGW_ROOT/uploads
openwifi.fileuploader.maxsize: 10000
ucentral.fileuploader.host.0.backlog: 100
ucentral.fileuploader.host.0.rootca: $UCENTRALGW_ROOT/certs/restapi-ca.pem
ucentral.fileuploader.host.0.security: relaxed
ucentral.fileuploader.host.0.address: "*"
ucentral.fileuploader.host.0.name: localhost
ucentral.fileuploader.host.0.port: 16003
ucentral.fileuploader.host.0.cert: $UCENTRALGW_ROOT/certs/restapi-cert.pem
ucentral.fileuploader.host.0.key: $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.fileuploader.path: $UCENTRALGW_ROOT/uploads
ucentral.fileuploader.maxsize: 10000
# Auto provisioning
openwifi.autoprovisioning: "true"
openwifi.devicetypes.0: AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
openwifi.devicetypes.1: SWITCH:edgecore_ecs4100-12ph
openwifi.devicetypes.2: IOT:esp32
ucentral.autoprovisioning: "true"
ucentral.devicetypes.0: AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
ucentral.devicetypes.1: SWITCH:edgecore_ecs4100-12ph
ucentral.devicetypes.2: IOT:esp32
oui.download.uri: https://linuxnet.ca/ieee/oui.txt
firmware.autoupdate.policy.default: auto
# Callback
openwifi.callback.enable: "false"
openwifi.callback.0.local: localhost:16001
openwifi.callback.0.remote: localhost:15055
openwifi.callback.0.topics: owfws
ucentral.callback.enable: "false"
ucentral.callback.0.local: localhost:16001
ucentral.callback.0.remote: localhost:15055
ucentral.callback.0.topics: ucentralfws
# rtty
rtty.enabled: "true"
rtty.server: localhost
@@ -220,12 +192,12 @@ configProperties:
alb.enable: "true"
alb.port: 16102
# Kafka
openwifi.kafka.enable: "false"
openwifi.kafka.group.id: gateway
openwifi.kafka.client.id: gateway1
openwifi.kafka.brokerlist: localhost:9092
openwifi.kafka.auto.commit: false
openwifi.kafka.queue.buffering.max.ms: 50
ucentral.kafka.enable: "false"
ucentral.kafka.group.id: gateway
ucentral.kafka.client.id: gateway1
ucentral.kafka.brokerlist: localhost:9092
ucentral.kafka.auto.commit: false
ucentral.kafka.queue.buffering.max.ms: 50
# Storage
storage.type: sqlite # (sqlite|postgresql|mysql|odbc)
## SQLite
@@ -236,31 +208,31 @@ configProperties:
storage.type.postgresql.maxsessions: 64
storage.type.postgresql.idletime: 60
storage.type.postgresql.host: localhost
storage.type.postgresql.database: owgw
storage.type.postgresql.database: ucentral
storage.type.postgresql.port: 5432
storage.type.postgresql.connectiontimeout: 60
## MySQL
storage.type.mysql.maxsessions: 64
storage.type.mysql.idletime: 60
storage.type.mysql.host: localhost
storage.type.mysql.database: owgw
storage.type.mysql.database: ucentral
storage.type.mysql.port: 3306
storage.type.mysql.connectiontimeout: 60
# System
openwifi.service.key: $OWGW_ROOT/certs/restapi-key.pem
openwifi.system.data: $OWGW_ROOT/persist
openwifi.system.debug: "true"
openwifi.system.uri.private: https://localhost:17002
openwifi.system.uri.public: https://localhost:16002
openwifi.system.commandchannel: /tmp/app_owgw
ucentral.service.key: $UCENTRALGW_ROOT/certs/restapi-key.pem
ucentral.system.data: $UCENTRALGW_ROOT/persist
ucentral.system.debug: "true"
ucentral.system.uri.private: https://localhost:17002
ucentral.system.uri.public: https://localhost:16002
ucentral.system.commandchannel: /tmp/app_ucentralgw
# Logging
logging.formatters.f1.class: PatternFormatter
logging.formatters.f1.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t"
logging.formatters.f1.pattern: "%s: [%p] %t"
logging.formatters.f1.times: UTC
logging.channels.c1.class: ConsoleChannel
logging.channels.c1.formatter: f1
logging.channels.c2.class: FileChannel
logging.channels.c2.path: /tmp/log_owgw
logging.channels.c2.path: /dev/stdout
logging.channels.c2.formatter.class: PatternFormatter
logging.channels.c2.formatter.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t"
logging.channels.c2.rotation: "20 M"
@@ -268,21 +240,21 @@ configProperties:
logging.channels.c2.purgeCount: 20
logging.channels.c3.class: ConsoleChannel
logging.channels.c3.pattern: "%s: [%p] %t"
logging.loggers.root.channel: c1
logging.loggers.root.channel: c2
logging.loggers.root.level: debug
# -> Secret part
# Websocket
ucentral.websocket.host.0.key.password: mypassword
# REST API
openwifi.restapi.host.0.key.password: mypassword
openwifi.internal.restapi.host.0.key.password: mypassword
ucentral.restapi.host.0.key.password: mypassword
ucentral.internal.restapi.host.0.key.password: mypassword
# File uploader
openwifi.fileuploader.host.0.key.password: mypassword
ucentral.fileuploader.host.0.key.password: mypassword
# Callback
openwifi.callback.id: qblat6dfDHxQAZ6yMe6MrypBpgRDhQrhUtTOovOXAKAWU8qOvjjKKiUai4t9hGjA
openwifi.callback.0.localkey: t2dEOc88OIxVDb94mw7SLcLocgnCzZzzFoQ4JJv3OCU9UO6Ou5ds5Dh4CfBnHgrk
openwifi.callback.0.remotekey: t2dEOc88OIxVDb94mw7SLcLocgnCzZzzFoQ4JJv3OCU9UO6Ou5ds5Dh4CfBnHgrk
ucentral.callback.id: qblat6dfDHxQAZ6yMe6MrypBpgRDhQrhUtTOovOXAKAWU8qOvjjKKiUai4t9hGjA
ucentral.callback.0.localkey: t2dEOc88OIxVDb94mw7SLcLocgnCzZzzFoQ4JJv3OCU9UO6Ou5ds5Dh4CfBnHgrk
ucentral.callback.0.remotekey: t2dEOc88OIxVDb94mw7SLcLocgnCzZzzFoQ4JJv3OCU9UO6Ou5ds5Dh4CfBnHgrk
# rtty
rtty.token: 96181c567b4d0d98c50f127230068fa8
# Storage
@@ -453,64 +425,3 @@ certsCAs:
L+/DtiR5fDVMNdBSGU89UNTi0wHY9+RFuNlIuvZC+x/swF0V9R5mN+ywquTPtDLA
5IOM7ItsRmen6u3qu+JXros54e4juQ==
-----END CERTIFICATE-----
# PostgreSQL (https://github.com/bitnami/charts/tree/master/bitnami/postgresql)
postgresql:
enabled: false
image:
registry: docker.io
repository: bitnami/postgresql
tag: 11.13.0-debian-10-r0
postgresqlPostgresPassword: "rootPassword"
postgresqlUsername: stephb
postgresqlPassword: snoopy99
postgresqlDatabase: owgw
persistence:
enabled: true
storageClass: ""
size: 8Gi
# MySQL (https://github.com/bitnami/charts/tree/master/bitnami/mysql)
mysql:
enabled: false
image:
registry: docker.io
repository: bitnami/mysql
tag: 8.0.26-debian-10-r10
auth:
rootPassword: rootPassword
database: owgw
username: stephb
password: snoopy99
primary:
persistence:
enabled: true
storageClass: ""
size: 8Gi
# MariaDB (https://github.com/bitnami/charts/tree/master/bitnami/mariadb)
mariadb:
enabled: false
image:
registry: docker.io
repository: bitnami/mariadb
tag: 10.5.12-debian-10-r0
auth:
rootPassword: rootPassword
database: owgw
username: stephb
password: snoopy99
primary:
persistence:
enabled: true
storageClass: ""
size: 8Gi

View File

@@ -2,7 +2,7 @@ openapi: 3.0.1
info:
title: uCentral gateway API
description: A process to manage configuration for devices.
version: 2.0.0
version: 0.0.8
license:
name: BSD3
url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
@@ -51,16 +51,6 @@ components:
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
ErrorDetails:
type: string
ErrorDescription:
@@ -101,9 +91,6 @@ components:
location:
type: string
format: uuid
venue:
type: string
format: uuid
serialNumber:
type: string
deviceType:
@@ -193,12 +180,6 @@ components:
rxBytes:
type: integer
format: int64
associations_2G:
type: integer
format: int64
associations_5G:
type: integer
format: int64
devicePassword:
type: string
lastContact:
@@ -267,12 +248,6 @@ components:
format: int64
firmware:
type: string
associations_2G:
type: integer
format: int64
associations_5G:
type: integer
format: int64
verifiedCertificate:
type: string
enum:
@@ -606,80 +581,6 @@ components:
items:
$ref: '#/components/schemas/CommandInfo'
DeviceDashboard:
type: object
properties:
snapshot:
type: integer
format: int64
numberOfDevices:
type: integer
format: int64
commands:
$ref: '#/components/schemas/TagIntPairList'
upTimes:
$ref: '#/components/schemas/TagIntPairList'
memoryUsed:
$ref: '#/components/schemas/TagIntPairList'
load1:
$ref: '#/components/schemas/TagIntPairList'
load5:
$ref: '#/components/schemas/TagIntPairList'
load15:
$ref: '#/components/schemas/TagIntPairList'
vendors:
$ref: '#/components/schemas/TagIntPairList'
status:
$ref: '#/components/schemas/TagIntPairList'
type:
$ref: '#/components/schemas/TagIntPairList'
deviceType:
$ref: '#/components/schemas/TagIntPairList'
healths:
$ref: '#/components/schemas/TagIntPairList'
certificates:
$ref: '#/components/schemas/TagIntPairList'
lastContact:
$ref: '#/components/schemas/TagIntPairList'
associations:
$ref: '#/components/schemas/TagIntPairList'
TelemetryStreamRequest:
type: object
properties:
serialNumber:
type: string
interval:
type: integer
example:
0 - means to stop streaming, values 1-120 in seconds.
types:
type: array
items:
type: string
enum:
- dhcp-snooping
- wire-frames
- state
uuid:
type: string
example:
only valid when terminating a stream
TelemetryStreamResponse:
type: object
properties:
serialNumber:
type: string
uuid:
type: string
format: uuid
uri:
type: string
format: uri
example:
wss://host.domain:port/endpoint
#########################################################################################
##
## These are endpoints that all services in the uCentral stack must provide
@@ -715,23 +616,6 @@ components:
items:
$ref: '#/components/schemas/TagValuePair'
TagIntPair:
type: object
properties:
tag:
type: string
value:
type: integer
format: int64
TagIntPairList:
type: object
properties:
tagList:
type: array
items:
$ref: '#/components/schemas/TagIntPair'
SystemCommandDetails:
type: object
properties:
@@ -765,107 +649,6 @@ components:
note:
type: string
SystemInfoResults:
type: object
properties:
version:
type: string
uptime:
type: integer
format: integer64
start:
type: integer
format: integer64
os:
type: string
processors:
type: integer
hostname:
type: string
certificates:
type: array
items:
type: object
properties:
filename:
type: string
expires:
type: integer
format: int64
SystemCommandSetLogLevel:
type: object
properties:
command:
type: string
enum:
- setloglevel
subsystems:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
SystemCommandReload:
type: object
properties:
command:
type: string
enum:
- reload
subsystems:
type: array
items:
type: string
example: these are the SubSystems names retrieve with the GetSubSystemsNamesResult.
SystemCommandGetLogLevels:
type: object
properties:
command:
type: string
enum:
- getloglevels
SystemGetLogLevelsResult:
type: object
properties:
taglist:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
SystemCommandGetLogLevelNames:
type: object
properties:
command:
type: string
enum:
- getloglevelnames
SystemCommandGetSubsystemNames:
type: object
properties:
command:
type: string
enum:
- getsubsystemnames
SystemCommandGetLogLevelNamesResult:
type: object
properties:
list:
type: array
items:
type: string
SystemGetSubSystemNamesResult:
type: object
properties:
taglist:
type: array
items:
$ref: '#/components/schemas/TagValuePair'
#########################################################################################
##
## End of uCentral system wide values
@@ -979,22 +762,6 @@ components:
password:
type: string
CapabilitiesModel:
type: object
properties:
deviceType:
type: string
capabilities:
type: string
CapabilitiesModelList:
type: object
properties:
devices:
type: array
items:
$ref: '#/components/schemas/CapabilitiesModel'
paths:
/devices:
get:
@@ -1038,7 +805,6 @@ paths:
name: countOnly
schema:
type: boolean
example: countOnly=true
- in: query
description: Return extra information with the device information
name: deviceWithStatus
@@ -1137,7 +903,7 @@ paths:
format: int64
responses:
204:
200:
description: Successfully deleted commands for the device.
content:
application/json:
@@ -1152,7 +918,7 @@ paths:
get:
tags:
- Commands
summary: Returns a specific command.
summary: Returns a specific command
description: Returns a specific command
operationId: getACommandDetails
parameters:
@@ -1177,7 +943,7 @@ paths:
delete:
tags:
- Commands
summary: Delete a specific command.
summary: Delete a specific command
description: Delete a specific command
operationId: deleteACommand
parameters:
@@ -1188,7 +954,7 @@ paths:
format: uuid
required: true
responses:
204:
200:
description: Delete command success
content:
application/json:
@@ -1203,8 +969,8 @@ paths:
get:
tags:
- Configurations
summary: Retrieve the lists of all default configurations.
description: Retrieve the lists of all default configurations.
summary: Retrieve the lists of all default configurations
description: Retrieve the lists of all default configurations
operationId: getDefaultConfigurations
responses:
@@ -1223,8 +989,8 @@ paths:
get:
tags:
- Configurations
summary: Retrieve a default configuration.
description: Retrieve a default configuration.
summary: Retrieve a default configuration
description: Retrieve a default configuration
operationId: getDefaultConfiguration
parameters:
- in: path
@@ -1247,8 +1013,8 @@ paths:
post:
tags:
- Configurations
summary: Create a default configuration.
description: Create a default configuration.
summary: Create a default configuration
description: Create a default configuration
operationId: createDefaultConfiguration
parameters:
- in: path
@@ -1283,7 +1049,7 @@ paths:
type: string
required: true
responses:
204:
200:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
@@ -1320,7 +1086,7 @@ paths:
get:
tags:
- Devices
summary: Retrieve information for a single device.
summary: Retrieve information for a single device
description: Retrieve all the inforamtion about a single device
operationId: getDeviceInformation
parameters:
@@ -1344,7 +1110,7 @@ paths:
post:
tags:
- Devices
summary: Create a new device.
summary: Creating a new device
operationId: createNewDevice
parameters:
- in: path
@@ -1352,11 +1118,6 @@ paths:
schema:
type: string
required: true
- in: query
name: validateOnly
schema:
type: boolean
required: false
requestBody:
description: Information used to create the new device
content:
@@ -1378,7 +1139,7 @@ paths:
put:
tags:
- Devices
summary: Update a device.
summary: Updating a new device
operationId: updateNewDevice
parameters:
- in: path
@@ -1407,7 +1168,7 @@ paths:
delete:
tags:
- Devices
summary: Delete a single device.
summary: Deleting a single device
operationId: deleteDevice
parameters:
- in: path
@@ -1416,7 +1177,7 @@ paths:
type: string
required: true
responses:
204:
200:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
@@ -1484,7 +1245,7 @@ paths:
delete:
tags:
- Commands
summary: Delete some device logs.
summary: Delete some device logs
operationId: deleteDeviceLogs
parameters:
- in: path
@@ -1511,7 +1272,7 @@ paths:
format: int64
responses:
204:
200:
description: Successfully deleted logs for the device.
content:
application/json:
@@ -1526,7 +1287,7 @@ paths:
get:
tags:
- Commands
summary: Get the latest health checks for a given device.
summary: Get the latest health checks for a given device
operationId: getDeviceHealthChecks
parameters:
- in: path
@@ -1573,7 +1334,7 @@ paths:
responses:
200:
description: Array of device health checks for this device
description: Array of device health checks for this device
content:
application/json:
schema:
@@ -1586,7 +1347,7 @@ paths:
delete:
tags:
- Commands
summary: Delete some device health checks.
summary: Delete some device health checks
operationId: deleteDeviceHealthChecks
parameters:
- in: path
@@ -1608,7 +1369,7 @@ paths:
required: false
responses:
204:
200:
description: Successfully deleted health checks for the device.
content:
application/json:
@@ -1623,7 +1384,7 @@ paths:
get:
tags:
- Commands
summary: Get the latest capabilities for a given device.
summary: Get the latest capabilities for a given device
operationId: getDeviceCapabilities
parameters:
- in: path
@@ -1646,7 +1407,7 @@ paths:
delete:
tags:
- Commands
summary: Delete the capabilities for a given device.
summary: Delete the capabilities for a given device
operationId: deleteDeviceCapabilities
parameters:
- in: path
@@ -1655,7 +1416,7 @@ paths:
type: string
required: true
responses:
204:
200:
description: List of logs for this device
content:
application/json:
@@ -1670,7 +1431,7 @@ paths:
get:
tags:
- Commands
summary: Get the latest statistics for a given device.
summary: Get the latest statistics for a given device
operationId: getDeviceStats
parameters:
- in: path
@@ -1738,7 +1499,7 @@ paths:
delete:
tags:
- Commands
summary: Get the latest statistics for a given device.
summary: Get the latest statistics for a given device
operationId: deleteDeviceStats
parameters:
- in: path
@@ -1760,7 +1521,7 @@ paths:
required: false
responses:
204:
200:
description: Array of statistics for this device
content:
application/json:
@@ -1775,7 +1536,7 @@ paths:
get:
tags:
- Commands
summary: Get the latest status for a given device.
summary: Get the latest status for a given device
operationId: getDeviceStatus
parameters:
- in: path
@@ -1825,7 +1586,7 @@ paths:
post:
tags:
- Commands
summary: Configure a device.
summary: Configura a device
operationId: updateConfigurationForADevice
parameters:
- in: path
@@ -1851,7 +1612,7 @@ paths:
post:
tags:
- Commands
summary: Upgrade a device.
summary: Upgrade a device
operationId: UpgradeDeviceFirmware
parameters:
- in: path
@@ -1877,7 +1638,7 @@ paths:
post:
tags:
- Commands
summary: Reboot a device.
summary: Upgrade a device
operationId: rebootDevice
parameters:
- in: path
@@ -1903,7 +1664,7 @@ paths:
post:
tags:
- Commands
summary: Factory reset a device.
summary: Factory reset a device a device
operationId: factoryReset
parameters:
- in: path
@@ -1929,7 +1690,7 @@ paths:
post:
tags:
- Commands
summary: Blink the LEDs on a device.
summary: Blink the LEDs on a device
operationId: ledsRequest
parameters:
- in: path
@@ -1955,7 +1716,7 @@ paths:
post:
tags:
- Commands
summary: Launch a trace for a device.
summary: Launch a trace for a device
operationId: traceRequest
parameters:
- in: path
@@ -1981,7 +1742,7 @@ paths:
post:
tags:
- Commands
summary: Launch a wifi scan for a device.
summary: Launch a wifi scan for a device
operationId: wifiscanRequest
parameters:
- in: path
@@ -2029,11 +1790,11 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/device/{serialNumber}/eventqueue:
/device/{serialNumber}/eventrequest:
post:
tags:
- Commands
summary: Request a list of queued events.
summary: Request a list of queued events
operationId: eventQueueRequest
parameters:
- in: path
@@ -2055,38 +1816,12 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/device/{serialNumber}/telemetry:
post:
tags:
- Commands
summary: Request a telemetry stream.
operationId: eventTelemetryStreamRequest
parameters:
- in: path
name: serialNumber
schema:
type: string
required: true
requestBody:
description: Message request details
content:
application/json:
schema:
$ref: '#/components/schemas/TelemetryStreamRequest'
responses:
200:
$ref: '#/components/schemas/TelemetryStreamResponse'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/ouis:
get:
tags:
- OUIs
operationId: getOUIs
summary: Get a list of OUIs.
summary: Get a list of OUIs
parameters:
- in: query
name: macList
@@ -2105,7 +1840,7 @@ paths:
get:
tags:
- Commands
summary: Get the rtty parameters to initiate a session.
summary: Get the rtty parameters to initiate a session
operationId: getRttySessionInfo
parameters:
- in: path
@@ -2129,7 +1864,7 @@ paths:
get:
tags:
- Files
summary: Get a file from the upload directory.
summary: Get a file from the upload directory
operationId: getUploadFile
parameters:
- in: path
@@ -2159,7 +1894,7 @@ paths:
delete:
tags:
- Files
summary: Delete a file from the upload directory.
summary: Delete a file from the upload directory
operationId: deleteUploadFidelete
parameters:
- in: path
@@ -2174,7 +1909,7 @@ paths:
type: string
required: true
responses:
204:
200:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
@@ -2186,7 +1921,7 @@ paths:
tags:
- Blacklist
summary: Returns a list blacklisted devices.
description: Get a list of blacklisted devices.
description: Get a list of blacklisteddevices.
operationId: getBlacklistDeviceList
parameters:
- in: query
@@ -2219,76 +1954,17 @@ paths:
404:
$ref: '#/components/responses/NotFound'
/blacklist/{serialNumber}:
get:
tags:
- Blacklist
summary: Returns a blacklist entry.
description: Get a list of blacklisted devices.
operationId: getBlacklistDevice
parameters:
- in: path
description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: serialNumber
schema:
type: string
required: true
responses:
200:
description: List blacklisted devices
content:
application/json:
schema:
$ref: '#/components/schemas/BlackDeviceInfo'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
post:
tags:
- Blacklist
summary: Create to the blacklist.
operationId: createBlackListDevice
parameters:
- in: path
description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: serialNumber
schema:
type: string
required: true
requestBody:
description: Add blacklisted device
content:
application/json:
schema:
$ref: '#/components/schemas/BlackDeviceInfo'
responses:
200:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- Blacklist
summary: Modify to the blacklist.
operationId: modifyBlackList
parameters:
- in: path
description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: serialNumber
schema:
type: string
required: true
summary: Adds to the blacklist
operationId: addToBlackList
requestBody:
description: Add blacklisted devices
content:
application/json:
schema:
$ref: '#/components/schemas/BlackDeviceInfo'
$ref: '#/components/schemas/BlackDeviceList'
responses:
200:
$ref: '#/components/responses/Success'
@@ -2300,114 +1976,99 @@ paths:
delete:
tags:
- Blacklist
summary: Delete from the blacklist.
summary: Delete from the blacklist
operationId: deleteFromBlackList
parameters:
- in: path
- in: query
description: Serial Number
name: serialNumber
schema:
type: string
required: true
responses:
204:
200:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/capabilities:
get:
tags:
- Devices
summary: Get the list of device types and capabilities.
operationId: getCapabilitiesList
responses:
200:
description: Successful command execution
content:
application/json:
schema:
$ref: '#/components/schemas/CapabilitiesModelList'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/deviceDashboard:
get:
tags:
- Dashboards
summary: Get the last version of the dashboard.
operationId: getDeviceDashboard
responses:
200:
$ref: '#/components/schemas/DeviceDashboard'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
#########################################################################################
##
## These are endpoints that all services in the uCentral stack must provide
##
#########################################################################################
/system:
post:
tags:
- System Commands
summary: Perform some system wide commands.
summary: Perform some systeme wide commands
operationId: systemCommand
requestBody:
description: Command details
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemCommandSetLogLevel'
- $ref: '#/components/schemas/SystemCommandReload'
- $ref: '#/components/schemas/SystemCommandGetLogLevels'
- $ref: '#/components/schemas/SystemCommandGetLogLevelNames'
- $ref: '#/components/schemas/SystemCommandGetSubsystemNames'
$ref: '#/components/schemas/SystemCommandDetails'
responses:
200:
description: Successful command execution
description: Successfull command execution
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemGetLogLevelsResult'
- $ref: '#/components/schemas/SystemCommandGetLogLevelNamesResult'
- $ref: '#/components/schemas/SystemGetSubSystemNamesResult'
$ref: '#/components/schemas/SystemCommandResults'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
get:
/callbackChannel:
post:
tags:
- System Commands
summary: Retrieve different values from the running service.
operationId: getSystemCommand
- Callback
summary: Generic callback hook
operationId: postCallback
parameters:
- in: query
description: Get a value
name: command
name: subscribe
schema:
type: boolean
required: false
- in: query
name: uri
schema:
type: string
enum:
- info
required: true
format: uri
- in: query
name: key
schema:
type: string
- in: query
name: topics
schema:
type: string
- in: query
name: id
schema:
type: string
- in: query
name: topic
schema:
type: string
requestBody:
description: A generic JSONDocument, may be empty too {}
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AnyPayload'
responses:
200:
description: Successful command execution
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemInfoResults'
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
$ref: '#/components/responses/NotFound'

View File

@@ -1,190 +0,0 @@
#
# uCentral protocol server for devices. This is where you point
# all your devices. You can replace the * for address by the specific
# address of one of your interfaces
#
ucentral.websocket.host.0.backlog = 500
ucentral.websocket.host.0.rootca = ${WEBSOCKET_HOST_ROOTCA}
ucentral.websocket.host.0.issuer = ${WEBSOCKET_HOST_ISSUER}
ucentral.websocket.host.0.cert = ${WEBSOCKET_HOST_CERT}
ucentral.websocket.host.0.key = ${WEBSOCKET_HOST_KEY}
ucentral.websocket.host.0.clientcas = ${WEBSOCKET_HOST_CLIENTCAS}
ucentral.websocket.host.0.cas = ${WEBSOCKET_HOST_CAS}
ucentral.websocket.host.0.address = *
ucentral.websocket.host.0.port = ${WEBSOCKET_HOST_PORT}
ucentral.websocket.host.0.security = strict
ucentral.websocket.host.0.key.password = ${WEBSOCKET_HOST_KEY_PASSWORD}
ucentral.websocket.maxreactors = 20
#
# REST API access
#
openwifi.restapi.host.0.backlog = 100
openwifi.restapi.host.0.security = relaxed
openwifi.restapi.host.0.rootca = ${RESTAPI_HOST_ROOTCA}
openwifi.restapi.host.0.address = *
openwifi.restapi.host.0.port = ${RESTAPI_HOST_PORT}
openwifi.restapi.host.0.cert = ${RESTAPI_HOST_CERT}
openwifi.restapi.host.0.key = ${RESTAPI_HOST_KEY}
openwifi.restapi.host.0.key.password = ${RESTAPI_HOST_KEY_PASSWORD}
openwifi.internal.restapi.host.0.backlog = 100
openwifi.internal.restapi.host.0.security = relaxed
openwifi.internal.restapi.host.0.rootca = ${INTERNAL_RESTAPI_HOST_ROOTCA}
openwifi.internal.restapi.host.0.address = *
openwifi.internal.restapi.host.0.port = ${INTERNAL_RESTAPI_HOST_PORT}
openwifi.internal.restapi.host.0.cert = ${INTERNAL_RESTAPI_HOST_CERT}
openwifi.internal.restapi.host.0.key = ${INTERNAL_RESTAPI_HOST_KEY}
openwifi.internal.restapi.host.0.key.password = ${INTERNAL_RESTAPI_HOST_KEY_PASSWORD}
#
# Used to upload files to the service.
# You should replace the 'name' vaalue with the IP address of your gateway or an FQDN
# that your devices can reach
#
openwifi.fileuploader.host.0.backlog = 100
openwifi.fileuploader.host.0.rootca = ${FILEUPLOADER_HOST_ROOTCA}
openwifi.fileuploader.host.0.security = relaxed
openwifi.fileuploader.host.0.address = *
openwifi.fileuploader.host.0.name = ${FILEUPLOADER_HOST_NAME}
openwifi.fileuploader.host.0.port = ${FILEUPLOADER_HOST_PORT}
openwifi.fileuploader.host.0.cert = ${FILEUPLOADER_HOST_CERT}
openwifi.fileuploader.host.0.key = ${FILEUPLOADER_HOST_KEY}
openwifi.fileuploader.host.0.key.password = ${FILEUPLOADER_HOST_KEY_PASSWORD}
openwifi.fileuploader.path = ${FILEUPLOADER_PATH}
openwifi.fileuploader.uri = ${FILEUPLOADER_URI}
openwifi.fileuploader.maxsize = 10000
#
# Generic section that all microservices must have
#
openwifi.service.key = ${SERVICE_KEY}
openwifi.service.key.password = ${SERVICE_KEY_PASSWORD}
openwifi.system.data = ${SYSTEM_DATA}
openwifi.system.debug = true
openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE}
openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC}
openwifi.system.uri.ui = ${SYSTEM_URI_UI}
openwifi.system.commandchannel = /tmp/app.ucentralgw
#
# Gateway Microservice Specific Section
#
openwifi.autoprovisioning = true
openwifi.devicetypes.0 = AP:linksys_ea8300,edgecore_eap101,linksys_e8450-ubi
openwifi.devicetypes.1 = SWITCH:edgecore_ecs4100-12ph
openwifi.devicetypes.2 = IOT:esp32
oui.download.uri = https://linuxnet.ca/ieee/oui.txt
firmware.autoupdate.policy.default = auto
simulatorid = ${SIMULATORID}
#
# rtty
#
rtty.enabled = ${RTTY_ENABLED}
rtty.server = ${RTTY_SERVER}
rtty.port = ${RTTY_PORT}
rtty.token = ${RTTY_TOKEN}
rtty.timeout = ${RTTY_TIMEOUT}
rtty.viewport = ${RTTY_VIEWPORT}
#############################
# Generic information for all micro services
#############################
#
# NLB Support
#
alb.enable = true
alb.port = 16102
#
# Kafka
#
openwifi.kafka.group.id = gateway
openwifi.kafka.client.id = gateway1
openwifi.kafka.enable = ${KAFKA_ENABLE}
openwifi.kafka.brokerlist = ${KAFKA_BROKERLIST}
openwifi.kafka.auto.commit = false
openwifi.kafka.queue.buffering.max.ms = 50
#
# This section select which form of persistence you need
# Only one selected at a time. If you select multiple, this service will die if a horrible
# death and might make your beer flat.
#
storage.type = ${STORAGE_TYPE}
storage.type.sqlite.db = devices.db
storage.type.sqlite.idletime = 120
storage.type.sqlite.maxsessions = 128
storage.type.postgresql.maxsessions = 64
storage.type.postgresql.idletime = 60
storage.type.postgresql.host = ${STORAGE_TYPE_POSTGRESQL_HOST}
storage.type.postgresql.username = ${STORAGE_TYPE_POSTGRESQL_USERNAME}
storage.type.postgresql.password = ${STORAGE_TYPE_POSTGRESQL_PASSWORD}
storage.type.postgresql.database = ${STORAGE_TYPE_POSTGRESQL_DATABASE}
storage.type.postgresql.port = ${STORAGE_TYPE_POSTGRESQL_PORT}
storage.type.postgresql.connectiontimeout = 60
storage.type.mysql.maxsessions = 64
storage.type.mysql.idletime = 60
storage.type.mysql.host = ${STORAGE_TYPE_MYSQL_HOST}
storage.type.mysql.username = ${STORAGE_TYPE_MYSQL_USERNAME}
storage.type.mysql.password = ${STORAGE_TYPE_MYSQL_PASSWORD}
storage.type.mysql.database = ${STORAGE_TYPE_MYSQL_DATABASE}
storage.type.mysql.port = ${STORAGE_TYPE_MYSQL_PORT}
storage.type.mysql.connectiontimeout = 60
archiver.enabled = true
archiver.schedule = 03:00
archiver.db.0.name = healthchecks
archiver.db.0.keep = 7
archiver.db.1.name = statistics
archiver.db.1.keep = 7
archiver.db.2.name = devicelogs
archiver.db.2.keep = 7
archiver.db.3.name = commandlist
archiver.db.3.keep = 7
########################################################################
########################################################################
#
# Logging: please leave as is for now.
#
########################################################################
logging.formatters.f1.class = PatternFormatter
logging.formatters.f1.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.formatters.f1.times = UTC
logging.channels.c1.class = ConsoleChannel
logging.channels.c1.formatter = f1
# This is where the logs will be written. This path MUST exist
logging.channels.c2.class = FileChannel
logging.channels.c2.path = $OWGW_ROOT/logs/log
logging.channels.c2.formatter.class = PatternFormatter
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.channels.c2.rotation = 20 M
logging.channels.c2.archive = timestamp
logging.channels.c2.purgeCount = 20
logging.channels.c3.class = ConsoleChannel
logging.channels.c3.pattern = %s: [%p] %t
# External Channel
logging.loggers.root.channel = c1
logging.loggers.root.level = debug
# Inline Channel with PatternFormatter
# logging.loggers.l1.name = logger1
# logging.loggers.l1.channel.class = ConsoleChannel
# logging.loggers.l1.channel.pattern = %s: [%p] %t
# logging.loggers.l1.level = information
# SplitterChannel
# logging.channels.splitter.class = SplitterChannel
# logging.channels.splitter.channels = l1,l2
# logging.loggers.l2.name = logger2
# logging.loggers.l2.channel = splitter

View File

@@ -1,22 +0,0 @@
[Unit]
Description=OpenWiFi Gateway Service
After=network-online.target docker.service
Wants=network-online.target
[Service]
Type=simple
Environment="OWGW_ROOT=/home/admin/dev/wlan-cloud-ucentralgw"
ExecStart=/home/admin/dev/wlan-cloud-ucentralgw/cmake-build/owgw
WorkingDirectory=/home/admin/dev/wlan-cloud-ucentralgw
# ExecReload=/bin/kill -s HUP $MAINPID
User=admin
# TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
# KillMode=process
LimitNOFILE=500000
LimitNPROC=500000
[Install]
WantedBy=multi-user.target

View File

@@ -1,65 +0,0 @@
#!/bin/bash
set -e
if [[ "$(which jq)" == "" ]]
then
echo "You need the package jq installed to use this script."
exit 1
fi
if [[ "$(which curl)" == "" ]]
then
echo "You need the package curl installed to use this script."
exit 1
fi
if [[ "${OWSEC}" == "" ]]
then
echo "You must set the variable OWSEC in order to use this script. Something like"
echo "OWSEC=security.isp.com:16001"
exit 1
fi
if [[ "${OWSEC_USERNAME}" == "" ]]
then
echo "You must set the variable OWSEC_USERNAME in order to use this script. Something like"
echo "OWSEC_USERNAME=tip@ucentral.com"
exit 1
fi
if [[ "${OWSEC_PASSWORD}" == "" ]]
then
echo "You must set the variable OWSEC_PASSWORD in order to use this script. Something like"
echo "OWSEC_PASSWORD=openwifi"
exit 1
fi
if [[ "${READINESS_METHOD}" == "systeminfo" ]]
then
# Get OAuth token from OWSEC and cache it or use cached one
payload="{ \"userId\" : \"$OWSEC_USERNAME\" , \"password\" : \"$OWSEC_PASSWORD\" }"
if [[ -f "/tmp/token" ]]
then
token=$(cat /tmp/token)
else
token=$(curl ${FLAGS} -X POST -H "Content-Type: application/json" -d "$payload" "https://${OWSEC}/api/v1/oauth2" | jq -r '.access_token')
fi
if [[ "${token}" == "" ]]
then
echo "Could not login. Please verify the host and username/password."
exit 13
fi
echo -n $token > /tmp/token
# Make systeminfo request to the local owgw instance
export RESTAPI_PORT=$(grep 'openwifi.restapi.host.0.port' $OWGW_CONFIG/owgw.properties | awk -F '=' '{print $2}' | xargs | envsubst)
curl ${FLAGS} -k -X GET "https://localhost:$RESTAPI_PORT/api/v1/system?command=info" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > /tmp/result.json
exit_code=$?
jq < /tmp/result.json
exit $exit_code
else
export ALB_PORT=$(grep 'alb.port' $OWGW_CONFIG/owgw.properties | awk -F '=' '{print $2}' | xargs | envsubst)
curl localhost:$ALB_PORT
fi

View File

@@ -1,4 +1,4 @@
#!/bin/bash
export OWGW_CONFIG=`pwd`
export OWGW_ROOT=`pwd`
export UCENTRALGW_CONFIG=`pwd`
export UCENTRALGW_ROOT=`pwd`

114
src/ALBHealthCheckServer.h Normal file
View File

@@ -0,0 +1,114 @@
//
// Created by stephane bourque on 2021-06-04.
//
#ifndef UCENTRALGW_ALBHEALTHCHECKSERVER_H
#define UCENTRALGW_ALBHEALTHCHECKSERVER_H
#include <memory>
#include <iostream>
#include <fstream>
#include <sstream>
#include "Poco/Thread.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Logger.h"
#include "Daemon.h"
#include "SubSystemServer.h"
namespace uCentral {
class ALBRequestHandler: public Poco::Net::HTTPRequestHandler
/// Return a HTML document with the current date and time.
{
public:
ALBRequestHandler(Poco::Logger & L)
: Logger_(L)
{
}
void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response)
{
Logger_.information(Poco::format("ALB-REQUEST(%s): New ALB request.",Request.clientAddress().toString()));
Response.setChunkedTransferEncoding(true);
Response.setContentType("text/html");
Response.setDate(Poco::Timestamp());
Response.setStatus(Poco::Net::HTTPResponse::HTTP_OK);
Response.setKeepAlive(true);
Response.set("Connection","keep-alive");
Response.setVersion(Poco::Net::HTTPMessage::HTTP_1_1);
std::ostream &Answer = Response.send();
Answer << "uCentralGW Alive and kicking!" ;
}
private:
Poco::Logger & Logger_;
};
class ALBRequestHandlerFactory: public Poco::Net::HTTPRequestHandlerFactory
{
public:
explicit ALBRequestHandlerFactory(Poco::Logger & L):
Logger_(L)
{
}
ALBRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request) override
{
if (request.getURI() == "/")
return new ALBRequestHandler(Logger_);
else
return nullptr;
}
private:
Poco::Logger &Logger_;
};
class ALBHealthCheckServer : public SubSystemServer {
public:
ALBHealthCheckServer() noexcept:
SubSystemServer("ALBHealthCheckServer", "ALB-SVR", "alb")
{
}
static ALBHealthCheckServer *instance() {
if (instance_ == nullptr) {
instance_ = new ALBHealthCheckServer;
}
return instance_;
}
int Start() {
if(Daemon()->ConfigGetBool("alb.enable",false)) {
Port_ = (int)Daemon()->ConfigGetInt("alb.port",15015);
Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_);
auto Params = new Poco::Net::HTTPServerParams;
Server_ = std::make_unique<Poco::Net::HTTPServer>(new ALBRequestHandlerFactory(Logger_), *Socket_, Params);
Server_->start();
}
return 0;
}
void Stop() {
if(Server_)
Server_->stop();
}
private:
static ALBHealthCheckServer *instance_;
std::unique_ptr<Poco::Net::HTTPServer> Server_;
std::unique_ptr<Poco::Net::ServerSocket> Socket_;
int Port_ = 0;
};
inline ALBHealthCheckServer * ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); }
inline class ALBHealthCheckServer * ALBHealthCheckServer::instance_ = nullptr;
}
#endif // UCENTRALGW_ALBHEALTHCHECKSERVER_H

View File

@@ -1,61 +0,0 @@
//
// Created by stephane bourque on 2021-10-23.
//
#include "framework/MicroService.h"
#include "RESTAPI/RESTAPI_blacklist.h"
#include "RESTAPI/RESTAPI_blacklist_list.h"
#include "RESTAPI/RESTAPI_command.h"
#include "RESTAPI/RESTAPI_commands.h"
#include "RESTAPI/RESTAPI_default_configuration.h"
#include "RESTAPI/RESTAPI_default_configurations.h"
#include "RESTAPI/RESTAPI_deviceDashboardHandler.h"
#include "RESTAPI/RESTAPI_device_commandHandler.h"
#include "RESTAPI/RESTAPI_device_handler.h"
#include "RESTAPI/RESTAPI_devices_handler.h"
#include "RESTAPI/RESTAPI_file.h"
#include "RESTAPI/RESTAPI_ouis.h"
#include "RESTAPI/RESTAPI_capabilities_handler.h"
#include "RESTAPI/RESTAPI_TelemetryWebSocket.h"
#include "RESTAPI/RESTAPI_webSocketServer.h"
namespace OpenWifi {
Poco::Net::HTTPRequestHandler * RESTAPI_external_server(const char *Path, RESTAPIHandler::BindingMap &Bindings,
Poco::Logger & L, RESTAPI_GenericServer & S) {
return RESTAPI_Router<
RESTAPI_devices_handler,
RESTAPI_device_handler,
RESTAPI_device_commandHandler,
RESTAPI_default_configurations,
RESTAPI_default_configuration,
RESTAPI_command,
RESTAPI_commands,
RESTAPI_ouis,
RESTAPI_file,
RESTAPI_system_command,
RESTAPI_deviceDashboardHandler,
RESTAPI_webSocketServer,
RESTAPI_blacklist,
RESTAPI_blacklist_list,
RESTAPI_capabilities_handler,
RESTAPI_TelemetryWebSocket>(Path,Bindings,L, S);
}
Poco::Net::HTTPRequestHandler * RESTAPI_internal_server(const char *Path, RESTAPIHandler::BindingMap &Bindings,
Poco::Logger & L, RESTAPI_GenericServer & S) {
return RESTAPI_Router_I<
RESTAPI_devices_handler,
RESTAPI_device_handler,
RESTAPI_device_commandHandler,
RESTAPI_default_configurations,
RESTAPI_default_configuration,
RESTAPI_command,
RESTAPI_commands,
RESTAPI_ouis,
RESTAPI_file, RESTAPI_blacklist,
RESTAPI_blacklist_list>(Path,Bindings,L, S);
}
}

59
src/AuthClient.cpp Normal file
View File

@@ -0,0 +1,59 @@
//
// Created by stephane bourque on 2021-06-30.
//
#include <utility>
#include "AuthClient.h"
#include "RESTAPI_SecurityObjects.h"
#include "Daemon.h"
#include "OpenAPIRequest.h"
namespace uCentral {
class AuthClient * AuthClient::instance_ = nullptr;
int AuthClient::Start() {
return 0;
}
void AuthClient::Stop() {
}
void AuthClient::RemovedCachedToken(const std::string &Token) {
SubMutexGuard G(Mutex_);
UserCache_.erase(Token);
}
bool IsTokenExpired(const SecurityObjects::WebToken &T) {
return ((T.expires_in_+T.created_)<std::time(nullptr));
}
bool AuthClient::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) {
SubMutexGuard G(Mutex_);
auto User = UserCache_.find(SessionToken);
if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) {
UInfo = User->second;
return true;
} else {
Types::StringPairVec QueryData;
QueryData.push_back(std::make_pair("token",SessionToken));
OpenAPIRequestGet Req(uSERVICE_SECURITY,
"/api/v1/validateToken",
QueryData,
5000);
Poco::JSON::Object::Ptr Response;
if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) {
if(Response->has("tokenInfo") && Response->has("userInfo")) {
SecurityObjects::UserInfoAndPolicy P;
P.from_json(Response);
UserCache_[SessionToken] = P;
UInfo = P;
}
return true;
}
}
return false;
}
}

45
src/AuthClient.h Normal file
View File

@@ -0,0 +1,45 @@
//
// Created by stephane bourque on 2021-06-30.
//
#ifndef UCENTRALGW_AUTHCLIENT_H
#define UCENTRALGW_AUTHCLIENT_H
#include "Poco/JSON/Object.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/JWT/Signer.h"
#include "Poco/SHA2Engine.h"
#include "RESTAPI_SecurityObjects.h"
#include "SubSystemServer.h"
namespace uCentral {
class AuthClient : public SubSystemServer {
public:
explicit AuthClient() noexcept:
SubSystemServer("Authentication", "AUTH-CLNT", "authentication")
{
}
static AuthClient *instance() {
if (instance_ == nullptr) {
instance_ = new AuthClient;
}
return instance_;
}
int Start() override;
void Stop() override;
bool IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo );
void RemovedCachedToken(const std::string &Token);
private:
static AuthClient *instance_;
SecurityObjects::UserInfoCache UserCache_;
};
inline AuthClient * AuthClient() { return AuthClient::instance(); }
}
#endif // UCENTRALGW_AUTHCLIENT_H

170
src/CallbackManager.cpp Normal file
View File

@@ -0,0 +1,170 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "CallbackManager.h"
#include "Daemon.h"
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/URI.h"
namespace uCentral {
class CallbackManager *CallbackManager::instance_ = nullptr;
CallbackManager::CallbackManager() noexcept:
SubSystemServer("CallbackManager", "CBACK-MGR", "ucentral.callback")
{
}
int CallbackManager::Start() {
Logger_.notice("Starting...");
Mgr_.start(*this);
return 0;
}
bool CallbackManager::InitHosts() {
// get all the hosts we are registering with and register ourselves...
if(Daemon()->ConfigGetString("ucentral.callback.enable","false") == "false") {
Logger_.information("CALLBACK system disabled.");
return false;
}
MyIDCallbackId_ = Daemon()->ConfigGetString("ucentral.callback.id","");
if(MyIDCallbackId_.empty()) {
Logger_.information("CALLBACK system disabled. No CallbackID present in ucentral.callback.id");
return false;
}
// now get all the hosts we need to register with...
auto Index = 0 ;
while(true) {
std::string root = "ucentral.callback." + std::to_string(Index);
auto Local = Daemon()->ConfigGetString(root + ".local","");
auto Remote = Daemon()->ConfigGetString(root + ".remote","");
auto LocalKey = Daemon()->ConfigGetString(root + ".localkey","");
auto RemoteKey = Daemon()->ConfigGetString(root + ".localkey","");
auto Topics = Daemon()->ConfigGetString(root + ".topics","");
if(Local.empty() || Remote.empty() || LocalKey.empty() || Topics.empty() || RemoteKey.empty())
break;
CallbackHost H{
.Local = "https://" + Local + "/api/v1/callbackChannel",
.LocalKey = LocalKey,
.Remote = "https://" + Remote + "/api/v1/callbackChannel",
.RemoteKey = RemoteKey,
.Topics = Topics,
.LastContact = 0,
.NextContact = 0,
.Registered = false
};
Hosts_.push_back(H);
Index++;
}
return true;
}
bool DoRequest(Poco::Net::HTTPSClientSession& Session, Poco::Net::HTTPRequest& Request, Poco::Net::HTTPResponse& Response)
{
std::string Content{R"lit({ "comment" : "registration from uCentralGW" })lit"};
std::stringstream Body(Content);
Request.setContentType("application/json");
Request.setContentLength(Content.length());
std::ostream& OS = Session.sendRequest(Request);
Poco::StreamCopier::copyStream(Body, OS);
Session.receiveResponse(Response);
return (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK);
}
bool CallbackManager::RegisterHosts() {
if(MyIDCallbackId_.empty())
return false;
for(auto &i:Hosts_) {
if(!i.Registered || (time(nullptr)-i.LastContact)>300) {
Poco::URI Uri(i.Remote);
Uri.addQueryParameter("subscribe", "true");
Uri.addQueryParameter("uri", i.Local);
Uri.addQueryParameter("topics", i.Topics);
Uri.addQueryParameter("key", i.LocalKey);
Uri.addQueryParameter("id", MyIDCallbackId_);
Poco::Net::HTTPSClientSession Session(Uri.getHost(), Uri.getPort());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_POST,
Uri.getPathAndQuery(),
Poco::Net::HTTPMessage::HTTP_1_1);
Request.add("X-API-KEY", i.RemoteKey);
Poco::Net::HTTPResponse Response;
i.LastContact = time(nullptr);
i.Registered = DoRequest(Session, Request, Response);
}
}
return true;
}
void CallbackManager::run() {
Running_ = true;
uint64_t LastContact = time(nullptr);
InitHosts();
RegisterHosts();
while(Running_) {
if((time(nullptr) - LastContact) >300) {
RegisterHosts();
LastContact = time(nullptr);
}
if(Calls_.empty()) {
Poco::Thread::sleep(2000);
} else {
CallBackMessage E;
{
SubMutexGuard Guard(Mutex_);
E = Calls_.front();
}
std::cout << "Call: " << E.Message << " JSON:" << E.JSONDoc << std::endl;
{
SubMutexGuard Guard(Mutex_);
Calls_.pop();
}
}
}
}
void CallbackManager::Stop() {
SubMutexGuard Guard(Mutex_);
Logger_.notice("Stopping...");
Running_ = false ;
Mgr_.join();
}
bool CallbackManager::AddMessage(const CallBackMessage &Msg) {
SubMutexGuard Guard(Mutex_);
Calls_.push(Msg);
return true;
}
} // end of namespace

65
src/CallbackManager.h Normal file
View File

@@ -0,0 +1,65 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRALGW_CALLBACKMANAGER_H
#define UCENTRALGW_CALLBACKMANAGER_H
#include <queue>
#include "SubSystemServer.h"
namespace uCentral {
class CallbackManager : public SubSystemServer, Poco::Runnable {
public:
struct CallBackMessage {
std::string Message;
std::string JSONDoc;
};
struct CallbackHost {
std::string Local;
std::string LocalKey;
std::string Remote;
std::string RemoteKey;
std::string Topics;
uint64_t LastContact;
uint64_t NextContact;
bool Registered;
};
static CallbackManager *instance() {
if (instance_ == nullptr) {
instance_ = new CallbackManager;
}
return instance_;
}
void run() override;
int Start() override;
void Stop() override;
bool AddMessage(const CallBackMessage &Msg);
bool InitHosts();
bool RegisterHosts();
private:
static CallbackManager *instance_;
Poco::Thread Mgr_;
std::atomic_bool Running_ = false;
std::queue<CallBackMessage> Calls_;
std::string MyIDCallbackId_;
std::vector<CallbackHost> Hosts_;
CallbackManager() noexcept;
};
inline CallbackManager * CallbackManager() { return CallbackManager::instance(); }
} // end of namespace
#endif // UCENTRALGW_CALLBACKMANAGER_H

View File

@@ -7,15 +7,14 @@
//
#include <fstream>
#include "CentralConfig.h"
#include "Daemon.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "Poco/File.h"
#include "CentralConfig.h"
#include "framework/MicroService.h"
#include "Daemon.h"
namespace OpenWifi::Config {
namespace uCentral::Config {
static std::string DefaultConfiguration;
@@ -120,7 +119,7 @@ namespace OpenWifi::Config {
})lit"};
void SetBasicConfigFile() {
Poco::File DefaultConfigFileName{MicroService::instance().DataDir()+"/default_config.json"};
Poco::File DefaultConfigFileName{Daemon()->DataDir()+"/default_config.json"};
DefaultConfiguration = BasicConfig;
std::ofstream F;
F.open(DefaultConfigFileName.path(),std::ios::binary);
@@ -135,7 +134,7 @@ namespace OpenWifi::Config {
void Config::Init() {
if(DefaultConfiguration.empty()) {
// open the file
Poco::File DefaultConfigFileName{MicroService::instance().DataDir()+"/default_config.json"};
Poco::File DefaultConfigFileName{Daemon()->DataDir()+"/default_config.json"};
try {
if (!DefaultConfigFileName.exists()) {
SetBasicConfigFile();
@@ -233,7 +232,7 @@ namespace OpenWifi::Config {
}
catch ( const Poco::Exception & E )
{
Daemon()->logger().log(E);
uCentral::Daemon::instance()->logger().warning(Poco::format("%s: Failed with: %s", std::string(__func__) , E.displayText()));
}
}

View File

@@ -12,7 +12,7 @@
#include <string>
#include "Poco/JSON/Object.h"
namespace OpenWifi::Config {
namespace uCentral::Config {
class Config {
public:

164
src/CommandChannel.cpp Normal file
View File

@@ -0,0 +1,164 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "CommandChannel.h"
#include "AuthClient.h"
#include "CommandManager.h"
#include "Daemon.h"
#include "FileUploader.h"
#include "RESTAPI_server.h"
#include "StorageService.h"
#include "WebSocketServer.h"
#include <boost/algorithm/string.hpp>
namespace uCentral {
class CommandChannel * CommandChannel::instance_ = nullptr;
std::string CommandChannel::ProcessCommand(const std::string &Command) {
std::vector<std::string> Tokens{};
std::string Result{"OK"};
try {
size_t pos, old_pos = 0 ;
Logger_.notice(Poco::format("COMMAND: %s",Command));
while((pos = Command.find(' ', old_pos)) != std::string::npos) {
Tokens.push_back(Command.substr(old_pos,pos-old_pos));
old_pos = pos + 1 ;
}
Tokens.push_back(Command.substr(old_pos));
boost::algorithm::to_lower(Tokens[0]);
boost::algorithm::to_lower(Tokens[1]);
if(Tokens[0]=="set") {
if(Tokens[1]=="loglevel") {
if(!Daemon()->SetSubsystemLogLevel(Tokens[3],Tokens[2]))
Result = "ERROR: Invalid: set logLevel subsystem name:" + Tokens[3];
}
} else if(Tokens[0]=="get") {
if(Tokens[1]=="loglevel") {
std::cout << "LogLevels:" << std::endl;
std::cout << " Auth: " << AuthClient()->Logger().getLevel() << std::endl;
std::cout << " uFileUploader: " << FileUploader()->Logger().getLevel() << std::endl;
std::cout << " WebSocket: " << WebSocketServer()->Logger().getLevel() << std::endl;
std::cout << " Storage: " << Storage()->Logger().getLevel() << std::endl;
std::cout << " RESTAPI: " << RESTAPI_server()->Logger().getLevel() << std::endl;
std::cout << " CommandManager: " << Logger_.getLevel() << std::endl;
std::cout << " DeviceRegistry: " << DeviceRegistry()->Logger().getLevel() << std::endl;
} else if (Tokens[1]=="stats") {
} else {
Result = "ERROR: Invalid: get command:" + Tokens[1];
}
} else if(Tokens[0]=="restart") {
Logger_.information("RESTART...");
} else if(Tokens[0]=="stop") {
Logger_.information("STOP...");
} else if(Tokens[0]=="stats") {
Logger_.information("STATS...");
} else {
Result = "ERROR: Invalid command: " + Tokens[0];
}
Logger_.notice(Poco::format("COMMAND-RESULT: %s",Result));
}
catch ( const Poco::Exception & E) {
Logger_.warning(Poco::format("COMMAND: Poco exception %s in performing command.",E.displayText()));
}
catch ( const std::exception & E) {
Logger_.warning(Poco::format("COMMAND: std::exception %s in performing command.",std::string(E.what())));
}
return Result;
}
/// This class handles all client connections.
class UnixSocketServerConnection: public Poco::Net::TCPServerConnection
{
public:
explicit UnixSocketServerConnection(const Poco::Net::StreamSocket & S, Poco::Logger & Logger):
TCPServerConnection(S),
Logger_(Logger)
{
}
void run() override
{
try
{
std::string Message;
std::vector<char> buffer(1024);
int n = 1;
while (n > 0)
{
n = socket().receiveBytes(&buffer[0], (int)buffer.size());
buffer[n] = '\0';
Message += &buffer[0];
Logger_.information(Poco::format("COMMAND-CHANNEL: %s",Message));
if(buffer.size() > n && !Message.empty())
{
CommandChannel()->ProcessCommand(Message);
Message.clear();
}
}
}
catch (const Poco::Exception & E)
{
Logger_.log(E);
}
}
private:
Poco::Logger & Logger_;
};
class UnixSocketServerConnectionFactory: public Poco::Net::TCPServerConnectionFactory
{
public:
explicit UnixSocketServerConnectionFactory() :
Logger_(CommandChannel()->Logger())
{
}
Poco::Net::TCPServerConnection* createConnection(const Poco::Net::StreamSocket& socket) override
{
return new UnixSocketServerConnection(socket,Logger_);
}
private:
Poco::Logger & Logger_;
};
CommandChannel::CommandChannel() noexcept:
SubSystemServer("CommandChannel", "COMMAND-CHANNEL", "commandchannel")
{
}
void CommandChannel::Stop() {
Logger_.notice("Stopping...");
Srv_->stop();
}
int CommandChannel::Start() {
Poco::File F(Daemon()->ConfigPath("ucentral.system.commandchannel","/tmp/app.ucentralgw"));
try {
if (F.exists())
F.remove();
} catch (const Poco::Exception &E ) {
}
SocketFile_ = std::make_unique<Poco::File>(F);
UnixSocket_ = std::make_unique<Poco::Net::SocketAddress>(Poco::Net::SocketAddress::UNIX_LOCAL, SocketFile_->path());
Svs_ = std::make_unique<Poco::Net::ServerSocket>(*UnixSocket_);
Srv_ = std::make_unique<Poco::Net::TCPServer>(new UnixSocketServerConnectionFactory, *Svs_);
Srv_->start();
Logger_.notice("Starting...");
return 0;
}
}

51
src/CommandChannel.h Normal file
View File

@@ -0,0 +1,51 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRALGW_COMMANDCHANNEL_H
#define UCENTRALGW_COMMANDCHANNEL_H
#include "SubSystemServer.h"
#include "Poco/File.h"
#include "Poco/Net/Socket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/TCPServer.h"
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
namespace uCentral {
class CommandChannel : public SubSystemServer {
public:
static CommandChannel *instance() {
if (instance_ == nullptr) {
instance_ = new CommandChannel;
}
return instance_;
}
int Start() override;
void Stop() override;
std::string ProcessCommand(const std::string &Command);
private:
static CommandChannel * instance_;
std::unique_ptr<Poco::File> SocketFile_;
std::unique_ptr<Poco::Net::SocketAddress> UnixSocket_;
std::unique_ptr<Poco::Net::ServerSocket> Svs_;
std::unique_ptr<Poco::Net::TCPServer> Srv_;
CommandChannel() noexcept;
};
inline CommandChannel * CommandChannel() { return CommandChannel::instance(); }
} //namespace
#endif // UCENTRALGW_COMMANDCHANNEL_H

View File

@@ -6,48 +6,43 @@
// Arilia Wireless Inc.
//
#include "CommandManager.h"
#include <algorithm>
#include "Poco/JSON/Parser.h"
#include "CommandManager.h"
#include "DeviceRegistry.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "RESTAPI_GWobjects.h"
#include "RESTAPI_handler.h"
#include "StorageService.h"
#include "framework/MicroService.h"
#include "framework/uCentral_Protocol.h"
#include "uCentralProtocol.h"
#include "Poco/JSON/Parser.h"
namespace OpenWifi {
#define DBG std::cout << __LINE__ << " " __FILE__ << std::endl;
namespace uCentral {
class CommandManager * CommandManager::instance_ = nullptr;
CommandManager::CommandManager() noexcept:
SubSystemServer("CommandManager", "CMD_MGR", "command.manager")
{
}
void CommandManager::run() {
Running_ = true;
while(Running_)
{
Poco::Thread::trySleep(30000);
Poco::Thread::trySleep(10000);
if(!Running_)
break;
std::vector<GWObjects::CommandDetails> Commands;
if(StorageService()->GetReadyToExecuteCommands(1,200,Commands))
if(Storage()->GetReadyToExecuteCommands(0,1000,Commands))
{
for(auto & Cmd: Commands)
{
if(!Running_)
break;
uint64_t RPC_Id;
Poco::JSON::Parser P;
auto Params = P.parse(Cmd.Details).extract<Poco::JSON::Object::Ptr>();
if(SendCommand( Cmd.SerialNumber,
Cmd.Command,
*Params,
Cmd.UUID,
RPC_Id)) {
StorageService()->SetCommandExecuted(Cmd.UUID);
Logger_.information(Poco::format("Sent command '%s' to '%s'",Cmd.Command,Cmd.SerialNumber));
} else {
if(!SendCommand(Cmd)) {
Logger_.information(Poco::format("Failed to send command '%s' to %s",Cmd.Command,Cmd.SerialNumber));
}
}
@@ -75,85 +70,107 @@ namespace OpenWifi {
}
void CommandManager::Janitor() {
std::lock_guard G(Mutex_);
SubMutexGuard G(SubMutex);
uint64_t Now = time(nullptr);
Logger_.information("Janitor starting.");
for(auto i=OutStandingRequests_.begin();i!=OutStandingRequests_.end();) {
if((Now-i->second.Submitted)>120)
i = OutStandingRequests_.erase(i);
for(auto i = Age_.begin(); i!= Age_.end();)
if((Now-i->first)>300)
Age_.erase(i++);
else
++i;
}
Logger_.information("Janitor finished.");
}
bool CommandManager::GetCommand(uint64_t Id, const std::string &SerialNumber, CommandTag &T) {
std::lock_guard G(Mutex_);
CommandTagIndex TI{.Id=Id,.SerialNumber=SerialNumber};
auto Hint=OutStandingRequests_.find(TI);
if(Hint==OutStandingRequests_.end() || Hint->second.Completed==0)
return false;
T = Hint->second;
OutStandingRequests_.erase(Hint);
return true;
}
bool CommandManager::SendCommand(const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,
std::shared_ptr<std::promise<Poco::JSON::Object::Ptr>> Promise,
const std::string &UUID) {
bool CommandManager::SendCommand( const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,
const std::string &UUID,
uint64_t & Id,
bool oneway_rpc) {
SubMutexGuard G(SubMutex);
std::stringstream ToSend;
std::unique_lock G(Mutex_);
if(oneway_rpc)
Id = 1;
else
Id = ++Id_;
Poco::JSON::Object CompleteRPC;
Poco::JSON::Object CompleteRPC;
CompleteRPC.set(uCentralProtocol::JSONRPC, uCentralProtocol::JSONRPC_VERSION);
CompleteRPC.set(uCentralProtocol::ID, Id);
CompleteRPC.set(uCentralProtocol::METHOD, Method);
CompleteRPC.set(uCentralProtocol::ID, Id_);
CompleteRPC.set(uCentralProtocol::METHOD, Method );
CompleteRPC.set(uCentralProtocol::PARAMS, Params);
std::stringstream ToSend;
Poco::JSON::Stringifier::stringify(CompleteRPC, ToSend);
Logger_.information(
Poco::format("(%s): Sending command '%s', ID: %lu", SerialNumber, Method, Id));
CommandTagIndex Idx{.Id = Id, .SerialNumber = SerialNumber};
CommandTag Tag;
Tag.UUID = UUID;
Tag.Submitted = std::time(nullptr);
Tag.Completed = 0;
Tag.Result = Poco::makeShared<Poco::JSON::Object>();
OutStandingRequests_[Idx] = Tag;
G.unlock();
std::cout << "Count: " << Promise.use_count() << std::endl;
OutStandingRequests_[Id_] = std::make_pair(std::move(Promise),UUID);
Age_[Id_] = time(nullptr);
Id_++;
return DeviceRegistry()->SendFrame(SerialNumber, ToSend.str());
}
void CommandManager::PostCommandResult(const std::string &SerialNumber, Poco::JSON::Object::Ptr Obj) {
bool CommandManager::SendCommand(GWObjects::CommandDetails & Command) {
SubMutexGuard G(SubMutex);
Logger_.debug(Poco::format("Sending command to %s",Command.SerialNumber));
try {
Poco::JSON::Object Obj;
Obj.set(uCentralProtocol::JSONRPC,uCentralProtocol::JSONRPC_VERSION);
Obj.set(uCentralProtocol::ID,Id_);
Obj.set(uCentralProtocol::METHOD, Command.Custom ? uCentralProtocol::PERFORM : Command.Command );
bool FullCommand = true;
if(Command.Command==uCentralProtocol::REQUEST)
FullCommand = false;
// the params section was composed earlier... just include it here
Poco::JSON::Parser parser;
auto ParsedMessage = parser.parse(Command.Details);
const auto & ParamsObj = ParsedMessage.extract<Poco::JSON::Object::Ptr>();
Obj.set(uCentralProtocol::PARAMS,ParamsObj);
std::stringstream ToSend;
Poco::JSON::Stringifier::stringify(Obj,ToSend);
if(DeviceRegistry()->SendFrame(Command.SerialNumber, ToSend.str())) {
Storage()->SetCommandExecuted(Command.UUID);
OutStandingRequests_[Id_] = std::make_pair(nullptr,Command.UUID);
Age_[Id_] = time(nullptr);
return true;
} else {
}
Id_++;
}
catch( const Poco::Exception & E )
{
Logger_.warning(Poco::format("COMMAND(%s): Exception while sending a command.",Command.SerialNumber));
}
return false;
}
void CommandManager::PostCommandResult(const std::string &SerialNumber, Poco::JSON::Object::Ptr Obj) {
if(!Obj->has(uCentralProtocol::ID)){
Logger_.error(Poco::format("(%s): Invalid RPC response.",SerialNumber));
Logger_.error("Invalid RPC response.");
return;
}
SubMutexGuard G(SubMutex);
uint64_t ID = Obj->get(uCentralProtocol::ID);
if(ID<2) {
Logger_.error(Poco::format("(%s): Ignoring RPC response.",SerialNumber));
return;
auto RPC = OutStandingRequests_.find(ID);
Age_.erase(ID);
if(RPC != OutStandingRequests_.end()) {
if(RPC->second.first.use_count() > 1) {
try {
RPC->second.first->set_value(std::move(Obj));
} catch (...) {
Logger_.error(Poco::format("COMPLETING-RPC(%Lu): future was lost", ID));
Storage()->CommandCompleted(RPC->second.second, Obj, true);
}
}
else {
Storage()->CommandCompleted(RPC->second.second, Obj, true);
}
OutStandingRequests_.erase(RPC);
} else {
Logger_.warning(Poco::format("OUTDATED-RPC(%lu): Nothing waiting for this RPC.",ID));
}
std::unique_lock G(Mutex_);
auto Idx = CommandTagIndex{.Id = ID, .SerialNumber = SerialNumber};
auto RPC = OutStandingRequests_.find(Idx);
if (RPC == OutStandingRequests_.end()) {
Logger_.warning(Poco::format("(%s): Outdated RPC %lu", SerialNumber, ID));
return;
}
RPC->second.Completed = std::time(nullptr);
RPC->second.Result = Obj;
Logger_.information(Poco::format("(%s): Received RPC answer %lu", SerialNumber, ID));
G.unlock();
StorageService()->CommandCompleted(RPC->second.UUID, Obj, true);
}
} // namespace

View File

@@ -19,36 +19,10 @@
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "framework/MicroService.h"
#include "RESTAPI_GWobjects.h"
#include "SubSystemServer.h"
namespace OpenWifi {
struct CommandTagIndex {
uint64_t Id=0;
std::string SerialNumber;
};
inline bool operator <(const CommandTagIndex& lhs, const CommandTagIndex& rhs) {
if(lhs.Id<rhs.Id)
return true;
if(lhs.Id>rhs.Id)
return false;
return lhs.SerialNumber<rhs.SerialNumber;
}
inline bool operator ==(const CommandTagIndex& lhs, const CommandTagIndex& rhs) {
if(lhs.Id == rhs.Id && lhs.SerialNumber == rhs.SerialNumber)
return true;
return false;
}
struct CommandTag {
std::string UUID;
Poco::JSON::Object::Ptr Result;
uint64_t Submitted=0;
uint64_t Completed=0;
};
namespace uCentral {
class CommandManager : public SubSystemServer, Poco::Runnable {
public:
@@ -57,32 +31,34 @@ namespace OpenWifi {
void WakeUp();
void PostCommandResult(const std::string &SerialNumber, Poco::JSON::Object::Ptr Obj);
bool SendCommand( const std::string &SerialNumber,
const std::string &Method,
const Poco::JSON::Object &Params,
const std::string &UUID,
uint64_t & Id,
bool oneway_rpc=false);
const std::string &Method,
const Poco::JSON::Object &Params,
std::shared_ptr<std::promise<Poco::JSON::Object::Ptr>> Promise,
const std::string &UUID);
bool SendCommand( const std::string & SerialNumber,
const std::string & Method,
const Poco::JSON::Object &Params,
const std::string & UUID);
bool SendCommand(GWObjects::CommandDetails & Command);
void Janitor();
void run() override;
bool GetCommand(uint64_t Id, const std::string & SerialNumber, CommandTag &T);
static CommandManager *instance() {
static CommandManager *instance_ = new CommandManager;
if (instance_ == nullptr) {
instance_ = new CommandManager;
}
return instance_;
}
inline bool Running() const { return Running_; }
private:
std::atomic_bool Running_ = false;
Poco::Thread ManagerThread;
uint64_t Id_=2; // do not start @1. We ignore ID=1 & 0 is illegal..
std::map<CommandTagIndex,CommandTag> OutStandingRequests_;
static CommandManager * instance_;
std::atomic_bool Running_ = false;
Poco::Thread ManagerThread;
uint64_t Id_=1;
std::map< uint64_t , std::pair< std::shared_ptr<std::promise<Poco::JSON::Object::Ptr>>, std::string> > OutStandingRequests_;
std::map< uint64_t , uint64_t > Age_;
CommandManager() noexcept:
SubSystemServer("CommandManager", "CMD-MGR", "command.manager")
{
}
CommandManager() noexcept;
};
inline CommandManager * CommandManager() { return CommandManager::instance(); }

View File

@@ -1,8 +0,0 @@
//
// Created by stephane bourque on 2021-09-21.
//
#include "ConfigurationCache.h"
namespace OpenWifi {
}

View File

@@ -1,42 +0,0 @@
//
// Created by stephane bourque on 2021-09-21.
//
#ifndef OWGW_CONFIGURATIONCACHE_H
#define OWGW_CONFIGURATIONCACHE_H
#include <map>
#include <string>
#include <mutex>
namespace OpenWifi {
class ConfigurationCache {
public:
static ConfigurationCache & instance() {
static ConfigurationCache instance;
return instance;
}
inline uint64_t CurrentConfig(const std::string &SerialNumber) {
std::lock_guard G(Mutex_);
const auto Hint = Cache_.find(SerialNumber);
if(Hint==end(Cache_))
return 0;
return Hint->second;
}
inline void Add(const std::string &SerialNumber, uint64_t Id) {
std::lock_guard G(Mutex_);
Cache_[SerialNumber]=Id;
}
private:
std::mutex Mutex_;
std::map<std::string,uint64_t> Cache_;
};
inline uint64_t GetCurrentConfigurationID(const std::string &S) { return ConfigurationCache::instance().CurrentConfig(S); }
inline void SetCurrentConfigurationID(const std::string &S, uint64_t ID) { ConfigurationCache::instance().Add(S,ID); }
}
#endif // OWGW_CONFIGURATIONCACHE_H

View File

@@ -10,58 +10,70 @@
#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "Poco/Environment.h"
#include "Poco/Net/HTTPStreamFactory.h"
#include "CentralConfig.h"
#include "CommandManager.h"
#include "Daemon.h"
#include "CallbackManager.h"
#include "CommandChannel.h"
#include "CommandManager.h"
#include "DeviceRegistry.h"
#include "FileUploader.h"
#include "OUIServer.h"
#include "SerialNumberCache.h"
#include "StorageArchiver.h"
#include "RESTAPI_server.h"
#include "StorageService.h"
#include "TelemetryStream.h"
#include "WebSocketServer.h"
#include "framework/ConfigurationValidator.h"
#include "framework/MicroService.h"
#include "CentralConfig.h"
#include "OUIServer.h"
#include "StateProcessor.h"
#include "Utils.h"
#include "RESTAPI_InternalServer.h"
#include "AuthClient.h"
#include "StorageArchiver.h"
namespace uCentral {
class Daemon *Daemon::instance_ = nullptr;
namespace OpenWifi {
class Daemon *Daemon::instance() {
static Daemon instance(vDAEMON_PROPERTIES_FILENAME,
if (instance_ == nullptr) {
instance_ = new Daemon(vDAEMON_PROPERTIES_FILENAME,
vDAEMON_ROOT_ENV_VAR,
vDAEMON_CONFIG_ENV_VAR,
vDAEMON_APP_NAME,
vDAEMON_BUS_TIMER,
SubSystemVec{
StorageService(),
SerialNumberCache(),
ConfigurationValidator(),
Types::SubSystemVec{
Storage(),
AuthClient(),
DeviceRegistry(),
RESTAPI_server(),
RESTAPI_InternalServer(),
WebSocketServer(),
CommandManager(),
FileUploader(),
OUIServer(),
CommandChannel(),
CallbackManager(),
StorageArchiver(),
TelemetryStream()
});
return &instance;
}
return instance_;
}
void Daemon::initialize() {
void Daemon::initialize(Poco::Util::Application &self) {
MicroService::initialize(*this);
Config::Config::Init();
AutoProvisioning_ = config().getBool("openwifi.autoprovisioning",false);
AutoProvisioning_ = config().getBool("ucentral.autoprovisioning",false);
// DeviceTypeIdentifications_
Types::StringVec Keys;
config().keys("openwifi.devicetypes",Keys);
config().keys("ucentral.devicetypes",Keys);
for(const auto & i:Keys)
{
std::string Line = config().getString("openwifi.devicetypes."+i);
std::string Line = config().getString("ucentral.devicetypes."+i);
auto P1 = Line.find_first_of(':');
auto Type = Line.substr(0, P1);
auto List = Line.substr(P1+1);
Types::StringVec Tokens = Utils::Split(List);
Types::StringVec Tokens = uCentral::Utils::Split(List);
auto Entry = DeviceTypeIdentifications_.find(Type);
if(DeviceTypeIdentifications_.end() == Entry) {
@@ -74,10 +86,6 @@ namespace OpenWifi {
}
}
void MicroServicePostInitialization() {
Daemon()->initialize();
}
[[nodiscard]] std::string Daemon::IdentifyDevice(const std::string & Id ) const {
for(const auto &[Type,List]:DeviceTypeIdentifications_)
{
@@ -88,12 +96,12 @@ namespace OpenWifi {
}
}
int main(int argc, char **argv) {
try {
auto App = OpenWifi::Daemon::instance();
auto App = uCentral::Daemon::instance();
auto ExitCode = App->run(argc, argv);
delete App;
return ExitCode;
} catch (Poco::Exception &exc) {

View File

@@ -25,39 +25,35 @@
#include "Poco/Crypto/CipherFactory.h"
#include "Poco/Crypto/Cipher.h"
#include "Dashboard.h"
#include "framework/MicroService.h"
#include "framework/OpenWifiTypes.h"
#include "MicroService.h"
#include "uCentralTypes.h"
namespace OpenWifi {
namespace uCentral {
static const char * vDAEMON_PROPERTIES_FILENAME = "owgw.properties";
static const char * vDAEMON_ROOT_ENV_VAR = "OWGW_ROOT";
static const char * vDAEMON_CONFIG_ENV_VAR = "OWGW_CONFIG";
static const char * vDAEMON_PROPERTIES_FILENAME = "ucentralgw.properties";
static const char * vDAEMON_ROOT_ENV_VAR = "UCENTRALGW_ROOT";
static const char * vDAEMON_CONFIG_ENV_VAR = "UCENTRALGW_CONFIG";
static const char * vDAEMON_APP_NAME = uSERVICE_GATEWAY.c_str();
static const uint64_t vDAEMON_BUS_TIMER = 10000;
class Daemon : public MicroService {
public:
explicit Daemon(const std::string & PropFile,
const std::string & RootEnv,
const std::string & ConfigEnv,
const std::string & AppName,
explicit Daemon(std::string PropFile,
std::string RootEnv,
std::string ConfigEnv,
std::string AppName,
uint64_t BusTimer,
const SubSystemVec & SubSystems) :
Types::SubSystemVec SubSystems) :
MicroService( PropFile, RootEnv, ConfigEnv, AppName, BusTimer, SubSystems) {};
bool AutoProvisioning() const { return AutoProvisioning_ ; }
[[nodiscard]] std::string IdentifyDevice(const std::string & Compatible) const;
void initialize();
void initialize(Poco::Util::Application &self);
static Daemon *instance();
inline DeviceDashboard & GetDashboard() { return DB_; }
Poco::Logger & Log() { return Poco::Logger::get(AppName()); }
private:
static Daemon *instance_;
bool AutoProvisioning_ = false;
Types::StringMapStringSet DeviceTypeIdentifications_;
DeviceDashboard DB_;
};
inline Daemon * Daemon() { return Daemon::instance(); }

View File

@@ -1,20 +0,0 @@
//
// Created by stephane bourque on 2021-07-21.
//
#include "Dashboard.h"
#include "DeviceRegistry.h"
#include "StorageService.h"
namespace OpenWifi {
void DeviceDashboard::Create() {
uint64_t Now = std::time(nullptr);
if(LastRun_==0 || (Now-LastRun_)>120) {
DB_.reset();
StorageService()->AnalyzeCommands(DB_.commands);
StorageService()->AnalyzeDevices(DB_);
LastRun_ = Now;
}
}
}

View File

@@ -1,24 +0,0 @@
//
// Created by stephane bourque on 2021-07-21.
//
#ifndef UCENTRALGW_DASHBOARD_H
#define UCENTRALGW_DASHBOARD_H
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "framework/OpenWifiTypes.h"
namespace OpenWifi {
class DeviceDashboard {
public:
DeviceDashboard() { DB_.reset(); }
void Create();
[[nodiscard]] const GWObjects::Dashboard & Report() const { return DB_;}
private:
GWObjects::Dashboard DB_;
uint64_t LastRun_=0;
inline void Reset() { DB_.reset(); }
};
}
#endif // UCENTRALGW_DASHBOARD_H

View File

@@ -6,41 +6,47 @@
// Arilia Wireless Inc.
//
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "DeviceRegistry.h"
#include "RESTAPI_handler.h"
#include "WebSocketServer.h"
#include "DeviceRegistry.h"
#include "WebSocketServer.h"
#include "OUIServer.h"
namespace OpenWifi {
namespace uCentral {
class DeviceRegistry *DeviceRegistry::instance_ = nullptr;
DeviceRegistry::DeviceRegistry() noexcept:
SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") {
}
int DeviceRegistry::Start() {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
Logger_.notice("Starting ");
return 0;
}
void DeviceRegistry::Stop() {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
Logger_.notice("Stopping ");
}
bool DeviceRegistry::GetStatistics(const std::string &SerialNumber, std::string & Statistics) {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device == Devices_.end())
return false;
Statistics = Device->second->LastStats;
return true;
if(Device != Devices_.end()) {
Statistics = Device->second->LastStats;
return true;
}
return false;
}
void DeviceRegistry::SetStatistics(const std::string &SerialNumber, const std::string &Statistics) {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end())
{
Device->second->Conn_.LastContact = time(nullptr);
@@ -49,18 +55,22 @@ namespace OpenWifi {
}
bool DeviceRegistry::GetState(const std::string &SerialNumber, GWObjects::ConnectionState & State) {
std::lock_guard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device == Devices_.end())
return false;
SubMutexGuard Guard(Mutex_);
State = Device->second->Conn_;
return true;
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end())
{
State = Device->second->Conn_;
return true;
}
return false;
}
void DeviceRegistry::SetState(const std::string & SerialNumber, GWObjects::ConnectionState & State) {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end())
{
Device->second->Conn_.LastContact = time(nullptr);
@@ -68,8 +78,8 @@ namespace OpenWifi {
}
}
bool DeviceRegistry::GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData) {
std::lock_guard Guard(Mutex_);
bool DeviceRegistry::GetHealthcheck(const std::string &SerialNumber, std::string & CheckData) {
SubMutexGuard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end()) {
@@ -79,174 +89,114 @@ namespace OpenWifi {
return false;
}
void DeviceRegistry::SetHealthcheck(const std::string &SerialNumber, const GWObjects::HealthCheck & CheckData) {
std::lock_guard Guard(Mutex_);
void DeviceRegistry::SetHealthcheck(const std::string &SerialNumber, const std::string &CheckData) {
SubMutexGuard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device != Devices_.end())
{
Device->second->LastHealthcheck = CheckData;
}
}
std::shared_ptr<DeviceRegistry::ConnectionEntry> DeviceRegistry::Register(const std::string & SerialNumber, WSConnection *Ptr, uint64_t & ConnectionId )
GWObjects::ConnectionState * DeviceRegistry::Register(const std::string & SerialNumber, WSConnection *Ptr)
{
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
const auto & E = Devices_[SerialNumber] = std::make_shared<ConnectionEntry>();
E->WSConn_ = Ptr;
E->Conn_.SerialNumber = SerialNumber;
E->Conn_.LastContact = std::time(nullptr);
E->Conn_.Connected = true ;
E->Conn_.UUID = 0 ;
E->Conn_.MessageCount = 0 ;
E->Conn_.Address = "";
E->Conn_.TX = 0 ;
E->Conn_.RX = 0;
E->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
ConnectionId = E->ConnectionId = ++Id_;
return E;
auto Device = Devices_.find(SerialNumber);
if( Device == Devices_.end()) {
auto E = std::make_unique<ConnectionEntry>();
E->WSConn_ = Ptr;
E->Conn_.SerialNumber = SerialNumber;
E->Conn_.LastContact = std::time(nullptr);
E->Conn_.Connected = true ;
E->Conn_.UUID = 0 ;
E->Conn_.MessageCount = 0 ;
E->Conn_.Address = "";
E->Conn_.TX = 0 ;
E->Conn_.RX = 0;
E->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
auto R=&E->Conn_;
Devices_[SerialNumber] = std::move(E);
return R;
}
else
{
Device->second->WSConn_ = Ptr;
Device->second->Conn_.Connected = true;
Device->second->Conn_.LastContact = std::time(nullptr);
Device->second->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE;
return &Device->second->Conn_;
}
}
bool DeviceRegistry::Connected(const std::string & SerialNumber) {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device == Devices_.end())
return false;
return Device->second->Conn_.Connected;
}
void DeviceRegistry::UnRegister(const std::string & SerialNumber, uint64_t ConnectionId) {
std::lock_guard Guard(Mutex_);
auto It = Devices_.find(SerialNumber);
if(It!=Devices_.end()) {
if(It->second->ConnectionId == ConnectionId)
Devices_.erase(SerialNumber);
}
}
void DeviceRegistry::UnRegister(const std::string & SerialNumber, WSConnection *Ptr) {
SubMutexGuard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if( Device != Devices_.end() && Device->second->WSConn_==Ptr) {
Device->second->Conn_.Address = "";
Device->second->WSConn_ = nullptr;
Device->second->Conn_.Connected = false;
Device->second->Conn_.LastContact = time(nullptr);
Device->second->Conn_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
}
}
bool DeviceRegistry::SendFrame(const std::string & SerialNumber, const std::string & Payload) {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device!=Devices_.end() && Device->second->WSConn_!= nullptr) {
try {
return Device->second->WSConn_->Send(Payload);
} catch (...) {
Logger_.debug(Poco::format("Could not send data to device '%s'", SerialNumber));
Device->second->Conn_.Address = "";
Device->second->WSConn_ = nullptr;
Device->second->Conn_.Connected = false;
Device->second->Conn_.VerifiedCertificate = GWObjects::NO_CERTIFICATE;
}
auto *WSConn =
static_cast<WSConnection *>(Device->second->WSConn_);
return WSConn->Send(Payload);
}
return false;
}
void DeviceRegistry::SetPendingUUID(const std::string & SerialNumber, uint64_t PendingUUID) {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
auto Device = Devices_.find(SerialNumber);
if(Device!=Devices_.end()) {
Device->second->Conn_.PendingUUID = PendingUUID;
}
}
std::string ComputeCertificateTag( GWObjects::CertificateValidation V) {
switch(V) {
case GWObjects::NO_CERTIFICATE: return "no certificate";
case GWObjects::VALID_CERTIFICATE: return "non TIP certificate";
case GWObjects::MISMATCH_SERIAL: return "serial mismatch";
case GWObjects::VERIFIED: return "verified";
}
return "unknown";
}
/* bool Service::SendCommand(uCentral::Objects::CommandDetails & Cmd)
{
SubMutexGuard Guard(Mutex_);
const uint64_t SECONDS_MONTH = 30*24*60*60;
const uint64_t SECONDS_WEEK = 7*24*60*60;
const uint64_t SECONDS_DAY = 1*24*60*60;
const uint64_t SECONDS_HOUR = 1*24*60*60;
std::string ComputeUpLastContactTag(uint64_t T1) {
uint64_t T = T1 - std::time(nullptr);
if( T>SECONDS_MONTH) return ">month";
if( T>SECONDS_WEEK) return ">week";
if( T>SECONDS_DAY) return ">day";
if( T>SECONDS_HOUR) return ">hour";
return "now";
}
std::string ComputeSanityTag(uint64_t T) {
if( T==100) return "100%";
if( T>90) return ">90%";
if( T>60) return ">60%";
return "<60%";
}
std::string ComputeUpTimeTag(uint64_t T) {
if( T>SECONDS_MONTH) return ">month";
if( T>SECONDS_WEEK) return ">week";
if( T>SECONDS_DAY) return ">day";
if( T>SECONDS_HOUR) return ">hour";
return "now";
}
std::string ComputeLoadTag(uint64_t T) {
float V=100.0*((float)T/65536.0);
if(V<5.0) return "< 5%";
if(V<25.0) return "< 25%";
if(V<50.0) return "< 50%";
if(V<75.0) return "< 75%";
return ">75%";
}
std::string ComputeFreeMemoryTag(uint64_t Free, uint64_t Total) {
float V = 100.0 * ((float)Free/(float(Total)));
if(V<5.0) return "< 5%";
if(V<25.0) return "< 25%";
if(V<50.0) return "< 50%";
if(V<75.0) return "< 75%";
return ">75%";
}
bool DeviceRegistry::AnalyzeRegistry(GWObjects::Dashboard &D) {
std::lock_guard Guard(Mutex_);
for(auto const &[SerialNumber,Connection]:Devices_) {
Types::UpdateCountedMap(D.status, Connection->Conn_.Connected ? "connected" : "not connected");
Types::UpdateCountedMap(D.vendors, OUIServer()->GetManufacturer(SerialNumber));
Types::UpdateCountedMap(D.certificates, ComputeCertificateTag(Connection->Conn_.VerifiedCertificate));
Types::UpdateCountedMap(D.lastContact, ComputeUpLastContactTag(Connection->Conn_.LastContact));
Types::UpdateCountedMap(D.healths, ComputeSanityTag(Connection->LastHealthcheck.Sanity));
Types::UpdateCountedMap(D.deviceType, Connection->Conn_.Compatible);
if(!Connection->LastStats.empty()) {
Poco::JSON::Parser P;
auto RawObject = P.parse(Connection->LastStats).extract<Poco::JSON::Object::Ptr>();
if(RawObject->has("unit")) {
auto Unit = RawObject->getObject("unit");
if (Unit->has("uptime")) {
Types::UpdateCountedMap(D.upTimes, ComputeUpTimeTag(Unit->get("uptime")));
}
if (Unit->has("memory")) {
auto Memory = Unit->getObject("memory");
uint64_t Free = Memory->get("free");
uint64_t Total = Memory->get("total");
Types::UpdateCountedMap(D.memoryUsed, ComputeFreeMemoryTag(Free, Total));
}
if (Unit->has("load")) {
auto Load = Unit->getArray("load");
Types::UpdateCountedMap(D.load1,
ComputeLoadTag(Load->getElement<uint64_t>(0)));
Types::UpdateCountedMap(D.load5,
ComputeLoadTag(Load->getElement<uint64_t>(1)));
Types::UpdateCountedMap(D.load15,
ComputeLoadTag(Load->getElement<uint64_t>(2)));
}
}
}
}
return false;
}
auto Device = Devices_.find(Cmd.SerialNumber);
try {
if (Device != Devices_.end()) {
if (Device->second->Conn_.Connected) {
if (Device->second->WSConn_ != nullptr) {
auto *WSConn = static_cast<uCentral::WebSocket::WSConnection *>(Device->second->WSConn_);
WSConn->SendCommand(Cmd);
return true;
}
}
}
} catch(...) {
Logger_.error(Poco::format("COMMAND(%s): Cannot send command %s.",Cmd.SerialNumber, Cmd.Command));
}
return false;
}
*/
} // namespace

View File

@@ -6,16 +6,17 @@
// Arilia Wireless Inc.
//
#pragma once
#ifndef UCENTRAL_UDEVICEREGISTRY_H
#define UCENTRAL_UDEVICEREGISTRY_H
#include "Poco/JSON/Object.h"
#include "RESTObjects//RESTAPI_GWobjects.h"
#include "framework/MicroService.h"
#include "RESTAPI_GWobjects.h"
#include "SubSystemServer.h"
// class uCentral::WebSocket::WSConnection;
namespace OpenWifi {
namespace uCentral {
class WSConnection;
class DeviceRegistry : public SubSystemServer {
@@ -24,12 +25,13 @@ namespace OpenWifi {
WSConnection *WSConn_;
GWObjects::ConnectionState Conn_;
std::string LastStats;
GWObjects::HealthCheck LastHealthcheck;
uint64_t ConnectionId=0;
std::string LastHealthcheck;
};
static DeviceRegistry *instance() {
static DeviceRegistry *instance_ = new DeviceRegistry;
if (instance_ == nullptr) {
instance_ = new DeviceRegistry;
}
return instance_;
}
@@ -39,26 +41,24 @@ namespace OpenWifi {
void SetStatistics(const std::string &SerialNumber, const std::string &stats);
bool GetState(const std::string & SerialNumber, GWObjects::ConnectionState & State);
void SetState(const std::string & SerialNumber, GWObjects::ConnectionState & State);
bool GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData);
void SetHealthcheck(const std::string &SerialNumber, const GWObjects::HealthCheck &H);
std::shared_ptr<ConnectionEntry> Register(const std::string & SerialNumber, WSConnection *, uint64_t & ConnectionId);
void UnRegister(const std::string & SerialNumber, uint64_t ConnectionId);
bool GetHealthcheck(const std::string &SerialNumber, std::string & Statistics);
void SetHealthcheck(const std::string &SerialNumber, const std::string &stats);
GWObjects::ConnectionState * Register(const std::string & SerialNumber, WSConnection *);
void UnRegister(const std::string & SerialNumber, WSConnection *);
bool SendCommand(GWObjects::CommandDetails & Command);
bool Connected(const std::string & SerialNumber);
bool SendFrame(const std::string & SerialNumber, const std::string & Payload);
void SetPendingUUID(const std::string & SerialNumber, uint64_t PendingUUID);
bool AnalyzeRegistry(GWObjects::Dashboard &D);
private:
inline static std::atomic_uint64_t Id_=1;
std::map<std::string,std::shared_ptr<ConnectionEntry>> Devices_;
static DeviceRegistry *instance_;
std::map<std::string,std::unique_ptr<ConnectionEntry>> Devices_;
DeviceRegistry() noexcept:
SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") {
}
DeviceRegistry() noexcept;
};
inline DeviceRegistry * DeviceRegistry() { return DeviceRegistry::instance(); }
} // namespace
#endif //UCENTRAL_UDEVICEREGISTRY_H

View File

@@ -10,6 +10,10 @@
#include <fstream>
#include <cstdio>
#include "Daemon.h"
#include "FileUploader.h"
#include "StorageService.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/DynamicAny.h"
@@ -20,34 +24,32 @@
#include "Poco/StreamCopier.h"
#include "Poco/Exception.h"
#include "FileUploader.h"
#include "StorageService.h"
#include "framework/MicroService.h"
#include "Utils.h"
namespace OpenWifi {
namespace uCentral {
class FileUploader *FileUploader::instance_ = nullptr;
FileUploader::FileUploader() noexcept:
SubSystemServer("FileUploader", "FILE-UPLOAD", "ucentral.fileuploader")
{
SubMutexGuard Guard(Mutex_);
}
static const std::string URI_BASE{"/v1/upload/"};
int FileUploader::Start() {
Logger_.notice("Starting.");
Poco::File UploadsDir(MicroService::instance().ConfigPath("openwifi.fileuploader.path","/tmp"));
Path_ = UploadsDir.path();
if(!UploadsDir.exists()) {
try {
UploadsDir.createDirectory();
} catch (const Poco::Exception &E) {
Logger_.log(E);
Path_ = "/tmp";
}
}
for(const auto & Svr: ConfigServersList_) {
std::string l{"Starting: " +
Svr.Address() + ":" + std::to_string(Svr.Port()) +
" key:" + Svr.KeyFile() +
" cert:" + Svr.CertFile()};
Logger_.information(l);
Path_ = Daemon()->ConfigPath("ucentral.fileuploader.path","/tmp");
auto Sock{Svr.CreateSecureSocket(Logger_)};
Svr.LogCert(Logger_);
@@ -59,40 +61,24 @@ namespace OpenWifi {
Params->setMaxQueued(100);
if(FullName_.empty()) {
std::string TmpName = MicroService::instance().ConfigGetString("openwifi.fileuploader.uri","");
if(TmpName.empty()) {
FullName_ =
"https://" + Svr.Name() + ":" + std::to_string(Svr.Port()) + URI_BASE;
} else {
FullName_ = TmpName + URI_BASE ;
}
Logger_.information(Poco::format("Uploader URI base is '%s'", FullName_));
FullName_ = "https://" + Svr.Name() + ":" + std::to_string(Svr.Port()) + URI_BASE;
Logger_.information(Poco::format("Uploader URI base is '%s'", FullName_));
}
auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new FileUpLoaderRequestHandlerFactory(Logger_), Pool_, Sock, Params);
NewServer->start();
Servers_.push_back(std::move(NewServer));
}
MaxSize_ = 1000 * MicroService::instance().ConfigGetInt("openwifi.fileuploader.maxsize", 10000);
return 0;
}
void FileUploader::reinitialize(Poco::Util::Application &self) {
MicroService::instance().LoadConfigurationFile();
Logger_.information("Reinitializing.");
Stop();
Start();
}
const std::string & FileUploader::FullName() {
return FullName_;
}
// if you pass in an empty UUID, it will just clean the list and not add it.
bool FileUploader::AddUUID( const std::string & UUID) {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
uint64_t Now = time(nullptr) ;
@@ -111,20 +97,20 @@ namespace OpenWifi {
}
bool FileUploader::ValidRequest(const std::string &UUID) {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
return OutStandingUploads_.find(UUID)!=OutStandingUploads_.end();
}
void FileUploader::RemoveRequest(const std::string &UUID) {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
OutStandingUploads_.erase(UUID);
}
class FileUploaderPartHandler: public Poco::Net::PartHandler
class MyPartHandler: public Poco::Net::PartHandler
{
public:
FileUploaderPartHandler(std::string UUID, Poco::Logger & Logger):
MyPartHandler(std::string UUID, Poco::Logger & Logger):
UUID_(std::move(UUID)),
Logger_(Logger)
{
@@ -132,54 +118,42 @@ namespace OpenWifi {
void handlePart(const Poco::Net::MessageHeader& Header, std::istream& Stream) override
{
try {
Name_ = "(unnamed)";
if (Header.has("Content-Disposition")) {
std::string Disposition;
Poco::Net::NameValueCollection Parameters;
Poco::Net::MessageHeader::splitParameters(Header["Content-Disposition"],
Disposition, Parameters);
Name_ = Parameters.get("filename", "(unnamed)");
}
FileType_ = Header.get("Content-Type", "(unspecified)");
if (Header.has("Content-Disposition"))
{
std::string Disposition;
Poco::Net::NameValueCollection Parameters;
Poco::Net::MessageHeader::splitParameters(Header["Content-Disposition"], Disposition, Parameters);
Name_ = Parameters.get("name", "(unnamed)");
}
std::string FinalFileName = FileUploader()->Path() + "/" + UUID_;
Poco::CountingInputStream InputStream(Stream);
std::string TmpFileName = FileUploader()->Path() + "/" + UUID_ + ".upload.start" ;
std::string FinalFileName = FileUploader()->Path() + "/" + UUID_ ;
Logger_.information(Poco::format("FILE-UPLOADER: uploading trace for %s", FinalFileName));
Poco::CountingInputStream InputStream(Stream);
std::ofstream OutputStream(FinalFileName, std::ofstream::out);
Poco::StreamCopier::copyStream(InputStream, OutputStream);
Logger_.information(Poco::format("FILE-UPLOADER: uploading %s",TmpFileName));
Poco::File TmpFile(FinalFileName);
Length_ = TmpFile.getSize();
if (Length_ < FileUploader()->MaxSize()) {
Good_=true;
} else {
TmpFile.remove();
Error_ = "File is too large.";
}
return;
} catch (const Poco::Exception &E ) {
Logger_.log(E);
Error_ = std::string("Upload caused an internal error: ") + E.what() ;
}
}
std::ofstream OutputStream(TmpFileName, std::ofstream::out);
Poco::StreamCopier::copyStream(InputStream, OutputStream);
Length_ = InputStream.chars();
rename(TmpFileName.c_str(),FinalFileName.c_str());
}
[[nodiscard]] uint64_t Length() const { return Length_; }
[[nodiscard]] const std::string& Name() const { return Name_; }
[[nodiscard]] bool Good() const { return Good_; }
std::string & Error() { return Error_; }
[[nodiscard]] const std::string& ContentType() const { return FileType_; }
private:
uint64_t Length_=0;
bool Good_=false;
std::string FileType_;
std::string Name_;
std::string UUID_;
std::string Error_;
Poco::Logger & Logger_;
};
class FormRequestHandler: public Poco::Net::HTTPRequestHandler
/// Return a HTML document with the current date and time.
{
public:
explicit FormRequestHandler(std::string UUID, Poco::Logger & L):
@@ -191,27 +165,62 @@ namespace OpenWifi {
void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override
{
try {
FileUploaderPartHandler partHandler(UUID_,Logger_);
MyPartHandler partHandler(UUID_,Logger_);
Poco::Net::HTMLForm form(Request, Request.stream(), partHandler);
Response.setChunkedTransferEncoding(true);
Response.setContentType("text/html");
std::ostream &ResponseStream = Response.send();
Response.setChunkedTransferEncoding(true);
Response.setContentType("application/json");
ResponseStream <<
"<html>\n"
"<head>\n"
"<title>POCO Form Server Sample</title>\n"
"</head>\n"
"<body>\n"
"<h1>POCO Form Server Sample</h1>\n"
"<h2>GET Form</h2>\n"
"<form method=\"GET\" action=\"/form\">\n"
"<input type=\"text\" name=\"text\" size=\"31\">\n"
"<input type=\"submit\" value=\"GET\">\n"
"</form>\n"
"<h2>POST Form</h2>\n"
"<form method=\"POST\" action=\"/form\">\n"
"<input type=\"text\" name=\"text\" size=\"31\">\n"
"<input type=\"submit\" value=\"POST\">\n"
"</form>\n"
"<h2>File Upload</h2>\n"
"<form method=\"POST\" action=\"/form\" enctype=\"multipart/form-data\">\n"
"<input type=\"file\" name=\"file\" size=\"31\"> \n"
"<input type=\"submit\" value=\"Upload\">\n"
"</form>\n";
Poco::JSON::Object Answer;
if (partHandler.Good()) {
Answer.set("filename", UUID_);
Answer.set("error", 0);
StorageService()->AttachFileToCommand(UUID_);
} else {
Answer.set("filename", UUID_);
Answer.set("error", 13);
Answer.set("errorText", partHandler.Error() );
StorageService()->CancelWaitFile(UUID_, partHandler.Error() );
}
std::ostream &ResponseStream = Response.send();
Poco::JSON::Stringifier::stringify(Answer, ResponseStream);
return;
ResponseStream << "<h2>Request</h2><p>\n";
ResponseStream << "Method: " << Request.getMethod() << "<br>\n";
ResponseStream << "URI: " << Request.getURI() << "<br>\n";
for (auto & i:Request) {
ResponseStream << i.first << ": " << i.second << "<br>\n";
}
ResponseStream << "</p>";
if (!form.empty()) {
ResponseStream << "<h2>Form</h2><p>\n";
for (const auto & i:form)
ResponseStream << i.first << ": " << i.second << "<br>\n";
ResponseStream << "</p>";
}
if (!partHandler.Name().empty()) {
ResponseStream << "<h2>Upload</h2><p>\n";
ResponseStream << "Name: " << partHandler.Name() << "<br>\n";
ResponseStream << "Type: " << partHandler.ContentType() << "<br>\n";
ResponseStream << "Size: " << partHandler.Length() << "<br>\n";
ResponseStream << "</p>";
}
ResponseStream << "</body>\n";
Storage()->AttachFileToCommand(UUID_);
}
catch( const Poco::Exception & E )
{
@@ -228,7 +237,7 @@ namespace OpenWifi {
Poco::Net::HTTPRequestHandler *FileUpLoaderRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) {
Logger_.debug(Poco::format("REQUEST(%s): %s %s", Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
Logger_.debug(Poco::format("REQUEST(%s): %s %s", uCentral::Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI()));
// The UUID should be after the /v1/upload/ part...
auto UUIDLocation = Request.getURI().find_first_of(URI_BASE);
@@ -254,7 +263,6 @@ namespace OpenWifi {
Logger_.notice("Stopping ");
for( const auto & svr : Servers_ )
svr->stop();
Servers_.clear();
}
} // Namespace

View File

@@ -9,20 +9,19 @@
#ifndef UCENTRAL_UFILEUPLOADER_H
#define UCENTRAL_UFILEUPLOADER_H
#include "SubSystemServer.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "framework/MicroService.h"
namespace OpenWifi {
namespace uCentral {
class FileUploader : public SubSystemServer {
public:
int Start() override;
void Stop() override;
void reinitialize(Poco::Util::Application &self) override;
const std::string & FullName();
bool AddUUID( const std::string & UUID);
bool ValidRequest(const std::string & UUID);
@@ -30,24 +29,21 @@ namespace OpenWifi {
const std::string & Path() { return Path_; };
static FileUploader *instance() {
static FileUploader * instance_ = new FileUploader;
return instance_;
if (instance_ == nullptr) {
instance_ = new FileUploader;
}
return instance_;
}
[[nodiscard]] inline uint64_t MaxSize() const { return MaxSize_; }
private:
static FileUploader *instance_;
std::vector<std::unique_ptr<Poco::Net::HTTPServer>> Servers_;
Poco::ThreadPool Pool_;
std::string FullName_;
std::map<std::string,uint64_t> OutStandingUploads_;
std::string Path_;
uint64_t MaxSize_=10000000;
explicit FileUploader() noexcept:
SubSystemServer("FileUploader", "FILE-UPLOAD", "openwifi.fileuploader")
{
}
FileUploader() noexcept;
};
class FileUpLoaderRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {

202
src/KafkaManager.cpp Normal file
View File

@@ -0,0 +1,202 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include <thread>
#include "KafkaManager.h"
#include "Daemon.h"
#include "Utils.h"
namespace uCentral {
class KafkaManager *KafkaManager::instance_ = nullptr;
KafkaManager::KafkaManager() noexcept:
SubSystemServer("KafkaManager", "KAFKA-SVR", "ucentral.kafka")
{
}
void KafkaManager::initialize(Poco::Util::Application & self) {
SubSystemServer::initialize(self);
KafkaEnabled_ = Daemon()->ConfigGetBool("ucentral.kafka.enable",false);
}
#ifdef SMALL_BUILD
int KafkaManager::Start() {
return 0;
}
void KafkaManager::Stop() {
}
#else
int KafkaManager::Start() {
if(!KafkaEnabled_)
return 0;
ProducerThr_ = std::make_unique<std::thread>([this]() { this->ProducerThr(); });
ConsumerThr_ = std::make_unique<std::thread>([this]() { this->ConsumerThr(); });
return 0;
}
void KafkaManager::Stop() {
if(KafkaEnabled_) {
ProducerRunning_ = ConsumerRunning_ = false;
ProducerThr_->join();
ConsumerThr_->join();
return;
}
}
void KafkaManager::ProducerThr() {
cppkafka::Configuration Config({
{ "client.id", Daemon()->ConfigGetString("ucentral.kafka.client.id") },
{ "metadata.broker.list", Daemon()->ConfigGetString("ucentral.kafka.brokerlist") }
});
SystemInfoWrapper_ = R"lit({ "system" : { "id" : )lit" +
std::to_string(Daemon()->ID()) +
R"lit( , "host" : ")lit" + Daemon()->PrivateEndPoint() +
R"lit(" } , "payload" : ")lit" ;
cppkafka::Producer Producer(Config);
ProducerRunning_ = true;
while(ProducerRunning_) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
try
{
SubMutexGuard G(ProducerMutex_);
auto Num=0;
while (!Queue_.empty()) {
const auto M = Queue_.front();
Producer.produce(
cppkafka::MessageBuilder(M.Topic).key(M.Key).payload(M.PayLoad));
Queue_.pop();
Num++;
}
if(Num)
Producer.flush();
} catch (const cppkafka::HandleException &E ) {
Logger_.warning(Poco::format("Caught a Kafka exception (producer): %s",std::string{E.what()}));
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
}
void KafkaManager::ConsumerThr() {
cppkafka::Configuration Config({
{ "client.id", Daemon()->ConfigGetString("ucentral.kafka.client.id") },
{ "metadata.broker.list", Daemon()->ConfigGetString("ucentral.kafka.brokerlist") },
{ "group.id", Daemon()->ConfigGetString("ucentral.kafka.group.id") },
{ "enable.auto.commit", Daemon()->ConfigGetBool("ucentral.kafka.auto.commit",false) },
{ "auto.offset.reset", "latest" } ,
{ "enable.partition.eof", false }
});
cppkafka::TopicConfiguration topic_config = {
{ "auto.offset.reset", "smallest" }
};
// Now configure it to be the default topic config
Config.set_default_topic_configuration(topic_config);
cppkafka::Consumer Consumer(Config);
Consumer.set_assignment_callback([this](const cppkafka::TopicPartitionList& partitions) {
Logger_.information(Poco::format("Partition assigned: %Lu...",(uint64_t )partitions.front().get_partition()));
});
Consumer.set_revocation_callback([this](const cppkafka::TopicPartitionList& partitions) {
Logger_.information(Poco::format("Partition revocation: %Lu...",(uint64_t )partitions.front().get_partition()));
});
Types::StringVec Topics;
for(const auto &i:Notifiers_)
Topics.push_back(i.first);
Consumer.subscribe(Topics);
ConsumerRunning_ = true;
while(ConsumerRunning_) {
try {
cppkafka::Message Msg = Consumer.poll(std::chrono::milliseconds(200));
if (!Msg)
continue;
if (Msg.get_error()) {
if (!Msg.is_eof()) {
Logger_.error(Poco::format("Error: %s", Msg.get_error().to_string()));
}
Consumer.commit(Msg);
continue;
}
SubMutexGuard G(ConsumerMutex_);
auto It = Notifiers_.find(Msg.get_topic());
if (It != Notifiers_.end()) {
Types::TopicNotifyFunctionList &FL = It->second;
std::string Key{Msg.get_key()};
std::string Payload{Msg.get_payload()};
for (auto &F : FL) {
std::thread T(F.first, Key, Payload);
T.detach();
}
}
Consumer.commit(Msg);
} catch (const cppkafka::HandleException &E) {
Logger_.warning(Poco::format("Caught a Kafka exception (consumer): %s",std::string{E.what()}));
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
}
std::string KafkaManager::WrapSystemId(const std::string & PayLoad) {
return std::move( SystemInfoWrapper_ + PayLoad + "}");
}
void KafkaManager::PostMessage(std::string topic, std::string key, std::string PayLoad, bool WrapMessage ) {
if(KafkaEnabled_) {
SubMutexGuard G(Mutex_);
KMessage M{
.Topic = topic,
.Key = key,
.PayLoad = WrapMessage ? WrapSystemId(PayLoad) : PayLoad };
Queue_.push(M);
}
}
int KafkaManager::RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F) {
if(KafkaEnabled_) {
SubMutexGuard G(Mutex_);
auto It = Notifiers_.find(Topic);
if(It == Notifiers_.end()) {
Types::TopicNotifyFunctionList L;
L.emplace(L.end(),std::make_pair(F,FunctionId_));
Notifiers_[Topic] = std::move(L);
} else {
It->second.emplace(It->second.end(),std::make_pair(F,FunctionId_));
}
return FunctionId_++;
} else {
return 0;
}
}
void KafkaManager::UnregisterTopicWatcher(const std::string &Topic, int Id) {
if(KafkaEnabled_) {
SubMutexGuard G(Mutex_);
auto It = Notifiers_.find(Topic);
if(It != Notifiers_.end()) {
Types::TopicNotifyFunctionList & L = It->second;
for(auto it=L.begin(); it!=L.end(); it++)
if(it->second == Id) {
L.erase(it);
break;
}
}
}
}
#endif
} // namespace

72
src/KafkaManager.h Normal file
View File

@@ -0,0 +1,72 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRALGW_KAFKAMANAGER_H
#define UCENTRALGW_KAFKAMANAGER_H
#include <queue>
#include <thread>
#include "SubSystemServer.h"
#include "uCentralTypes.h"
#include "cppkafka/cppkafka.h"
namespace uCentral {
class KafkaManager : public SubSystemServer {
public:
struct KMessage {
std::string Topic,
Key,
PayLoad;
};
void initialize(Poco::Util::Application & self) override;
static KafkaManager *instance() {
if(instance_== nullptr)
instance_ = new KafkaManager;
return instance_;
}
void ProducerThr();
void ConsumerThr();
int Start() override;
void Stop() override;
void PostMessage(std::string topic, std::string key, std::string payload, bool WrapMessage = true);
[[nodiscard]] std::string WrapSystemId(const std::string & PayLoad);
[[nodiscard]] bool Enabled() { return KafkaEnabled_; }
int RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction & F);
void UnregisterTopicWatcher(const std::string &Topic, int FunctionId);
void WakeUp();
private:
static KafkaManager *instance_;
SubMutex ProducerMutex_;
SubMutex ConsumerMutex_;
bool KafkaEnabled_ = false;
std::atomic_bool ProducerRunning_ = false;
std::atomic_bool ConsumerRunning_ = false;
std::queue<KMessage> Queue_;
std::string SystemInfoWrapper_;
std::unique_ptr<std::thread> ConsumerThr_;
std::unique_ptr<std::thread> ProducerThr_;
int FunctionId_=1;
Types::NotifyTable Notifiers_;
std::unique_ptr<cppkafka::Configuration> Config_;
KafkaManager() noexcept;
};
inline KafkaManager * KafkaManager() { return KafkaManager::instance(); }
} // NameSpace
#endif // UCENTRALGW_KAFKAMANAGER_H

View File

@@ -1,14 +1,11 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
// Created by stephane bourque on 2021-06-07.
//
#ifndef UCENTRALGW_KAFKA_TOPICS_H
#define UCENTRALGW_KAFKA_TOPICS_H
namespace OpenWifi::KafkaTopics {
namespace uCentral::KafkaTopics {
static const std::string HEALTHCHECK{"healthcheck"};
static const std::string STATE{"state"};
static const std::string CONNECTION{"connection"};
@@ -16,7 +13,6 @@ namespace OpenWifi::KafkaTopics {
static const std::string ALERTS{"alerts"};
static const std::string COMMAND{"command"};
static const std::string SERVICE_EVENTS{"service_events"};
static const std::string DEVICE_EVENT_QUEUE{"device_event_queue"};
namespace ServiceEvents {
static const std::string EVENT_JOIN{"join"};

495
src/MicroService.cpp Normal file
View File

@@ -0,0 +1,495 @@
//
// Created by stephane bourque on 2021-06-22.
//
#include <cstdlib>
#include <boost/algorithm/string.hpp>
#include "Poco/Util/Application.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Environment.h"
#include "Poco/Net/HTTPSStreamFactory.h"
#include "Poco/Net/HTTPStreamFactory.h"
#include "Poco/Net/FTPSStreamFactory.h"
#include "Poco/Net/FTPStreamFactory.h"
#include "Poco/Path.h"
#include "Poco/File.h"
#include "Poco/String.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
#include "ALBHealthCheckServer.h"
#ifndef SMALL_BUILD
#include "KafkaManager.h"
#endif
#include "Kafka_topics.h"
#include "MicroService.h"
#include "Utils.h"
#ifndef TIP_SECURITY_SERVICE
#include "AuthClient.h"
#endif
namespace uCentral {
void MyErrorHandler::exception(const Poco::Exception & E) {
Poco::Thread * CurrentThread = Poco::Thread::current();
App_.logger().log(E);
App_.logger().error(Poco::format("Exception occurred in %s",CurrentThread->getName()));
}
void MyErrorHandler::exception(const std::exception & E) {
Poco::Thread * CurrentThread = Poco::Thread::current();
App_.logger().warning(Poco::format("std::exception on %s",CurrentThread->getName()));
}
void MyErrorHandler::exception() {
Poco::Thread * CurrentThread = Poco::Thread::current();
App_.logger().warning(Poco::format("exception on %s",CurrentThread->getName()));
}
void MicroService::Exit(int Reason) {
std::exit(Reason);
}
void MicroService::BusMessageReceived(const std::string &Key, const std::string & Message) {
SubMutexGuard G(InfraMutex_);
try {
Poco::JSON::Parser P;
auto Object = P.parse(Message).extract<Poco::JSON::Object::Ptr>();
if (Object->has(KafkaTopics::ServiceEvents::Fields::ID) &&
Object->has(KafkaTopics::ServiceEvents::Fields::EVENT)) {
uint64_t ID = Object->get(KafkaTopics::ServiceEvents::Fields::ID);
auto Event = Object->get(KafkaTopics::ServiceEvents::Fields::EVENT).toString();
if (ID != ID_) {
if( Event==KafkaTopics::ServiceEvents::EVENT_JOIN ||
Event==KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE ||
Event==KafkaTopics::ServiceEvents::EVENT_LEAVE ) {
if( Object->has(KafkaTopics::ServiceEvents::Fields::TYPE) &&
Object->has(KafkaTopics::ServiceEvents::Fields::PUBLIC) &&
Object->has(KafkaTopics::ServiceEvents::Fields::PRIVATE) &&
Object->has(KafkaTopics::ServiceEvents::Fields::VRSN) &&
Object->has(KafkaTopics::ServiceEvents::Fields::KEY)) {
if (Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE && Services_.find(ID) != Services_.end()) {
Services_[ID].LastUpdate = std::time(nullptr);
} else if (Event == KafkaTopics::ServiceEvents::EVENT_LEAVE) {
Services_.erase(ID);
logger().information(Poco::format("Service %s ID=%Lu leaving system.",Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),ID));
} else if (Event == KafkaTopics::ServiceEvents::EVENT_JOIN || Event == KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE) {
logger().information(Poco::format("Service %s ID=%Lu joining system.",Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),ID));
Services_[ID] = MicroServiceMeta{
.Id = ID,
.Type = Poco::toLower(Object->get(KafkaTopics::ServiceEvents::Fields::TYPE).toString()),
.PrivateEndPoint = Object->get(KafkaTopics::ServiceEvents::Fields::PRIVATE).toString(),
.PublicEndPoint = Object->get(KafkaTopics::ServiceEvents::Fields::PUBLIC).toString(),
.AccessKey = Object->get(KafkaTopics::ServiceEvents::Fields::KEY).toString(),
.Version = Object->get(KafkaTopics::ServiceEvents::Fields::VRSN).toString(),
.LastUpdate = (uint64_t)std::time(nullptr)};
for (const auto &[Id, Svc] : Services_) {
logger().information(Poco::format("ID: %Lu Type: %s EndPoint: %s",Id,Svc.Type,Svc.PrivateEndPoint));
}
}
} else {
logger().error(Poco::format("KAFKA-MSG: invalid event '%s', missing a field.",Event));
}
} else if (Event==KafkaTopics::ServiceEvents::EVENT_REMOVE_TOKEN) {
if(Object->has(KafkaTopics::ServiceEvents::Fields::TOKEN)) {
#ifndef TIP_SECURITY_SERVICE
AuthClient()->RemovedCachedToken(Object->get(KafkaTopics::ServiceEvents::Fields::TOKEN).toString());
#endif
} else {
logger().error(Poco::format("KAFKA-MSG: invalid event '%s', missing token",Event));
}
} else {
logger().error(Poco::format("Unknown Event: %s Source: %Lu", Event, ID));
}
}
} else {
logger().error("Bad bus message.");
}
} catch (const Poco::Exception &E) {
logger().log(E);
}
}
MicroServiceMetaVec MicroService::GetServices(const std::string & Type) {
SubMutexGuard G(InfraMutex_);
auto T = Poco::toLower(Type);
MicroServiceMetaVec Res;
for(const auto &[Id,ServiceRec]:Services_) {
if(ServiceRec.Type==T)
Res.push_back(ServiceRec);
}
return Res;
}
MicroServiceMetaVec MicroService::GetServices() {
SubMutexGuard G(InfraMutex_);
MicroServiceMetaVec Res;
for(const auto &[Id,ServiceRec]:Services_) {
Res.push_back(ServiceRec);
}
return Res;
}
void MicroService::initialize(Poco::Util::Application &self) {
std::string V{APP_VERSION};
std::string B{BUILD_NUMBER};
Version_ = V + "(" + B + ")";
// add the default services
SubSystems_.push_back(KafkaManager());
SubSystems_.push_back(ALBHealthCheckServer());
Poco::Net::initializeSSL();
Poco::Net::HTTPStreamFactory::registerFactory();
Poco::Net::HTTPSStreamFactory::registerFactory();
Poco::Net::FTPStreamFactory::registerFactory();
Poco::Net::FTPSStreamFactory::registerFactory();
std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR,".");
Poco::Path ConfigFile;
ConfigFile = ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_;
if(!ConfigFile.isFile())
{
std::cerr << DAEMON_APP_NAME << ": Configuration "
<< ConfigFile.toString() << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR
+ " env variable the path of the " + DAEMON_PROPERTIES_FILENAME + " file." << std::endl;
std::exit(Poco::Util::Application::EXIT_CONFIG);
}
static const char * LogFilePathKey = "logging.channels.c2.path";
loadConfiguration(ConfigFile.toString());
if(LogDir_.empty()) {
std::string OriginalLogFileValue = ConfigPath(LogFilePathKey);
config().setString(LogFilePathKey, OriginalLogFileValue);
} else {
config().setString(LogFilePathKey, LogDir_);
}
Poco::File DataDir(ConfigPath("ucentral.system.data"));
DataDir_ = DataDir.path();
if(!DataDir.exists()) {
try {
DataDir.createDirectory();
} catch (const Poco::Exception &E) {
logger().log(E);
}
}
std::string KeyFile = ConfigPath("ucentral.service.key");
AppKey_ = Poco::SharedPtr<Poco::Crypto::RSAKey>(new Poco::Crypto::RSAKey("", KeyFile, ""));
Cipher_ = CipherFactory_.createCipher(*AppKey_);
ID_ = Utils::GetSystemId();
if(!DebugMode_)
DebugMode_ = ConfigGetBool("ucentral.system.debug",false);
MyPrivateEndPoint_ = ConfigGetString("ucentral.system.uri.private");
MyPublicEndPoint_ = ConfigGetString("ucentral.system.uri.public");
UIURI_ = ConfigGetString("ucentral.system.uri.ui");
MyHash_ = CreateHash(MyPublicEndPoint_);
InitializeSubSystemServers();
ServerApplication::initialize(self);
Types::TopicNotifyFunction F = [this](std::string s1,std::string s2) { this->BusMessageReceived(s1,s2); };
KafkaManager()->RegisterTopicWatcher(KafkaTopics::SERVICE_EVENTS, F);
}
void MicroService::uninitialize() {
// add your own uninitialization code here
ServerApplication::uninitialize();
}
void MicroService::reinitialize(Poco::Util::Application &self) {
ServerApplication::reinitialize(self);
// add your own reinitialization code here
}
void MicroService::defineOptions(Poco::Util::OptionSet &options) {
ServerApplication::defineOptions(options);
options.addOption(
Poco::Util::Option("help", "", "display help information on command line arguments")
.required(false)
.repeatable(false)
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleHelp)));
options.addOption(
Poco::Util::Option("file", "", "specify the configuration file")
.required(false)
.repeatable(false)
.argument("file")
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleConfig)));
options.addOption(
Poco::Util::Option("debug", "", "to run in debug, set to true")
.required(false)
.repeatable(false)
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleDebug)));
options.addOption(
Poco::Util::Option("logs", "", "specify the log directory and file (i.e. dir/file.log)")
.required(false)
.repeatable(false)
.argument("dir")
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleLogs)));
options.addOption(
Poco::Util::Option("version", "", "get the version and quit.")
.required(false)
.repeatable(false)
.callback(Poco::Util::OptionCallback<MicroService>(this, &MicroService::handleVersion)));
}
void MicroService::handleHelp(const std::string &name, const std::string &value) {
HelpRequested_ = true;
displayHelp();
stopOptionsProcessing();
}
void MicroService::handleVersion(const std::string &name, const std::string &value) {
HelpRequested_ = true;
std::cout << Version() << std::endl;
stopOptionsProcessing();
}
void MicroService::handleDebug(const std::string &name, const std::string &value) {
if(value == "true")
DebugMode_ = true ;
}
void MicroService::handleLogs(const std::string &name, const std::string &value) {
LogDir_ = value;
}
void MicroService::handleConfig(const std::string &name, const std::string &value) {
ConfigFileName_ = value;
}
void MicroService::displayHelp() {
Poco::Util::HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A " + DAEMON_APP_NAME + " implementation for TIP.");
helpFormatter.format(std::cout);
}
void MicroService::InitializeSubSystemServers() {
for(auto i:SubSystems_)
addSubsystem(i);
}
void MicroService::StartSubSystemServers() {
for(auto i:SubSystems_) {
i->Start();
}
BusEventManager_.Start();
}
void MicroService::StopSubSystemServers() {
BusEventManager_.Stop();
for(auto i=SubSystems_.rbegin(); i!=SubSystems_.rend(); ++i)
(*i)->Stop();
}
std::string MicroService::CreateUUID() {
return UUIDGenerator_.create().toString();
}
bool MicroService::SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level) {
try {
auto P = Poco::Logger::parseLevel(Level);
auto Sub = Poco::toLower(SubSystem);
if (Sub == "all") {
for (auto i : SubSystems_) {
i->Logger().setLevel(P);
}
return true;
} else {
// std::cout << "Sub:" << SubSystem << " Level:" << Level << std::endl;
for (auto i : SubSystems_) {
if (Sub == Poco::toLower(i->Name())) {
i->Logger().setLevel(P);
return true;
}
}
}
} catch (const Poco::Exception & E) {
std::cout << "Exception" << std::endl;
}
return false;
}
Types::StringVec MicroService::GetSubSystems() const {
Types::StringVec Result;
for(auto i:SubSystems_)
Result.push_back(i->Name());
return Result;
}
Types::StringPairVec MicroService::GetLogLevels() const {
Types::StringPairVec Result;
for(auto &i:SubSystems_) {
auto P = std::make_pair( i->Name(), Utils::LogLevelToString(i->GetLoggingLevel()));
Result.push_back(P);
}
return Result;
}
const Types::StringVec & MicroService::GetLogLevelNames() const {
static Types::StringVec LevelNames{"none", "fatal", "critical", "error", "warning", "notice", "information", "debug", "trace" };
return LevelNames;
}
uint64_t MicroService::ConfigGetInt(const std::string &Key,uint64_t Default) {
return (uint64_t) config().getInt64(Key,Default);
}
uint64_t MicroService::ConfigGetInt(const std::string &Key) {
return config().getInt(Key);
}
uint64_t MicroService::ConfigGetBool(const std::string &Key,bool Default) {
return config().getBool(Key,Default);
}
uint64_t MicroService::ConfigGetBool(const std::string &Key) {
return config().getBool(Key);
}
std::string MicroService::ConfigGetString(const std::string &Key,const std::string & Default) {
return config().getString(Key, Default);
}
std::string MicroService::ConfigGetString(const std::string &Key) {
return config().getString(Key);
}
std::string MicroService::ConfigPath(const std::string &Key,const std::string & Default) {
std::string R = config().getString(Key, Default);
return Poco::Path::expand(R);
}
std::string MicroService::ConfigPath(const std::string &Key) {
std::string R = config().getString(Key);
return Poco::Path::expand(R);
}
std::string MicroService::Encrypt(const std::string &S) {
return Cipher_->encryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);;
}
std::string MicroService::Decrypt(const std::string &S) {
return Cipher_->decryptString(S, Poco::Crypto::Cipher::Cipher::ENC_BASE64);;
}
std::string MicroService::CreateHash(const std::string &S) {
SHA2_.update(S);
return Utils::ToHex(SHA2_.digest());
}
std::string MicroService::MakeSystemEventMessage( const std::string & Type ) const {
Poco::JSON::Object Obj;
Obj.set(KafkaTopics::ServiceEvents::Fields::EVENT,Type);
Obj.set(KafkaTopics::ServiceEvents::Fields::ID,ID_);
Obj.set(KafkaTopics::ServiceEvents::Fields::TYPE,Poco::toLower(DAEMON_APP_NAME));
Obj.set(KafkaTopics::ServiceEvents::Fields::PUBLIC,MyPublicEndPoint_);
Obj.set(KafkaTopics::ServiceEvents::Fields::PRIVATE,MyPrivateEndPoint_);
Obj.set(KafkaTopics::ServiceEvents::Fields::KEY,MyHash_);
Obj.set(KafkaTopics::ServiceEvents::Fields::VRSN,Version_);
std::stringstream ResultText;
Poco::JSON::Stringifier::stringify(Obj, ResultText);
return ResultText.str();
}
void BusEventManager::run() {
Running_ = true;
auto Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN);
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false);
while(Running_) {
Poco::Thread::trySleep((unsigned long)Daemon()->DaemonBusTimer());
if(!Running_)
break;
auto Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE);
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false);
}
Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_LEAVE);
KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false);
};
void BusEventManager::Start() {
if(KafkaManager()->Enabled()) {
Thread_.start(*this);
}
}
void BusEventManager::Stop() {
if(KafkaManager()->Enabled()) {
Running_ = false;
Thread_.wakeUp();
Thread_.join();
}
}
[[nodiscard]] bool MicroService::IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request) {
try {
auto APIKEY = Request.get("X-API-KEY");
return APIKEY == MyHash_;
} catch (const Poco::Exception &E) {
logger().log(E);
}
return false;
}
void MicroService::SavePID() {
try {
std::ofstream O;
O.open(Daemon()->DataDir() + "/pidfile",std::ios::binary | std::ios::trunc);
O << Poco::Process::id();
O.close();
} catch (...)
{
std::cout << "Could not save system ID" << std::endl;
}
}
int MicroService::main(const ArgVec &args) {
MyErrorHandler ErrorHandler(*this);
Poco::ErrorHandler::set(&ErrorHandler);
if (!HelpRequested_) {
SavePID();
Poco::Logger &logger = Poco::Logger::get(DAEMON_APP_NAME);
logger.notice(Poco::format("Starting %s version %s.",DAEMON_APP_NAME, Version()));
if(Poco::Net::Socket::supportsIPv6())
logger.information("System supports IPv6.");
else
logger.information("System does NOT support IPv6.");
if (config().getBool("application.runAsDaemon", false)) {
logger.information("Starting as a daemon.");
}
logger.information(Poco::format("System ID set to %Lu",ID_));
StartSubSystemServers();
waitForTerminationRequest();
StopSubSystemServers();
logger.notice(Poco::format("Stopped %s...",DAEMON_APP_NAME));
}
return Application::EXIT_OK;
}
}

168
src/MicroService.h Normal file
View File

@@ -0,0 +1,168 @@
//
// Created by stephane bourque on 2021-06-22.
//
#ifndef UCENTRALGW_MICROSERVICE_H
#define UCENTRALGW_MICROSERVICE_H
#include <array>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <set>
#include "Poco/Util/Application.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/UUIDGenerator.h"
#include "Poco/ErrorHandler.h"
#include "Poco/Crypto/RSAKey.h"
#include "Poco/Crypto/CipherFactory.h"
#include "Poco/Crypto/Cipher.h"
#include "Poco/SHA2Engine.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Process.h"
#include "uCentralTypes.h"
#include "SubSystemServer.h"
namespace uCentral {
static const std::string uSERVICE_SECURITY{"ucentralsec"};
static const std::string uSERVICE_GATEWAY{"ucentralgw"};
static const std::string uSERVICE_FIRMWARE{ "ucentralfws"};
class MyErrorHandler : public Poco::ErrorHandler {
public:
explicit MyErrorHandler(Poco::Util::Application &App) : App_(App) {}
void exception(const Poco::Exception & E) override;
void exception(const std::exception & E) override;
void exception() override;
private:
Poco::Util::Application &App_;
};
class BusEventManager : public Poco::Runnable {
public:
void run() override;
void Start();
void Stop();
private:
std::atomic_bool Running_ = false;
Poco::Thread Thread_;
};
struct MicroServiceMeta {
uint64_t Id=0;
std::string Type;
std::string PrivateEndPoint;
std::string PublicEndPoint;
std::string AccessKey;
std::string Version;
uint64_t LastUpdate=0;
};
typedef std::map<uint64_t, MicroServiceMeta> MicroServiceMetaMap;
typedef std::vector<MicroServiceMeta> MicroServiceMetaVec;
class MicroService : public Poco::Util::ServerApplication {
public:
explicit MicroService( std::string PropFile,
std::string RootEnv,
std::string ConfigVar,
std::string AppName,
uint64_t BusTimer,
Types::SubSystemVec Subsystems) :
DAEMON_PROPERTIES_FILENAME(std::move(PropFile)),
DAEMON_ROOT_ENV_VAR(std::move(RootEnv)),
DAEMON_CONFIG_ENV_VAR(std::move(ConfigVar)),
DAEMON_APP_NAME(std::move(AppName)),
DAEMON_BUS_TIMER(BusTimer),
SubSystems_(std::move(Subsystems)) {}
int main(const ArgVec &args) override;
void initialize(Application &self) override;
void uninitialize() override;
void reinitialize(Application &self) override;
void defineOptions(Poco::Util::OptionSet &options) override;
void handleHelp(const std::string &name, const std::string &value);
void handleVersion(const std::string &name, const std::string &value);
void handleDebug(const std::string &name, const std::string &value);
void handleLogs(const std::string &name, const std::string &value);
void handleConfig(const std::string &name, const std::string &value);
void displayHelp();
void InitializeSubSystemServers();
void StartSubSystemServers();
void StopSubSystemServers();
void Exit(int Reason);
bool SetSubsystemLogLevel(const std::string & SubSystem, const std::string & Level);
[[nodiscard]] std::string Version() { return Version_; }
[[nodiscard]] const Poco::SharedPtr<Poco::Crypto::RSAKey> & Key() { return AppKey_; }
[[nodiscard]] inline const std::string & DataDir() { return DataDir_; }
[[nodiscard]] std::string CreateUUID();
[[nodiscard]] bool Debug() const { return DebugMode_; }
[[nodiscard]] uint64_t ID() const { return ID_; }
[[nodiscard]] Types::StringVec GetSubSystems() const;
[[nodiscard]] Types::StringPairVec GetLogLevels() const;
[[nodiscard]] const Types::StringVec & GetLogLevelNames() const;
[[nodiscard]] std::string ConfigGetString(const std::string &Key,const std::string & Default);
[[nodiscard]] std::string ConfigGetString(const std::string &Key);
[[nodiscard]] std::string ConfigPath(const std::string &Key,const std::string & Default);
[[nodiscard]] std::string ConfigPath(const std::string &Key);
[[nodiscard]] uint64_t ConfigGetInt(const std::string &Key,uint64_t Default);
[[nodiscard]] uint64_t ConfigGetInt(const std::string &Key);
[[nodiscard]] uint64_t ConfigGetBool(const std::string &Key,bool Default);
[[nodiscard]] uint64_t ConfigGetBool(const std::string &Key);
[[nodiscard]] std::string Encrypt(const std::string &S);
[[nodiscard]] std::string Decrypt(const std::string &S);
[[nodiscard]] std::string CreateHash(const std::string &S);
[[nodiscard]] std::string Hash() const { return MyHash_; };
[[nodiscard]] std::string ServiceType() const { return DAEMON_APP_NAME; };
[[nodiscard]] std::string PrivateEndPoint() const { return MyPrivateEndPoint_; };
[[nodiscard]] std::string PublicEndPoint() const { return MyPublicEndPoint_; };
[[nodiscard]] std::string MakeSystemEventMessage( const std::string & Type ) const ;
inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; };
void BusMessageReceived( const std::string & Key, const std::string & Message);
[[nodiscard]] MicroServiceMetaVec GetServices(const std::string & type);
[[nodiscard]] MicroServiceMetaVec GetServices();
[[nodiscard]] bool IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request);
void SavePID();
inline uint64_t GetPID() { return Poco::Process::id(); };
[[nodiscard]] inline const std::string GetPublicAPIEndPoint() const { return MyPublicEndPoint_ + "/api/v1"; };
[[nodiscard]] inline const std::string & GetUIURI() const { return UIURI_;};
private:
bool HelpRequested_ = false;
std::string LogDir_;
std::string ConfigFileName_;
Poco::UUIDGenerator UUIDGenerator_;
uint64_t ID_ = 1;
Poco::SharedPtr<Poco::Crypto::RSAKey> AppKey_ = nullptr;
bool DebugMode_ = false;
std::string DataDir_;
Types::SubSystemVec SubSystems_;
Poco::Crypto::CipherFactory & CipherFactory_ = Poco::Crypto::CipherFactory::defaultFactory();
Poco::Crypto::Cipher * Cipher_ = nullptr;
Poco::SHA2Engine SHA2_;
MicroServiceMetaMap Services_;
std::string MyHash_;
std::string MyPrivateEndPoint_;
std::string MyPublicEndPoint_;
std::string UIURI_;
std::string Version_;
BusEventManager BusEventManager_;
SubMutex InfraMutex_;
std::string DAEMON_PROPERTIES_FILENAME;
std::string DAEMON_ROOT_ENV_VAR;
std::string DAEMON_CONFIG_ENV_VAR;
std::string DAEMON_APP_NAME;
uint64_t DAEMON_BUS_TIMER;
};
}
#endif // UCENTRALGW_MICROSERVICE_H

View File

@@ -6,6 +6,7 @@
#include <vector>
#include "OUIServer.h"
#include "Daemon.h"
#include "Poco/String.h"
#include "Poco/StringTokenizer.h"
@@ -14,10 +15,10 @@
#include "Poco/URI.h"
#include "Poco/File.h"
#include "OUIServer.h"
#include "framework/MicroService.h"
#include "Utils.h"
namespace OpenWifi {
namespace uCentral {
class OUIServer * OUIServer::instance_;
int OUIServer::Start() {
Running_=true;
@@ -37,17 +38,10 @@ namespace OpenWifi {
Updater.detach();
}
void OUIServer::reinitialize(Poco::Util::Application &self) {
MicroService::instance().LoadConfigurationFile();
Logger_.information("Reinitializing.");
Stop();
Start();
}
bool OUIServer::GetFile(const std::string &FileName) {
try {
std::unique_ptr<std::istream> pStr(
Poco::URIStreamOpener::defaultOpener().open(MicroService::instance().ConfigGetString("oui.download.uri")));
Poco::URIStreamOpener::defaultOpener().open(Daemon()->ConfigGetString("oui.download.uri")));
std::ofstream OS;
Poco::File F(FileName);
if(F.exists())
@@ -103,12 +97,12 @@ namespace OpenWifi {
Updating_ = true;
// fetch data from server, if not available, just use the file we already have.
std::string LatestOUIFileName{ MicroService::instance().DataDir() + "/newOUIFile.txt"};
std::string CurrentOUIFileName{ MicroService::instance().DataDir() + "/current_oui.txt"};
std::string LatestOUIFileName{ Daemon()->DataDir() + "/newOUIFile.txt"};
std::string CurrentOUIFileName{ Daemon()->DataDir() + "/current_oui.txt"};
OUIMap TmpOUIs;
if(GetFile(LatestOUIFileName) && ProcessFile(LatestOUIFileName, TmpOUIs)) {
std::lock_guard G(Mutex_);
SubMutexGuard G(Mutex_);
OUIs_ = std::move(TmpOUIs);
LastUpdate_ = time(nullptr);
Poco::File F1(CurrentOUIFileName);
@@ -120,7 +114,7 @@ namespace OpenWifi {
} else if(OUIs_.empty()) {
if(ProcessFile(CurrentOUIFileName, TmpOUIs)) {
LastUpdate_ = time(nullptr);
std::lock_guard G(Mutex_);
SubMutexGuard G(Mutex_);
OUIs_ = std::move(TmpOUIs);
}
}
@@ -128,7 +122,7 @@ namespace OpenWifi {
}
std::string OUIServer::GetManufacturer(const std::string &MAC) {
std::lock_guard Guard(Mutex_);
SubMutexGuard Guard(Mutex_);
auto Manufacturer = OUIs_.find(Utils::SerialNumberToOUI(MAC));
if(Manufacturer != OUIs_.end())
return Manufacturer->second;

View File

@@ -5,9 +5,9 @@
#ifndef UCENTRALGW_OUISERVER_H
#define UCENTRALGW_OUISERVER_H
#include "framework/MicroService.h"
#include "SubSystemServer.h"
namespace OpenWifi {
namespace uCentral {
class OUIServer : public SubSystemServer {
public:
@@ -15,15 +15,14 @@ namespace OpenWifi {
typedef std::map<uint64_t,std::string> OUIMap;
static OUIServer *instance() {
static OUIServer *instance_ = new OUIServer;
if (instance_ == nullptr) {
instance_ = new OUIServer;
}
return instance_;
}
int Start() override;
void Stop() override;
void reinitialize(Poco::Util::Application &self) override;
void Update();
void UpdateImpl();
[[nodiscard]] std::string GetManufacturer(const std::string &MAC);
@@ -31,6 +30,7 @@ namespace OpenWifi {
[[nodiscard]] bool ProcessFile(const std::string &FileName, OUIMap &Map);
private:
static OUIServer * instance_;
uint64_t LastUpdate_ = 0 ;
bool ValidFile_=false;
OUIMap OUIs_;

68
src/OpenAPIRequest.cpp Normal file
View File

@@ -0,0 +1,68 @@
//
// Created by stephane bourque on 2021-07-01.
//
#include <iostream>
#include "OpenAPIRequest.h"
#include "Poco/Net/HTTPSClientSession.h"
#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/StreamCopier.h>
#include <Poco/JSON/Parser.h>
#include <Poco/Path.h>
#include <Poco/URI.h>
#include <Poco/Exception.h>
#include "Utils.h"
#include "Daemon.h"
namespace uCentral {
OpenAPIRequestGet::OpenAPIRequestGet( const std::string & ServiceType,
const std::string & EndPoint,
Types::StringPairVec & QueryData,
uint64_t msTimeout):
Type_(ServiceType),
EndPoint_(EndPoint),
QueryData_(QueryData),
msTimeout_(msTimeout) {
}
int OpenAPIRequestGet::Do(Poco::JSON::Object::Ptr &ResponseObject) {
try {
auto Services = Daemon()->GetServices(Type_);
for(auto const &Svc:Services) {
Poco::URI URI(Svc.PrivateEndPoint);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
URI.setPath(EndPoint_);
for (const auto &qp : QueryData_)
URI.addQueryParameter(qp.first, qp.second);
std::string Path(URI.getPathAndQuery());
Session.setTimeout(Poco::Timespan(5, 0));
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET,
Path,
Poco::Net::HTTPMessage::HTTP_1_1);
Request.add("X-API-KEY", Svc.AccessKey);
Session.sendRequest(Request);
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Parser P;
ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>();
}
return Response.getStatus();
}
}
catch (const Poco::Exception &E)
{
std::cerr << E.displayText() << std::endl;
}
return -1;
}
}

29
src/OpenAPIRequest.h Normal file
View File

@@ -0,0 +1,29 @@
//
// Created by stephane bourque on 2021-07-01.
//
#ifndef UCENTRALGW_OPENAPIREQUEST_H
#define UCENTRALGW_OPENAPIREQUEST_H
#include "Poco/JSON/Object.h"
#include "uCentralTypes.h"
namespace uCentral {
class OpenAPIRequestGet {
public:
explicit OpenAPIRequestGet( const std::string & Type,
const std::string & EndPoint,
Types::StringPairVec & QueryData,
uint64_t msTimeout);
int Do(Poco::JSON::Object::Ptr &ResponseObject);
private:
std::string Type_;
std::string EndPoint_;
Types::StringPairVec QueryData_;
uint64_t msTimeout_;
};
}
#endif // UCENTRALGW_OPENAPIREQUEST_H

View File

@@ -1,118 +0,0 @@
//
// Created by stephane bourque on 2021-06-28.
//
#include <cctype>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <future>
#include <numeric>
#include <chrono>
#include "RESTAPI_RPC.h"
#include "CommandManager.h"
#include "DeviceRegistry.h"
#include "StorageService.h"
#include "framework/uCentral_Protocol.h"
namespace OpenWifi::RESTAPI_RPC {
void SetCommandStatus(GWObjects::CommandDetails &Cmd,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
RESTAPIHandler *Handler,
OpenWifi::Storage::CommandExecutionType Status,
Poco::Logger &Logger) {
if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
Poco::JSON::Object RetObj;
Cmd.to_json(RetObj);
Handler->ReturnObject(RetObj);
return;
} else {
Handler->ReturnStatus(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
return;
}
}
void WaitForCommand(GWObjects::CommandDetails &Cmd,
Poco::JSON::Object & Params,
Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response,
int64_t WaitTimeInMs,
Poco::JSON::Object * ObjectToReturn,
RESTAPIHandler * Handler,
Poco::Logger &Logger) {
// if the command should be executed in the future, or if the device is not connected, then we should just add the command to
// the DB and let it figure out when to deliver the command.
if(Cmd.RunAt || !DeviceRegistry()->Connected(Cmd.SerialNumber)) {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_PENDING, Logger);
return;
}
Cmd.Executed = std::time(nullptr);
uint64_t RPC_Id=0;
if (CommandManager()->SendCommand(Cmd.SerialNumber, Cmd.Command, Params, Cmd.UUID, RPC_Id)) {
CommandTag T;
while (CommandManager()->Running() && WaitTimeInMs > 0) {
if (CommandManager()->GetCommand(RPC_Id, Cmd.SerialNumber, T)) {
auto Answer = T.Result;
if (Answer->has("result") && Answer->isObject("result")) {
auto ResultFields =
Answer->get("result").extract<Poco::JSON::Object::Ptr>();
if (ResultFields->has("status") && ResultFields->isObject("status")) {
auto StatusInnerObj =
ResultFields->get("status").extract<Poco::JSON::Object::Ptr>();
if (StatusInnerObj->has("error"))
Cmd.ErrorCode = StatusInnerObj->get("error");
if (StatusInnerObj->has("text"))
Cmd.ErrorText = StatusInnerObj->get("text").toString();
std::stringstream ResultText;
Poco::JSON::Stringifier::stringify(Answer->get("result"), ResultText);
Cmd.Results = ResultText.str();
Cmd.Status = "completed";
Cmd.Completed = time(nullptr);
if (Cmd.ErrorCode && Cmd.Command == uCentralProtocol::TRACE) {
Cmd.WaitingForFile = 0;
Cmd.AttachDate = Cmd.AttachSize = 0;
Cmd.AttachType = "";
}
// Add the completed command to the database...
StorageService()->AddCommand(Cmd.SerialNumber, Cmd,
Storage::COMMAND_COMPLETED);
if (ObjectToReturn) {
Handler->ReturnObject(*ObjectToReturn);
} else {
Poco::JSON::Object O;
Cmd.to_json(O);
Handler->ReturnObject(O);
}
return;
} else {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_FAILED, Logger);
Logger.information(Poco::format("Invalid response for command '%s'. Missing status.", Cmd.UUID));
return;
}
} else {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_FAILED, Logger);
Logger.information(Poco::format("Invalid response for command '%s'. Missing result.", Cmd.UUID));
return;
}
} else {
Poco::Thread::trySleep(100);
WaitTimeInMs -= 100;
}
}
if(WaitTimeInMs<0)
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_TIMEDOUT, Logger);
else
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_PENDING, Logger);
} else {
SetCommandStatus(Cmd, Request, Response, Handler, Storage::COMMAND_PENDING, Logger);
}
}
}

View File

@@ -1,48 +0,0 @@
//
// Created by stephane bourque on 2021-09-16.
//
#include "RESTAPI_TelemetryWebSocket.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/NetException.h"
#include "TelemetryStream.h"
namespace OpenWifi {
void RESTAPI_TelemetryWebSocket::DoGet() {
// try and upgrade this session to websocket...
if (Request->find("Upgrade") != Request->end() &&
Poco::icompare((*Request)["Upgrade"], "websocket") == 0) {
try {
Poco::URI U(Request->getURI());
std::string UUID, SerialNumber;
auto Parameters = U.getQueryParameters();
for (const auto &i : Parameters) {
if (i.first == "serialNumber") {
SerialNumber = i.second;
} else if(i.first=="uuid") {
UUID = i.second;
}
}
auto WS = Poco::SharedPtr<Poco::Net::WebSocket>( new Poco::Net::WebSocket(*Request, *Response));
new TelemetryClient(UUID, SerialNumber, WS, TelemetryStream()->NextReactor(), Logger_);
} catch (const Poco::Net::WebSocketException &E) {
Logger_.log(E);
switch (E.code()) {
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION:
Response->set("Sec-WebSocket-Version", Poco::Net::WebSocket::WEBSOCKET_VERSION);
// fallthrough
case Poco::Net::WebSocket::WS_ERR_NO_HANDSHAKE:
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_VERSION:
case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_KEY:
Response->setStatusAndReason(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Response->setContentLength(0);
Response->send();
break;
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
}
}

View File

@@ -1,28 +0,0 @@
//
// Created by stephane bourque on 2021-09-16.
//
#ifndef OWGW_RESTAPI_TELEMETRYWEBSOCKET_H
#define OWGW_RESTAPI_TELEMETRYWEBSOCKET_H
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_TelemetryWebSocket : public RESTAPIHandler {
public:
RESTAPI_TelemetryWebSocket(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{ Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Internal,false) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/ws_telemetry"};}
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
private:
void Process(const Poco::JSON::Object::Ptr &O, std::string &Answer);
};
}
#endif // OWGW_RESTAPI_TELEMETRYWEBSOCKET_H

View File

@@ -1,120 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include <ctime>
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
#include "RESTAPI_blacklist.h"
#include "StorageService.h"
#include "framework/RESTAPI_errors.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_blacklist::DoDelete() {
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
GWObjects::BlackListedDevice D;
if(!StorageService()->GetBlackListDevice(SerialNumber, D)) {
return NotFound();
}
if (StorageService()->DeleteBlackListDevice(SerialNumber)) {
return OK();
}
BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
}
void RESTAPI_blacklist::DoGet() {
auto SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, "");
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
GWObjects::BlackListedDevice D;
if(!StorageService()->GetBlackListDevice(SerialNumber, D)) {
return NotFound();
}
Poco::JSON::Object Answer;
D.to_json(Answer);
return ReturnObject(Answer);
}
void RESTAPI_blacklist::DoPost() {
auto Obj = ParseStream();
GWObjects::BlackListedDevice D;
if(!D.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(D.serialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
Poco::toLowerInPlace(D.serialNumber);
if(StorageService()->IsBlackListed(D.serialNumber)) {
return BadRequest(RESTAPI::Errors::SerialNumberExists);
}
D.author = UserInfo_.userinfo.email;
D.created = std::time(nullptr);
if(StorageService()->AddBlackListDevice(D)) {
GWObjects::BlackListedDevice CreatedDevice;
StorageService()->GetBlackListDevice(D.serialNumber,CreatedDevice);
Poco::JSON::Object Answer;
CreatedDevice.to_json(Answer);
return ReturnObject(Answer);
}
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
void RESTAPI_blacklist::DoPut() {
auto SerialNumber = Poco::toLower(GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""));
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
auto Obj = ParseStream();
GWObjects::BlackListedDevice Existing;
if(!StorageService()->GetBlackListDevice(SerialNumber, Existing)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
GWObjects::BlackListedDevice NewDevice;
if(!NewDevice.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
Existing.reason = NewDevice.reason;
Existing.author = UserInfo_.userinfo.email;
if(StorageService()->UpdateBlackListDevice(SerialNumber, Existing)) {
GWObjects::BlackListedDevice CreatedDevice;
StorageService()->GetBlackListDevice(SerialNumber,CreatedDevice);
Poco::JSON::Object Answer;
CreatedDevice.to_json(Answer);
return ReturnObject(Answer);
}
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
}

View File

@@ -1,34 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#ifndef UCENTRALGW_RESTAPI_BLACKLIST_H
#define UCENTRALGW_RESTAPI_BLACKLIST_H
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_blacklist : public RESTAPIHandler {
public:
RESTAPI_blacklist(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_PUT,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/blacklist/{serialNumber}"};}
void DoGet() final;
void DoDelete() final;
void DoPost() final;
void DoPut() final;
};
}
#endif // UCENTRALGW_RESTAPI_BLACKLIST_H

View File

@@ -1,28 +0,0 @@
//
// Created by stephane bourque on 2021-10-14.
//
#include "RESTAPI_blacklist_list.h"
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
#include "StorageService.h"
namespace OpenWifi {
void RESTAPI_blacklist_list::DoGet() {
std::vector<GWObjects::BlackListedDevice> Devices;
Poco::JSON::Array Arr;
Poco::JSON::Object Answer;
if(StorageService()->GetBlackListDevices(QB_.Offset, QB_.Limit, Devices)) {
for(const auto &i:Devices) {
Poco::JSON::Object O;
i.to_json(O);
Arr.add(O);
}
}
Answer.set("devices", Arr);
return ReturnObject(Answer);
}
}

View File

@@ -1,27 +0,0 @@
//
// Created by stephane bourque on 2021-10-14.
//
#ifndef UCENTRALGW_RESTAPI_BLACKLIST_LIST_H
#define UCENTRALGW_RESTAPI_BLACKLIST_LIST_H
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_blacklist_list : public RESTAPIHandler {
public:
RESTAPI_blacklist_list(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/blacklist"};}
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
};
}
#endif // UCENTRALGW_RESTAPI_BLACKLIST_LIST_H

View File

@@ -1,28 +0,0 @@
//
// Created by stephane bourque on 2021-10-17.
//
#include "RESTAPI_capabilities_handler.h"
#include "StorageService.h"
namespace OpenWifi {
void RESTAPI_capabilities_handler::DoGet() {
Storage::DeviceCapabilitiesCache DevCaps;
StorageService()->GetDeviceCapabilitiesCache(DevCaps);
Poco::JSON::Array ObjArr;
for(const auto &[deviceType,capabilities]:DevCaps) {
Poco::JSON::Object Inner;
Inner.set("deviceType",deviceType);
Poco::JSON::Parser P;
auto R = P.parse(capabilities).extract<Poco::JSON::Object::Ptr>();
Inner.set("capabilities", R);
ObjArr.add(Inner);
}
Poco::JSON::Object Answer;
Answer.set("devices",ObjArr);
return ReturnObject(Answer);
}
}

View File

@@ -1,26 +0,0 @@
//
// Created by stephane bourque on 2021-10-17.
//
#ifndef UCENTRALGW_RESTAPI_CAPABILITIES_HANDLER_H
#define UCENTRALGW_RESTAPI_CAPABILITIES_HANDLER_H
#include "framework/MicroService.h"
namespace OpenWifi {
class RESTAPI_capabilities_handler : public RESTAPIHandler {
public:
RESTAPI_capabilities_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server,
Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/capabilities"};}
void DoGet() final;
void DoDelete() final {};
void DoPost() final {};
void DoPut() final {};
};
}
#endif // UCENTRALGW_RESTAPI_CAPABILITIES_HANDLER_H

View File

@@ -1,44 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "RESTAPI_command.h"
#include "StorageService.h"
#include "framework/RESTAPI_errors.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_command::DoGet() {
auto CommandUUID = GetBinding(RESTAPI::Protocol::COMMANDUUID, "");
GWObjects::CommandDetails Command;
if (StorageService()->GetCommand(CommandUUID, Command)) {
Poco::JSON::Object RetObj;
Command.to_json(RetObj);
return ReturnObject(RetObj);
}
return NotFound();
}
void RESTAPI_command::DoDelete() {
auto UUID = GetBinding(RESTAPI::Protocol::COMMANDUUID, "");
if(UUID.empty()) {
return BadRequest(RESTAPI::Errors::MissingUUID);
}
GWObjects::CommandDetails C;
if(!StorageService()->GetCommand(UUID, C)) {
return NotFound();
}
if (StorageService()->DeleteCommand(UUID)) {
return OK();
}
return InternalError();
}
}

View File

@@ -1,46 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "RESTAPI_commands.h"
#include "StorageService.h"
#include "framework/RESTAPI_errors.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_commands::DoGet() {
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
std::vector<GWObjects::CommandDetails> Commands;
if (QB_.Newest) {
StorageService()->GetNewestCommands(SerialNumber, QB_.Limit, Commands);
} else {
StorageService()->GetCommands(SerialNumber, QB_.StartDate, QB_.EndDate, QB_.Offset, QB_.Limit,
Commands);
}
Poco::JSON::Array ArrayObj;
for (const auto &i : Commands) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(RESTAPI::Protocol::COMMANDS, ArrayObj);
ReturnObject(RetObj);
}
void RESTAPI_commands::DoDelete() {
auto SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, "");
if(SerialNumber.empty()) {
return BadRequest(RESTAPI::Errors::MissingSerialNumber);
}
if (StorageService()->DeleteCommands(SerialNumber, QB_.StartDate, QB_.EndDate)) {
return OK();
}
InternalError();
}
}

View File

@@ -1,76 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "Poco/JSON/Parser.h"
#include "RESTAPI_default_configuration.h"
#include "RESTObjects/RESTAPI_GWobjects.h"
#include "StorageService.h"
#include "framework/RESTAPI_errors.h"
#include "framework/RESTAPI_protocol.h"
namespace OpenWifi {
void RESTAPI_default_configuration::DoGet() {
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
GWObjects::DefaultConfiguration DefConfig;
if (StorageService()->GetDefaultConfiguration(Name, DefConfig)) {
Poco::JSON::Object Obj;
DefConfig.to_json(Obj);
return ReturnObject(Obj);
}
NotFound();
}
void RESTAPI_default_configuration::DoDelete() {
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
if(Name.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if (StorageService()->DeleteDefaultConfiguration(Name)) {
return OK();
}
BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
}
void RESTAPI_default_configuration::DoPost() {
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
if(Name.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
auto Obj = ParseStream();
GWObjects::DefaultConfiguration DefConfig;
if (!DefConfig.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if (StorageService()->CreateDefaultConfiguration(Name, DefConfig)) {
return OK();
}
BadRequest(RESTAPI::Errors::RecordNotCreated);
}
void RESTAPI_default_configuration::DoPut() {
std::string Name = GetBinding(RESTAPI::Protocol::NAME, "");
auto Obj = ParseStream();
GWObjects::DefaultConfiguration DefConfig;
if (!DefConfig.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if (StorageService()->UpdateDefaultConfiguration(Name, DefConfig)) {
return OK();
}
BadRequest(RESTAPI::Errors::RecordNotUpdated);
}
}

Some files were not shown because too many files have changed in this diff Show More