Compare commits

...

29 Commits

Author SHA1 Message Date
Adam Capparelli
38bc0f0d69 Fix wrong port in openapi.yaml
Signed-off-by: Adam Capparelli <adam.capparelli@alumni.utoronto.ca>
2024-09-25 11:08:11 -04:00
i-chvets
e7362c2020 Merge pull request #381 from Telecominfraproject/ols-246-feat-cable-diag
OLS-246: feat: add cable diagnostics command
2024-09-25 10:42:52 -04:00
Ivan Chvets
9c9987e190 feat: add cable diagnostics command
https://telecominfraproject.atlassian.net/browse/OLS-246

Summary of changes:
- Modified code to match spec, ie. command is `cable-diagnostics`.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-25 10:17:52 -04:00
i-chvets
4ac7b6ba0b Merge pull request #379 from Telecominfraproject/WIFI-14140-fix-update-schema-multi-psk
WIFI-14140: fix: sync-ed up ucentral schema with code - added missing code
2024-09-25 09:54:12 -04:00
Ivan Chvets
f9ee19af91 fix: sync-ed up ucentral schema with code - added missing code
https://telecominfraproject.atlassian.net/browse/WIFI-14140

Summary of changes:
- Synchronized built-in schema in configuration validation code with
ucentral schema. Added missing code.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-25 08:30:58 -04:00
i-chvets
cd2ab8660f Merge pull request #376 from Telecominfraproject/WIFI-14140-fix-update-schema-multi-psk
WIFI-14140 fix: sync-ed up ucentral schema with code
2024-09-24 10:05:56 -04:00
Ivan Chvets
b9f00f6603 fix: sync-ed up ucentral schema with code
https://telecominfraproject.atlassian.net/browse/WIFI-14140

Summary of changes:
- Synchronized built-in schema in configuration validation code with
  ucentral schema.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-19 10:26:51 -04:00
i-chvets
596cfd49e1 Merge pull request #375 from Telecominfraproject/ols-246-feat-cable-diag
OLS-246: feat: add cable diagnostics command
2024-09-18 11:45:14 -04:00
Ivan Chvets
b3deba5606 feat: add cable diagnostics command
https://telecominfraproject.atlassian.net/browse/OLS-246

Summary of changes:
- Added `cablediagnostics` command.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-18 11:04:57 -04:00
i-chvets
a97d49a06b Merge pull request #373 from Telecominfraproject/WIFI-13126-feat-fixed-config-doc-update
WIFI-13126: feat: fixedconfig doc update
2024-09-16 10:05:55 -04:00
Ivan Chvets
b1be0604d6 feat: fixedconfig doc update
https://telecominfraproject.atlassian.net/browse/WIFI-13126

Summary of changes:
- Updated documentation.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-13 11:30:40 -04:00
i-chvets
b29f7f7dc4 Merge pull request #372 from Telecominfraproject/WIFI-13126-feat-fixed-config
WIFI-13126: feat: add fixedconfig command
2024-09-11 16:59:16 -04:00
Ivan Chvets
132b31b06b feat: add fixedconfig command
https://telecominfraproject.atlassian.net/browse/WIFI-13126

Summary of changes:
- Added `fixedconfig` command.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-09-11 16:20:02 -04:00
i-chvets
3114ff8a32 Merge pull request #371 from Telecominfraproject/WIFI-14038-fix-exception-handling-for-zero-queue
WIFI-14038: fix: update code to improve exception handling
2024-09-10 13:45:48 -04:00
Ivan Chvets
9c5aeda5dd fix: update code to improve exception handling
https://telecominfraproject.atlassian.net/browse/WIFI-14038

Summary of changes:
- Modified code to cover zero sized queues under exception handling.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-08-29 17:57:05 -04:00
i-chvets
783ec99930 Merge pull request #370 from Telecominfraproject/WIFI-13875-fix-use-dns
WIFI-13875: fix: updated valijson version
2024-08-08 10:05:40 -04:00
Ivan Chvets
0c661b8b93 fix: updated valijson version
https://telecominfraproject.atlassian.net/browse/WIFI-13875

