Added ability to reboot a venue.

This commit is contained in:
stephb9959
2022-05-04 14:05:22 -07:00
parent 35890f3be4
commit e0d45d50d6
9 changed files with 251 additions and 8 deletions

View File

@@ -134,7 +134,7 @@ add_executable(owprov
src/storage/storage_variables.cpp src/storage/storage_variables.h
src/RESTAPI/RESTAPI_variables_handler.cpp src/RESTAPI/RESTAPI_variables_handler.h
src/RESTAPI/RESTAPI_variables_list_handler.cpp src/RESTAPI/RESTAPI_variables_list_handler.h
src/FileDownloader.cpp src/FileDownloader.h src/Tasks/VenueConfigUpdater.cpp src/Tasks/VenueConfigUpdater.h src/Kafka_ProvUpdater.cpp src/Kafka_ProvUpdater.h src/storage/storage_operataor.cpp src/storage/storage_operataor.h src/storage/storage_sub_devices.cpp src/storage/storage_sub_devices.h src/storage/storage_service_class.cpp src/storage/storage_service_class.h src/RESTAPI/RESTAPI_sub_devices_list_handler.cpp src/RESTAPI/RESTAPI_sub_devices_list_handler.h src/RESTAPI/RESTAPI_sub_devices_handler.cpp src/RESTAPI/RESTAPI_sub_devices_handler.h src/RESTAPI/RESTAPI_service_class_list_handler.cpp src/RESTAPI/RESTAPI_service_class_list_handler.h src/RESTAPI/RESTAPI_service_class_handler.cpp src/RESTAPI/RESTAPI_service_class_handler.h src/RESTAPI/RESTAPI_operators_list_handler.cpp src/RESTAPI/RESTAPI_operators_list_handler.h src/RESTAPI/RESTAPI_operators_handler.cpp src/RESTAPI/RESTAPI_operators_handler.h src/storage/storage_op_contacts.cpp src/storage/storage_op_contacts.h src/storage/storage_op_locations.cpp src/storage/storage_op_locations.h src/RESTAPI/RESTAPI_op_contact_list_handler.cpp src/RESTAPI/RESTAPI_op_contact_list_handler.h src/RESTAPI/RESTAPI_op_contact_handler.cpp src/RESTAPI/RESTAPI_op_contact_handler.h src/RESTAPI/RESTAPI_op_location_list_handler.cpp src/RESTAPI/RESTAPI_op_location_list_handler.h src/RESTAPI/RESTAPI_op_location_handler.cpp src/RESTAPI/RESTAPI_op_location_handler.h src/ProvWebSocketClient.cpp src/ProvWebSocketClient.h)
src/FileDownloader.cpp src/FileDownloader.h src/Tasks/VenueConfigUpdater.h src/Kafka_ProvUpdater.cpp src/Kafka_ProvUpdater.h src/storage/storage_operataor.cpp src/storage/storage_operataor.h src/storage/storage_sub_devices.cpp src/storage/storage_sub_devices.h src/storage/storage_service_class.cpp src/storage/storage_service_class.h src/RESTAPI/RESTAPI_sub_devices_list_handler.cpp src/RESTAPI/RESTAPI_sub_devices_list_handler.h src/RESTAPI/RESTAPI_sub_devices_handler.cpp src/RESTAPI/RESTAPI_sub_devices_handler.h src/RESTAPI/RESTAPI_service_class_list_handler.cpp src/RESTAPI/RESTAPI_service_class_list_handler.h src/RESTAPI/RESTAPI_service_class_handler.cpp src/RESTAPI/RESTAPI_service_class_handler.h src/RESTAPI/RESTAPI_operators_list_handler.cpp src/RESTAPI/RESTAPI_operators_list_handler.h src/RESTAPI/RESTAPI_operators_handler.cpp src/RESTAPI/RESTAPI_operators_handler.h src/storage/storage_op_contacts.cpp src/storage/storage_op_contacts.h src/storage/storage_op_locations.cpp src/storage/storage_op_locations.h src/RESTAPI/RESTAPI_op_contact_list_handler.cpp src/RESTAPI/RESTAPI_op_contact_list_handler.h src/RESTAPI/RESTAPI_op_contact_handler.cpp src/RESTAPI/RESTAPI_op_contact_handler.h src/RESTAPI/RESTAPI_op_location_list_handler.cpp src/RESTAPI/RESTAPI_op_location_list_handler.h src/RESTAPI/RESTAPI_op_location_handler.cpp src/RESTAPI/RESTAPI_op_location_handler.h src/ProvWebSocketClient.cpp src/ProvWebSocketClient.h src/Tasks/VenueRebooter.h)
target_link_libraries(owprov PUBLIC
${Poco_LIBRARIES}

2
build
View File

@@ -1 +1 @@
108
113

View File

@@ -2443,6 +2443,12 @@ paths:
type: boolean
default: false
required: false
- in: query
name: rebootAllDevices
schema:
type: boolean
default: false
required: false
- in: query
name: testUpdateOnly
schema:

View File

@@ -13,6 +13,7 @@
#include "StorageService.h"
#include "RESTAPI/RESTAPI_db_helpers.h"
#include "Tasks/VenueConfigUpdater.h"
#include "Tasks/VenueRebooter.h"
#include "Kafka_ProvUpdater.h"
@@ -231,6 +232,21 @@ namespace OpenWifi{
return ReturnObject(Answer);
}
auto rebootAllDevices = GetBoolParameter("rebootAllDevices");
if(rebootAllDevices) {
ProvObjects::SerialNumberList SNL;
Poco::JSON::Object Answer;
SNL.serialNumbers = Existing.devices;
auto Task = new VenueRebooter(UUID,UserInfo_.userinfo,0,Logger());
auto JobId = Task->Start();
SNL.to_json(Answer);
Answer.set("jobId",JobId);
return ReturnObject(Answer);
}
auto RawObject = ParseStream();
ProvObjects::Venue NewObject;
if (!NewObject.from_json(RawObject)) {

View File

@@ -1,5 +0,0 @@
//
// Created by stephane bourque on 2022-04-01.
//
#include "VenueConfigUpdater.h"

View File

@@ -243,7 +243,7 @@ namespace OpenWifi {
}
auto Sent = WebSocketClientServer()->SendUserNotification(UI_.email,N);
Logger().information(fmt::format("Job {} Completed: {} updated, {} failed to update , {} bad configurations. Notification was send={}",
Logger().information(fmt::format("Job {} Completed: {} updated, {} failed to update , {} bad configurations. Notification was sent={}",
JobId_, Updated ,Failed, BadConfigs, Sent));
delete this;
}

212
src/Tasks/VenueRebooter.h Normal file
View File

@@ -0,0 +1,212 @@
//
// Created by stephane bourque on 2022-05-04.
//
#include "framework/MicroService.h"
#include "StorageService.h"
#include "APConfig.h"
#include "sdks/SDK_gw.h"
namespace OpenWifi {
struct WebSocketNotificationRebootList {
std::string title,
details,
jobId;
std::vector<std::string> success,
warning;
uint64_t timeStamp=OpenWifi::Now();
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
inline void WebSocketNotificationRebootList::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"title",title);
RESTAPI_utils::field_to_json(Obj,"jobId",jobId);
RESTAPI_utils::field_to_json(Obj,"success",success);
RESTAPI_utils::field_to_json(Obj,"warning",warning);
RESTAPI_utils::field_to_json(Obj,"timeStamp",timeStamp);
RESTAPI_utils::field_to_json(Obj,"details",details);
}
inline bool WebSocketNotificationRebootList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
RESTAPI_utils::field_from_json(Obj,"title",title);
RESTAPI_utils::field_from_json(Obj,"jobId",jobId);
RESTAPI_utils::field_from_json(Obj,"success",success);
RESTAPI_utils::field_from_json(Obj,"warning",warning);
RESTAPI_utils::field_from_json(Obj,"timeStamp",timeStamp);
RESTAPI_utils::field_from_json(Obj,"details",details);
return true;
} catch(...) {
}
return false;
}
class VenueDeviceRebooter : public Poco::Runnable {
public:
VenueDeviceRebooter(const std::string &UUID, const std::string &venue, Poco::Logger &L) :
uuid_(UUID),
venue_(venue),
Logger_(L) {
}
void run() final {
ProvObjects::InventoryTag Device;
started_=true;
if(StorageService()->InventoryDB().GetRecord("id",uuid_,Device)) {
SerialNumber = Device.serialNumber;
if (SDK::GW::Device::Reboot(Device.serialNumber, 0)) {
Logger().debug(fmt::format("{}: Rebooted.",Device.serialNumber));
rebooted_++;
} else {
Logger().information(fmt::format("{}: Not rebooted.", Device.serialNumber));
failed_++;
}
}
done_ = true;
// std::cout << "Done push for " << Device.serialNumber << std::endl;
}
uint64_t rebooted_=0, failed_=0;
bool started_ = false,
done_ = false;
std::string SerialNumber;
private:
std::string uuid_;
std::string venue_;
Poco::Logger &Logger_;
inline Poco::Logger & Logger() { return Logger_; }
};
class VenueRebooter: public Poco::Runnable {
public:
explicit VenueRebooter(const std::string & VenueUUID, const SecurityObjects::UserInfo &UI, uint64_t When, Poco::Logger &L) :
VenueUUID_(VenueUUID),
UI_(UI),
When_(When),
Logger_(L)
{
}
inline std::string Start() {
JobId_ = MicroService::CreateUUID();
Worker_.start(*this);
return JobId_;
}
private:
std::string VenueUUID_;
SecurityObjects::UserInfo UI_;
uint64_t When_;
Poco::Logger &Logger_;
Poco::Thread Worker_;
std::string JobId_;
Poco::ThreadPool Pool_{2,16,300};
inline Poco::Logger & Logger() { return Logger_; }
inline void run() final {
if(When_ && When_>OpenWifi::Now())
Poco::Thread::trySleep( (long) (When_ - OpenWifi::Now()) * 1000 );
WebSocketNotification<WebSocketNotificationRebootList> N;
N.type = "venue_rebooter";
Logger().information(fmt::format("Job {} Starting.", JobId_));
ProvObjects::Venue Venue;
uint64_t rebooted_ = 0, failed_ = 0;
if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) {
const std::size_t MaxThreads=16;
struct tState {
Poco::Thread thr_;
VenueDeviceRebooter *task= nullptr;
};
N.content.title = fmt::format("Rebooting {} devices.", Venue.info.name);
N.content.jobId = JobId_;
std::array<tState,MaxThreads> Tasks;
for(const auto &uuid:Venue.devices) {
auto NewTask = new VenueDeviceRebooter(uuid, Venue.info.name, Logger());
// std::cout << "Scheduling config push for " << uuid << std::endl;
bool found_slot = false;
while (!found_slot) {
for (auto &cur_task: Tasks) {
if (cur_task.task == nullptr) {
cur_task.task = NewTask;
cur_task.thr_.start(*NewTask);
found_slot = true;
break;
}
}
// Let's look for a slot...
if (!found_slot) {
for (auto &cur_task: Tasks) {
if (cur_task.task != nullptr && cur_task.task->started_) {
if (cur_task.thr_.isRunning())
continue;
if (!cur_task.thr_.isRunning() && cur_task.task->done_) {
cur_task.thr_.join();
rebooted_ += cur_task.task->rebooted_;
failed_ += cur_task.task->failed_;
cur_task.task->started_ = cur_task.task->done_ = false;
delete cur_task.task;
cur_task.task = nullptr;
}
}
}
}
}
}
Logger().debug("Waiting for outstanding update threads to finish.");
bool stillTasksRunning=true;
while(stillTasksRunning) {
stillTasksRunning = false;
for(auto &cur_task:Tasks) {
if(cur_task.task!= nullptr && cur_task.task->started_) {
if(cur_task.thr_.isRunning()) {
stillTasksRunning = true;
continue;
}
if(!cur_task.thr_.isRunning() && cur_task.task->done_) {
cur_task.thr_.join();
if(cur_task.task->rebooted_) {
rebooted_++;
N.content.success.push_back(cur_task.task->SerialNumber);
} else if(cur_task.task->failed_) {
failed_++;
N.content.warning.push_back(cur_task.task->SerialNumber);
}
cur_task.task->started_ = cur_task.task->done_ = false;
delete cur_task.task;
cur_task.task = nullptr;
}
}
}
}
N.content.details = fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.",
JobId_, rebooted_ ,failed_);
} else {
N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_);
Logger().warning(N.content.details);
}
auto Sent = WebSocketClientServer()->SendUserNotification(UI_.email,N);
Logger().information(fmt::format("Job {} Completed: {} rebooted, {} failed to reboot. Notification was sent={}",
JobId_, rebooted_ ,failed_, Sent));
delete this;
}
};
}

View File

@@ -17,6 +17,19 @@ namespace OpenWifi::SDK::GW {
PerformCommand(client,"reboot",EndPoint, ObjRequest);
}
bool Reboot(const std::string & Mac, [[maybe_unused]] uint64_t When) {
std::string EndPoint = "/api/v1/device/" + Mac + "/reboot";
Poco::JSON::Object ObjRequest;
ObjRequest.set("serialNumber", Mac);
ObjRequest.set("when", When );
OpenAPIRequestPost RebootCommand( uSERVICE_GATEWAY, EndPoint, {}, ObjRequest, 30000);
Poco::JSON::Object::Ptr Response;
return RebootCommand.Do(Response) == Poco::Net::HTTPResponse::HTTP_OK;
}
void LEDs(RESTAPIHandler *client, const std::string & Mac, uint64_t When, uint64_t Duration, const std::string & Pattern) {
std::string EndPoint = "/api/v1/device/" + Mac + "/leds";
Poco::JSON::Object ObjRequest;

View File

@@ -9,6 +9,7 @@
namespace OpenWifi::SDK::GW {
namespace Device {
void Reboot(RESTAPIHandler *client, const std::string & Mac, uint64_t When);
bool Reboot(const std::string & Mac, [[maybe_unused]] uint64_t When);
void LEDs(RESTAPIHandler *client, const std::string & Mac, uint64_t When, uint64_t Duration, const std::string & Pattern);
void Factory(RESTAPIHandler *client, const std::string & Mac, uint64_t When, bool KeepRedirector);
void Upgrade(RESTAPIHandler *client, const std::string & Mac, uint64_t When, const std::string & ImageName, bool KeepRedirector);