Summary of changes:
- Updated valijson version in Docker file to bring in fix for https://github.com/tristanpenman/valijson/issues/181

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-08-08 09:23:30 -04:00
i-chvets
9d7f4da504 Merge pull request #369 from Telecominfraproject/WIFI-14027-fix-ping-crash
fix: fix crash for non-configure commands
2024-08-01 19:03:54 -04:00
Ivan Chvets
a3b6e7c315 fix: fix crash for non-configure commands
https://telecominfraproject.atlassian.net/browse/WIFI-14027

Summary of changes:
- Modified code to relay errors only in case of configure command and
  strict mode.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-08-01 17:09:09 -04:00
i-chvets
451680cd5a Merge pull request #368 from Telecominfraproject/WIFI-14019-fix-report-errors-in-strict-only
WIFI-14019: fix: relay errors from ap nos configuration only when strict mode is enabled
2024-07-30 12:50:25 -04:00
Ivan Chvets
7be48c3cfc fix: relay errors from ap nos configuration only when strict mode is
enabled
https://telecominfraproject.atlassian.net/browse/WIFI-14019

Summary of changes:
- Modified code to only relay errors from AP NOS configuration update
  only when strict mode is enabled.

NOTE: AP NOS is capable of modifying config thus fixing invalid configs
(in some cases) and applying resulting configuration. Warning messages
are produced, but error code is being sent back as error/failed.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-07-30 12:21:19 -04:00
i-chvets
b59d1cb4da Merge pull request #366 from Telecominfraproject/WIFI-13985-fix-return-400-on-error
WIFI-13985: commands API will return 400 if command fails on device.
2024-07-26 13:26:27 -04:00
Adam Capparelli
c3a709c2b9 commands API will return 400 if command fails on device.
Signed-off-by: Adam Capparelli <adam.capparelli@mail.utoronto.ca>
2024-07-22 14:28:03 -04:00
i-chvets
5d89107827 Merge pull request #362 from Telecominfraproject/WIFI-13597-fix-kafka-producer-using-poll
WIFI-13857: fix: modified code to use flush() when internal queue is not loaded
2024-06-19 16:52:01 -04:00
Ivan Chvets
3c15c6dc4f fix: modified code to use flush() when internal queue is not loaded
https://telecominfraproject.atlassian.net/browse/WIFI-13597

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-06-19 16:29:24 -04:00
i-chvets
7b33a692b2 Merge pull request #361 from Telecominfraproject/WIFI-13597-fix-kafka-producer-using-poll
fix: added flush() for proper shutdown
2024-06-18 12:04:02 -04:00
Ivan Chvets
b118dcbcec fix: added flush() for proper shutdown
https://telecominfraproject.atlassian.net/browse/WIFI-13597

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-06-14 16:30:23 -04:00
Stephane Bourque
02a0eef44a Merge pull request #360 from Telecominfraproject/WIFI-13597-fix-kafka-producer-using-poll
WIFI-13597: fix: modified kafka manager to use poll in producer
2024-06-12 12:17:08 -07:00
Ivan Chvets
c7ed7fb264 fix: modified kafka manager to use poll in producer
https://telecominfraproject.atlassian.net/browse/WIFI-13597

Summary of changes:
- Modified code in KafkaManager to use poll instead of flush for every
  messages sent. flush is used only on empty internal notification queue
in idle times.

Signed-off-by: Ivan Chvets <ivan.chvets@kinarasystems.com>
2024-06-11 11:15:42 -04:00
12 changed files with 235 additions and 19 deletions

View File

@@ -1,7 +1,7 @@
ARG DEBIAN_VERSION=11.5-slim
ARG POCO_VERSION=poco-tip-v2
ARG CPPKAFKA_VERSION=tip-v1
ARG VALIJASON_VERSION=tip-v1
ARG VALIJASON_VERSION=tip-v1.0.2
ARG APP_NAME=owgw
ARG APP_HOME_DIR=/openwifi

View File

@@ -306,8 +306,40 @@ The device should answer:
},
"id" : <same number>
}
```
#### Controller wants the device to apply a given fixed configuration
Controller sends this command when it requires the device to apply fixed configuration, eg. country code. The device
should respond with message indicating failure or success.
```json
{ "jsonrpc" : "2.0",
"method" : "fixedconfig",
"params" : {
"serial" : <serial number>,
"when" : Optional - <UTC time when to apply this config, 0 means immediate, this is a suggestion>
"country" : "<country-code>"
},
}
```
The device should answer:
```json
{ "jsonrpc" : "2.0",
"result" : {
"serial": <serial number>,
"status": {
"error": 0 or an error number,
"text": <description of the error or success, eg. "Applied fixed config, rebooting">
},
"uuid": <UUID>
}
}
```
##### The Answer
The device can answer and tell the controller it has rejected certain parts of the config and potentially replaced them with
appropriate values. This could be used to allow a device to replace frequencies for the regions it is located in. The device

View File

@@ -12,7 +12,7 @@ info:
url: https://www.ucentral.info/support
servers:
- url: 'https://localhost:16001/api/v1'
- url: 'https://localhost:16002/api/v1'
security:
- bearerAuth: []

View File

@@ -25,9 +25,23 @@ namespace OpenWifi::RESTAPI_RPC {
if (StorageService()->AddCommand(Cmd.SerialNumber, Cmd, Status)) {
Poco::JSON::Object RetObj;
Cmd.to_json(RetObj);
if (Handler != nullptr)
return Handler->ReturnObject(RetObj);
return;
if (Handler == nullptr) {
// nothing to process/return
return;
}
Poco::Net::HTTPResponse::HTTPStatus cmd_status = Poco::Net::HTTPResponse::HTTP_OK;
if (Cmd.ErrorCode > 0) {
// command returned error
cmd_status = Poco::Net::HTTPResponse::HTTP_BAD_REQUEST;
if (Cmd.Command == uCentralProtocol::CONFIGURE) {
// special handling for configure command
if (!Handler->GetBoolParameter("strict", false)) {
// in non-strict mode return success for failed configure command
cmd_status = Poco::Net::HTTPResponse::HTTP_OK;
}
}
}
return Handler->ReturnObject(RetObj, cmd_status);
}
if (Handler != nullptr)
return Handler->ReturnStatus(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
@@ -167,6 +181,20 @@ namespace OpenWifi::RESTAPI_RPC {
Cmd.AttachType = "";
}
// If the command fails on the device we should show it as failed and not return 200 OK
// exception is configure command which only reported failed in strict validation mode
if (Cmd.ErrorCode &&
(Cmd.Command != uCentralProtocol::CONFIGURE ||
(Cmd.Command == uCentralProtocol::CONFIGURE && Handler->GetBoolParameter("strict", false))
))
{
Logger.information(fmt::format(
"Command failed with error on device: {} Reason: {}.",
Cmd.ErrorCode, Cmd.ErrorText));
return SetCommandStatus(Cmd, Request, Response, Handler,
Storage::CommandExecutionType::COMMAND_FAILED, Logger);
}
if (Cmd.ErrorCode == 0 && Cmd.Command == uCentralProtocol::CONFIGURE) {
// we need to post a kafka event for this.
if (Params.has(uCentralProtocol::CONFIG) && Params.isObject(uCentralProtocol::CONFIG)) {
@@ -175,6 +203,7 @@ namespace OpenWifi::RESTAPI_RPC {
DeviceConfigurationChangeKafkaEvent KEvent(
Utils::SerialNumberToInt(Cmd.SerialNumber), Utils::Now(),
Config);
}
}

View File

@@ -167,7 +167,10 @@ namespace OpenWifi {
{APCommands::Commands::certupdate, false, true, &RESTAPI_device_commandHandler::CertUpdate, 60000ms},
{APCommands::Commands::transfer, false, true, &RESTAPI_device_commandHandler::Transfer, 60000ms},
{APCommands::Commands::script, false, true, &RESTAPI_device_commandHandler::Script, 60000ms},
{APCommands::Commands::powercycle, false, true, &RESTAPI_device_commandHandler::PowerCycle, 60000ms}
{APCommands::Commands::powercycle, false, true, &RESTAPI_device_commandHandler::PowerCycle, 60000ms},
{APCommands::Commands::fixedconfig, false, true, &RESTAPI_device_commandHandler::FixedConfig, 120000ms},
{APCommands::Commands::cablediagnostics, false, true, &RESTAPI_device_commandHandler::CableDiagnostics, 120000ms},
};
void RESTAPI_device_commandHandler::DoPost() {
@@ -1548,4 +1551,82 @@ namespace OpenWifi {
Logger_);
}
// `fixedconfig` command is used set country propery on AP
// This handler uses `fixedconfig` command definitions
void RESTAPI_device_commandHandler::FixedConfig(
const std::string &CMD_UUID, uint64_t CMD_RPC, std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
poco_debug(Logger_, fmt::format("FIXEDCONFIG({},{}): TID={} user={} serial={}", CMD_UUID, CMD_RPC,
TransactionId_, Requester(), SerialNumber_));
// do not allow `fixedconfig` command for simulated devices
if(IsDeviceSimulated(SerialNumber_)) {
CallCanceled("FIXEDCONFIG", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
// setup and validate fixedconfig object
GWObjects::FixedConfig fixed_config;
if(!fixed_config.from_json(ParsedBody_)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
// setup command message
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = Requester();
Cmd.UUID = CMD_UUID;
Cmd.Command = uCentralProtocol::FIXEDCONFIG;
std::ostringstream os;
ParsedBody_->stringify(os);
Cmd.Details = os.str();
Cmd.RunAt = 0;
Cmd.ErrorCode = 0;
Cmd.WaitingForFile = 0;
// send fixedconfig command to device and return status
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::fixedconfig, false, Cmd,
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
Logger_);
}
void RESTAPI_device_commandHandler::CableDiagnostics(
const std::string &CMD_UUID, uint64_t CMD_RPC,
[[maybe_unused]] std::chrono::milliseconds timeout,
[[maybe_unused]] const GWObjects::DeviceRestrictions &Restrictions) {
if(UserInfo_.userinfo.userRole != SecurityObjects::ROOT &&
UserInfo_.userinfo.userRole != SecurityObjects::ADMIN) {
CallCanceled("CABLEDIAGNOSTICS", CMD_UUID, CMD_RPC, RESTAPI::Errors::ACCESS_DENIED);
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
poco_debug(Logger_, fmt::format("CABLEDIAGNOSTICS({},{}): TID={} user={} serial={}", CMD_UUID,
CMD_RPC, TransactionId_, Requester(), SerialNumber_));
if(IsDeviceSimulated(SerialNumber_)) {
CallCanceled("CABLEDIAGNOSTICS", CMD_UUID, CMD_RPC, RESTAPI::Errors::SimulatedDeviceNotSupported);
return BadRequest(RESTAPI::Errors::SimulatedDeviceNotSupported);
}
GWObjects::CableDiagnostics PR;
if(!PR.from_json(ParsedBody_)) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
GWObjects::CommandDetails Cmd;
Cmd.SerialNumber = SerialNumber_;
Cmd.SubmittedBy = Requester();
Cmd.UUID = CMD_UUID;
Cmd.Command = uCentralProtocol::CABLEDIAGNOSTICS;
std::ostringstream os;
ParsedBody_->stringify(os);
Cmd.Details = os.str();
Cmd.RunAt = PR.when;
Cmd.ErrorCode = 0;
Cmd.WaitingForFile = 0;
return RESTAPI_RPC::WaitForCommand(CMD_RPC, APCommands::Commands::cablediagnostics, false, Cmd,
*ParsedBody_, *Request, *Response, timeout, nullptr, this,
Logger_);
}
} // namespace OpenWifi

View File

@@ -70,6 +70,10 @@ namespace OpenWifi {
const GWObjects::DeviceRestrictions &R);
void PowerCycle(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
void FixedConfig(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
void CableDiagnostics(const std::string &UUID, uint64_t RPC, std::chrono::milliseconds timeout,
const GWObjects::DeviceRestrictions &R);
static auto PathName() {
return std::list<std::string>{"/api/v1/device/{serialNumber}/{command}"};

View File

@@ -799,4 +799,24 @@ namespace OpenWifi::GWObjects {
return false;
}
bool FixedConfig::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serial", serialNumber);
field_from_json(Obj, "country", country);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
bool CableDiagnostics::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "serial", serialNumber);
field_from_json(Obj, "when", when);
field_from_json(Obj, "ports", ports);
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
} // namespace OpenWifi::GWObjects

View File

@@ -532,6 +532,19 @@ namespace OpenWifi::GWObjects {
std::uint64_t when;
std::vector<PowerCyclePort> ports;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct FixedConfig {
std::string serialNumber;
std::string country;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct CableDiagnostics {
std::string serialNumber;
std::uint64_t when;
std::vector<std::string> ports;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
} // namespace OpenWifi::GWObjects

View File

@@ -2411,11 +2411,18 @@ static std::string DefaultAPSchema = R"foo(
"$ref": "#/$defs/interface.ssid.encryption"
},
"multi-psk": {
"type": "array",
"items": {
"$ref": "#/$defs/interface.ssid.multi-psk"
}
},
"anyOf": [
{
"type": "array",
"items": {
"$ref": "#/$defs/interface.ssid.multi-psk"
}
},
{
"type": "boolean"
}
]
},
"rrm": {
"$ref": "#/$defs/interface.ssid.rrm"
},
@@ -6603,10 +6610,17 @@ static std::string DefaultSWITCHSchema = R"foo(
"$ref": "#/$defs/interface.ssid.encryption"
},
"multi-psk": {
"type": "array",
"items": {
"$ref": "#/$defs/interface.ssid.multi-psk"
}
"anyOf": [
{
"type": "array",
"items": {
"$ref": "#/$defs/interface.ssid.multi-psk"
}
},
{
"type": "boolean"
}
]
},
"rrm": {
"$ref": "#/$defs/interface.ssid.rrm"

View File

@@ -107,6 +107,19 @@ namespace OpenWifi {
NewMessage.partition(0);
NewMessage.payload(Msg->Payload());
Producer.produce(NewMessage);
if (Queue_.size() < 100) {
// use flush when internal queue is lightly loaded, i.e. flush after each
// message
Producer.flush();
}
else {
// use poll when internal queue is loaded to allow messages to be sent in
// batches
Producer.poll((std::chrono::milliseconds) 0);
}
}
if (Queue_.size() == 0) {
// message queue is empty, flush all previously sent messages
Producer.flush();
}
} catch (const cppkafka::HandleException &E) {
@@ -119,6 +132,7 @@ namespace OpenWifi {
}
Note = Queue_.waitDequeueNotification();
}
Producer.flush();
poco_information(Logger_, "Stopped...");
}
@@ -324,4 +338,4 @@ namespace OpenWifi {
partitions.front().get_partition()));
}
} // namespace OpenWifi
} // namespace OpenWifi

View File

@@ -552,8 +552,8 @@ namespace OpenWifi {
inline bool IsAuthorized(bool &Expired, bool &Contacted, bool SubOnly = false);
inline void ReturnObject(Poco::JSON::Object &Object) {
PrepareResponse();
inline void ReturnObject(Poco::JSON::Object &Object, Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK) {
PrepareResponse(Status);
if (Request != nullptr) {
// can we compress ???
auto AcceptedEncoding = Request->find("Accept-Encoding");

View File

@@ -580,6 +580,9 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char *INTERVAL = "interval";
static const char *UI = "UI";
static const char *BANDWIDTH = "bandwidth";
static const char *FIXEDCONFIG = "fixedconfig";
static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
} // namespace OpenWifi::RESTAPI::Protocol
namespace OpenWifi::uCentralProtocol {
@@ -692,6 +695,9 @@ namespace OpenWifi::uCentralProtocol {
static const char *RRM = "rrm";
static const char *ACTIONS = "actions";
static const char *FIXEDCONFIG = "fixedconfig";
static const char *CABLEDIAGNOSTICS = "cable-diagnostics";
} // namespace OpenWifi::uCentralProtocol
namespace OpenWifi::uCentralProtocol::Events {
@@ -788,6 +794,8 @@ namespace OpenWifi::APCommands {
certupdate,
transfer,
powercycle,
fixedconfig,
cablediagnostics,
unknown
};
@@ -802,7 +810,8 @@ namespace OpenWifi::APCommands {
RESTAPI::Protocol::EVENTQUEUE, RESTAPI::Protocol::TELEMETRY,
RESTAPI::Protocol::PING, RESTAPI::Protocol::SCRIPT,
RESTAPI::Protocol::RRM, RESTAPI::Protocol::CERTUPDATE,
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE
RESTAPI::Protocol::TRANSFER, RESTAPI::Protocol::POWERCYCLE,
RESTAPI::Protocol::FIXEDCONFIG, RESTAPI::Protocol::CABLEDIAGNOSTICS
};
inline const char *to_string(Commands Cmd) { return uCentralAPCommands[(uint8_t)Cmd]; }