mirror of
				https://github.com/Telecominfraproject/wlan-cloud-owprov.git
				synced 2025-10-30 18:18:03 +00:00 
			
		
		
		
	Compare commits
	
		
			37 Commits
		
	
	
		
			v2.6.0-RC3
			...
			release/v2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 7fcf2ca41b | ||
|   | 3c2017859b | ||
|   | eecf9a49c2 | ||
|   | 5945d02b3d | ||
|   | 0ac192cdc0 | ||
|   | 1b5eb87eef | ||
|   | 46db18d7cd | ||
|   | 30b8665d7d | ||
|   | c8b3a3b060 | ||
|   | 944500dea9 | ||
|   | a5e0dcb210 | ||
|   | 096da35ff4 | ||
|   | bd7f3af11c | ||
|   | 2a06021c4a | ||
|   | bf18bb25ba | ||
|   | 656562c691 | ||
|   | e93f899b76 | ||
|   | eda73038f6 | ||
|   | 953ca155a4 | ||
|   | 898806f232 | ||
|   | 7d97b19b85 | ||
|   | d6c587fde6 | ||
|   | 58c9a7805b | ||
|   | 94dd4c84e9 | ||
|   | 2636715f6f | ||
|   | f9f4624add | ||
|   | cf441de197 | ||
|   | 2ea7e3dcc5 | ||
|   | 158455a528 | ||
|   | 4d2ccec1a8 | ||
|   | 7dad5a9bdb | ||
|   | cd2ac84c5b | ||
|   | 205343619b | ||
|   | 9735f709e9 | ||
|   | ae5fd31818 | ||
|   | aa1136e55b | ||
|   | 2b46ad4a66 | 
| @@ -125,7 +125,6 @@ add_executable(owprov | |||||||
|         src/RESTAPI/RESTAPI_db_helpers.h |         src/RESTAPI/RESTAPI_db_helpers.h | ||||||
|         src/JobController.cpp src/JobController.h |         src/JobController.cpp src/JobController.h | ||||||
|         src/JobRegistrations.cpp |         src/JobRegistrations.cpp | ||||||
|         src/storage/storage_jobs.cpp src/storage/storage_jobs.h |  | ||||||
|         src/storage/storage_maps.cpp src/storage/storage_maps.h |         src/storage/storage_maps.cpp src/storage/storage_maps.h | ||||||
|         src/RESTAPI/RESTAPI_map_handler.cpp src/RESTAPI/RESTAPI_map_handler.h |         src/RESTAPI/RESTAPI_map_handler.cpp src/RESTAPI/RESTAPI_map_handler.h | ||||||
|         src/RESTAPI/RESTAPI_map_list_handler.cpp src/RESTAPI/RESTAPI_map_list_handler.h |         src/RESTAPI/RESTAPI_map_list_handler.cpp src/RESTAPI/RESTAPI_map_list_handler.h | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ if [ "$SELFSIGNED_CERTS" = 'true' ]; then | |||||||
|     update-ca-certificates |     update-ca-certificates | ||||||
| fi | fi | ||||||
|  |  | ||||||
| if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWPROV_CONFIG"/owprov.properties ]]; then | if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then | ||||||
|   RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWPROV_ROOT/certs/restapi-ca.pem"} \ |   RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWPROV_ROOT/certs/restapi-ca.pem"} \ | ||||||
|   RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16005"} \ |   RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16005"} \ | ||||||
|   RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWPROV_ROOT/certs/restapi-cert.pem"} \ |   RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWPROV_ROOT/certs/restapi-cert.pem"} \ | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ fullnameOverride: "" | |||||||
| images: | images: | ||||||
|   owprov: |   owprov: | ||||||
|     repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owprov |     repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owprov | ||||||
|     tag: v2.6.0-RC3 |     tag: v2.6.0 | ||||||
|     pullPolicy: Always |     pullPolicy: Always | ||||||
| #    regcred: | #    regcred: | ||||||
| #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io | #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io | ||||||
|   | |||||||
| @@ -27,71 +27,13 @@ components: | |||||||
|  |  | ||||||
|   responses: |   responses: | ||||||
|     NotFound: |     NotFound: | ||||||
|       description: The specified resource was not found. |       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/NotFound' | ||||||
|       content: |  | ||||||
|         application/json: |  | ||||||
|           schema: |  | ||||||
|             properties: |  | ||||||
|               ErrorCode: |  | ||||||
|                 type: integer |  | ||||||
|               ErrorDetails: |  | ||||||
|                 type: string |  | ||||||
|               ErrorDescription: |  | ||||||
|                 type: string |  | ||||||
|  |  | ||||||
|     Unauthorized: |     Unauthorized: | ||||||
|       description: The requested does not have sufficient rights to perform the operation. |       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Unauthorized' | ||||||
|       content: |  | ||||||
|         application/json: |  | ||||||
|           schema: |  | ||||||
|             properties: |  | ||||||
|               ErrorCode: |  | ||||||
|                 type: integer |  | ||||||
|                 enum: |  | ||||||
|                   - 0     # Success |  | ||||||
|                   - 1     # PASSWORD_CHANGE_REQUIRED, |  | ||||||
|                   - 2     # INVALID_CREDENTIALS, |  | ||||||
|                   - 3     # PASSWORD_ALREADY_USED, |  | ||||||
|                   - 4     # USERNAME_PENDING_VERIFICATION, |  | ||||||
|                   - 5     # PASSWORD_INVALID, |  | ||||||
|                   - 6     # INTERNAL_ERROR, |  | ||||||
|                   - 7     # ACCESS_DENIED, |  | ||||||
|                   - 8     # INVALID_TOKEN |  | ||||||
|                   - 9     # EXPIRED_TOKEN |  | ||||||
|                   - 10    # RATE_LIMIT_EXCEEDED |  | ||||||
|                   - 11    # BAD_MFA_TRANSACTION |  | ||||||
|                   - 12    # MFA_FAILURE |  | ||||||
|                   - 13    # SECURITY_SERVICE_UNREACHABLE |  | ||||||
|               ErrorDetails: |  | ||||||
|                 type: string |  | ||||||
|               ErrorDescription: |  | ||||||
|                 type: string |  | ||||||
|  |  | ||||||
|     Success: |     Success: | ||||||
|       description: The requested operation was performed. |       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Success' | ||||||
|       content: |  | ||||||
|         application/json: |  | ||||||
|           schema: |  | ||||||
|             properties: |  | ||||||
|               Operation: |  | ||||||
|                 type: string |  | ||||||
|               Details: |  | ||||||
|                 type: string |  | ||||||
|               Code: |  | ||||||
|                 type: integer |  | ||||||
|  |  | ||||||
|     BadRequest: |     BadRequest: | ||||||
|       description: The requested operation failed. |       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/BadRequest' | ||||||
|       content: |  | ||||||
|         application/json: |  | ||||||
|           schema: |  | ||||||
|             properties: |  | ||||||
|               ErrorCode: |  | ||||||
|                 type: integer |  | ||||||
|               ErrorDetails: |  | ||||||
|                 type: string |  | ||||||
|               ErrorDescription: |  | ||||||
|                 type: integer |  | ||||||
|  |  | ||||||
|   schemas: |   schemas: | ||||||
|  |  | ||||||
|   | |||||||
| @@ -153,60 +153,62 @@ namespace OpenWifi { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::set<std::string>   Sections; |         try { | ||||||
|         for(const auto &i:Config_) { |             std::set<std::string> Sections; | ||||||
|             Poco::JSON::Parser  P; |             for (const auto &i: Config_) { | ||||||
|             auto O = P.parse(i.element.configuration).extract<Poco::JSON::Object::Ptr>(); |                 Poco::JSON::Parser P; | ||||||
|             auto Names = O->getNames(); |                 auto O = P.parse(i.element.configuration).extract<Poco::JSON::Object::Ptr>(); | ||||||
|             for(const auto &SectionName:Names) { |                 auto Names = O->getNames(); | ||||||
|                 auto InsertInfo = Sections.insert(SectionName); |                 for (const auto &SectionName: Names) { | ||||||
|                 if (InsertInfo.second) { |                     auto InsertInfo = Sections.insert(SectionName); | ||||||
|                     if (O->isArray(SectionName)) { |                     if (InsertInfo.second) { | ||||||
|                         auto OriginalArray = O->getArray(SectionName); |                         if (O->isArray(SectionName)) { | ||||||
|                         if (Explain_) { |                             auto OriginalArray = O->getArray(SectionName); | ||||||
|                             Poco::JSON::Object ExObj; |                             if (Explain_) { | ||||||
|                             ExObj.set("from-uuid", i.info.id); |                                 Poco::JSON::Object ExObj; | ||||||
|                             ExObj.set("from-name", i.info.name); |                                 ExObj.set("from-uuid", i.info.id); | ||||||
|                             ExObj.set("action", "added"); |                                 ExObj.set("from-name", i.info.name); | ||||||
|                             ExObj.set("element", OriginalArray); |                                 ExObj.set("action", "added"); | ||||||
|                             Explanation_.add(ExObj); |                                 ExObj.set("element", OriginalArray); | ||||||
|  |                                 Explanation_.add(ExObj); | ||||||
|  |                             } | ||||||
|  |                             auto ExpandedArray = Poco::makeShared<Poco::JSON::Array>(); | ||||||
|  |                             ReplaceVariablesInArray(OriginalArray, ExpandedArray); | ||||||
|  |                             Configuration->set(SectionName, ExpandedArray); | ||||||
|  |                         } else if (O->isObject(SectionName)) { | ||||||
|  |                             auto OriginalSection = O->get(SectionName).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                             if (Explain_) { | ||||||
|  |                                 Poco::JSON::Object ExObj; | ||||||
|  |                                 ExObj.set("from-uuid", i.info.id); | ||||||
|  |                                 ExObj.set("from-name", i.info.name); | ||||||
|  |                                 ExObj.set("action", "added"); | ||||||
|  |                                 ExObj.set("element", OriginalSection); | ||||||
|  |                                 Explanation_.add(ExObj); | ||||||
|  |                             } | ||||||
|  |                             auto ExpandedSection = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|  |                             ReplaceVariablesInObject(OriginalSection, ExpandedSection); | ||||||
|  |                             Configuration->set(SectionName, ExpandedSection); | ||||||
|  |                         } else { | ||||||
|  |                             std::cout << " --- unknown element type --- " << O->get(SectionName).toString() | ||||||
|  |                                       << std::endl; | ||||||
|                         } |                         } | ||||||
|                         auto ExpandedArray = Poco::makeShared<Poco::JSON::Array>(); |  | ||||||
|                         ReplaceVariablesInArray(OriginalArray, ExpandedArray); |  | ||||||
|                         Configuration->set(SectionName, ExpandedArray); |  | ||||||
|                     } else if (O->isObject(SectionName)) { |  | ||||||
|                         auto OriginalSection = O->get(SectionName).extract<Poco::JSON::Object::Ptr>(); |  | ||||||
|                         if (Explain_) { |  | ||||||
|                             Poco::JSON::Object ExObj; |  | ||||||
|                             ExObj.set("from-uuid", i.info.id); |  | ||||||
|                             ExObj.set("from-name", i.info.name); |  | ||||||
|                             ExObj.set("action", "added"); |  | ||||||
|                             ExObj.set("element", OriginalSection); |  | ||||||
|                             Explanation_.add(ExObj); |  | ||||||
|                         } |  | ||||||
|                         auto ExpandedSection = Poco::makeShared<Poco::JSON::Object>(); |  | ||||||
|                         ReplaceVariablesInObject(OriginalSection, ExpandedSection); |  | ||||||
|                         Configuration->set(SectionName, ExpandedSection); |  | ||||||
|                     } else { |                     } else { | ||||||
|                         std::cout << " --- unknown element type --- " << O->get(SectionName).toString() << std::endl; |                         if (Explain_) { | ||||||
|                     } |                             Poco::JSON::Object ExObj; | ||||||
|                 } else { |                             ExObj.set("from-uuid", i.info.id); | ||||||
|                     if (Explain_) { |                             ExObj.set("from-name", i.info.name); | ||||||
|                         Poco::JSON::Object ExObj; |                             ExObj.set("action", "ignored"); | ||||||
|                         ExObj.set("from-uuid", i.info.id); |                             ExObj.set("reason", "weight insufficient"); | ||||||
|                         ExObj.set("from-name", i.info.name); |                             ExObj.set("element", O->get(SectionName)); | ||||||
|                         ExObj.set("action", "ignored"); |                             Explanation_.add(ExObj); | ||||||
|                         ExObj.set("reason", "weight insufficient"); |                         } | ||||||
|                         ExObj.set("element", O->get(SectionName)); |  | ||||||
|                         Explanation_.add(ExObj); |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } catch (...) { | ||||||
|         if(Config_.empty()) |  | ||||||
|             return false; |  | ||||||
|  |  | ||||||
|         return true; |         } | ||||||
|  |         return !Config_.empty(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static bool DeviceTypeMatch(const std::string &DeviceType, const Types::StringVec & Types) { |     static bool DeviceTypeMatch(const std::string &DeviceType, const Types::StringVec & Types) { | ||||||
|   | |||||||
| @@ -26,6 +26,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     void AutoDiscovery::run() { |     void AutoDiscovery::run() { | ||||||
|         Poco::AutoPtr<Poco::Notification>	Note(Queue_.waitDequeueNotification()); |         Poco::AutoPtr<Poco::Notification>	Note(Queue_.waitDequeueNotification()); | ||||||
|  |         Utils::SetThreadName("auto-discovery"); | ||||||
|         while(Note && Running_) { |         while(Note && Running_) { | ||||||
|             auto Msg = dynamic_cast<DiscoveryMessage *>(Note.get()); |             auto Msg = dynamic_cast<DiscoveryMessage *>(Note.get()); | ||||||
|             if(Msg!= nullptr) { |             if(Msg!= nullptr) { | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ namespace OpenWifi { | |||||||
|             void Stop() override; |             void Stop() override; | ||||||
|             void ConnectionReceived( const std::string & Key, const std::string & Payload) { |             void ConnectionReceived( const std::string & Key, const std::string & Payload) { | ||||||
|                 std::lock_guard G(Mutex_); |                 std::lock_guard G(Mutex_); | ||||||
|                 Logger().information(Poco::format("Device(%s): Connection/Ping message.", Key)); |                 poco_debug(Logger(),Poco::format("Device(%s): Connection/Ping message.", Key)); | ||||||
|                 Queue_.enqueueNotification( new DiscoveryMessage(Key,Payload)); |                 Queue_.enqueueNotification( new DiscoveryMessage(Key,Payload)); | ||||||
|             } |             } | ||||||
|             void run() override; |             void run() override; | ||||||
|   | |||||||
| @@ -26,6 +26,8 @@ namespace OpenWifi { | |||||||
|                 {"https://ucentral.io/ucentral.schema.pretty.json", "ucentral.schema.pretty.json" } |                 {"https://ucentral.io/ucentral.schema.pretty.json", "ucentral.schema.pretty.json" } | ||||||
|             }; |             }; | ||||||
|  |  | ||||||
|  |         Utils::SetThreadName("file-dmnldr"); | ||||||
|  |  | ||||||
|         for(const auto &[url,filename]:Files) { |         for(const auto &[url,filename]:Files) { | ||||||
|             try { |             try { | ||||||
|                 std::string FileContent; |                 std::string FileContent; | ||||||
|   | |||||||
| @@ -27,11 +27,32 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     void JobController::run() { |     void JobController::run() { | ||||||
|         Running_ = true ; |         Running_ = true ; | ||||||
|  |         Utils::SetThreadName("job-controller"); | ||||||
|         while(Running_) { |         while(Running_) { | ||||||
|             Poco::Thread::trySleep(2000); |             Poco::Thread::trySleep(2000); | ||||||
|  |  | ||||||
|  |             std::lock_guard G(Mutex_); | ||||||
|  |  | ||||||
|  |             for(auto ¤t_job:jobs_) { | ||||||
|  |                 if(current_job!=nullptr) { | ||||||
|  |                     if(current_job->Started()==0 && Pool_.used()<Pool_.available()) { | ||||||
|  |                         current_job->Logger().information(fmt::format("Starting {}: {}",current_job->JobId(),current_job->Name())); | ||||||
|  |                         current_job->Start(); | ||||||
|  |                         Pool_.start(*current_job); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             for(auto it = jobs_.begin(); it!=jobs_.end();) {\ | ||||||
|  |                 auto current_job = *it; | ||||||
|  |                 if(current_job!=nullptr && current_job->Completed()!=0) { | ||||||
|  |                     current_job->Logger().information(fmt::format("Completed {}: {}",current_job->JobId(),current_job->Name())); | ||||||
|  |                     it = jobs_.erase(it); | ||||||
|  |                     delete current_job; | ||||||
|  |                 } else { | ||||||
|  |                     ++it; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -7,99 +7,45 @@ | |||||||
| #include <vector> | #include <vector> | ||||||
| #include <utility> | #include <utility> | ||||||
| #include <functional> | #include <functional> | ||||||
|  | #include <list> | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
|     class Job { |     class Job : public Poco::Runnable { | ||||||
|         public: |     public: | ||||||
|             struct Parameter { |         Job(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) : | ||||||
|                 std::string name; |             jobId_(JobID), | ||||||
|                 std::string value; |             name_(name), | ||||||
|                 inline void to_json(Poco::JSON::Object &Obj) const { |             parameters_(parameters), | ||||||
|                     RESTAPI_utils::field_to_json(Obj,"name",name); |             when_(when), | ||||||
|                     RESTAPI_utils::field_to_json(Obj,"value",value); |             userinfo_(UI), | ||||||
|                 } |             Logger_(L) | ||||||
|  |         {}; | ||||||
|  |  | ||||||
|                 inline bool from_json(const Poco::JSON::Object::Ptr &Obj) { |         virtual void run() = 0; | ||||||
|                     try { |         [[nodiscard]] std::string Name() const { return name_; } | ||||||
|                         RESTAPI_utils::field_from_json(Obj,"name",name); |         const SecurityObjects::UserInfo & UserInfo() const { return userinfo_; } | ||||||
|                         RESTAPI_utils::field_from_json(Obj,"value",value); |         Poco::Logger & Logger() { return Logger_; } | ||||||
|                         return true; |         const std::string & JobId() const { return jobId_; } | ||||||
|                     } catch (...) { |         const std::string & Parameter(int x) const { return parameters_[x];} | ||||||
|  |         uint64_t When() const { return when_; } | ||||||
|  |         void Start() { started_ = OpenWifi::Now(); } | ||||||
|  |         uint64_t Started() const { return started_; } | ||||||
|  |         uint64_t Completed() const { return completed_;} | ||||||
|  |         void Complete() { completed_ = OpenWifi::Now(); } | ||||||
|  |  | ||||||
|                     } |     private: | ||||||
|                     return false; |         std::string                 jobId_; | ||||||
|                 } |         std::string                 name_; | ||||||
|             }; |         std::vector<std::string>    parameters_; | ||||||
|  |         uint64_t                    when_=0; | ||||||
|             struct Status { |         SecurityObjects::UserInfo   userinfo_; | ||||||
|                 Types::UUID_t   UUID; |         Poco::Logger                & Logger_; | ||||||
|                 uint64_t        Start = 0 ; |         uint64_t                    started_=0; | ||||||
|                 uint64_t        Progress = 0 ; |         uint64_t                    completed_=0; | ||||||
|                 uint64_t        Completed = 0 ; |  | ||||||
|                 std::string     CurrentDisplay; |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             struct Result { |  | ||||||
|                 int         Error=0; |  | ||||||
|                 std::string Reason; |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             typedef std::vector<Parameter>       Parameters; |  | ||||||
|             typedef std::vector<Parameters>      ParametersVec; |  | ||||||
|             typedef std::function<bool(const Parameters &Parameters, Result &Result, bool &Retry)>  WorkerFunction; |  | ||||||
|             typedef std::vector<Status>          Statuses; |  | ||||||
|  |  | ||||||
|             Job(std::string Title, |  | ||||||
|                          std::string Description, |  | ||||||
|                          std::string RegisteredName, |  | ||||||
|                          ParametersVec Parameters, |  | ||||||
|                          [[maybe_unused]] bool Parallel=true) : |  | ||||||
|                     Title_(std::move(Title)), |  | ||||||
|                     Description_(std::move(Description)), |  | ||||||
|                     RegisteredName_(std::move(RegisteredName)), |  | ||||||
|                     Parameters_(std::move(Parameters)) |  | ||||||
|                 { |  | ||||||
|                     UUID_ = MicroService::instance().CreateUUID(); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|             [[nodiscard]] inline const Types::UUID_t & ID() const { return UUID_; } |  | ||||||
|  |  | ||||||
|         private: |  | ||||||
|             Types::UUID_t       UUID_; |  | ||||||
|             std::string         Title_; |  | ||||||
|             std::string         Description_; |  | ||||||
|             std::string         RegisteredName_; |  | ||||||
|             ParametersVec       Parameters_; |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class JobRegistry { |  | ||||||
|         public: |  | ||||||
|             static auto instance() { |  | ||||||
|                 static auto instance_ = new JobRegistry; |  | ||||||
|                 return instance_; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             inline void RegisterJobType( const std::string & JobType, Job::WorkerFunction Function) { |  | ||||||
|                     JobTypes_[JobType] = std::move(Function); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             inline bool Execute(const std::string &JobType, const Job::Parameters & Params, Job::Result &Result, bool & Retry) { |  | ||||||
|                 auto Hint = JobTypes_.find(JobType); |  | ||||||
|                 if(Hint != end(JobTypes_)) { |  | ||||||
|                     Hint->second(Params, Result, Retry); |  | ||||||
|                     return true; |  | ||||||
|                 } |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         private: |  | ||||||
|             std::map<std::string,Job::WorkerFunction>  JobTypes_; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     inline auto JobRegistry() { return JobRegistry::instance(); } |  | ||||||
|  |  | ||||||
|     class JobController : public SubSystemServer, Poco::Runnable { |     class JobController : public SubSystemServer, Poco::Runnable { | ||||||
|         public: |         public: | ||||||
|             static auto instance() { |             static auto instance() { | ||||||
| @@ -112,11 +58,16 @@ namespace OpenWifi { | |||||||
|             void run() override; |             void run() override; | ||||||
|             inline void wakeup() { Thr_.wakeUp(); } |             inline void wakeup() { Thr_.wakeUp(); } | ||||||
|  |  | ||||||
|             bool JobList(Job::Statuses & Statuses); |             void AddJob( Job* newJob ) { | ||||||
|  |                 std::lock_guard G(Mutex_); | ||||||
|  |                 jobs_.push_back(newJob); | ||||||
|  |             } | ||||||
|  |  | ||||||
|         private: |         private: | ||||||
|             Poco::Thread            Thr_; |             Poco::Thread                        Thr_; | ||||||
|             std::atomic_bool        Running_=false; |             std::atomic_bool                    Running_=false; | ||||||
|  |             std::list<Job *>                    jobs_; | ||||||
|  |             Poco::ThreadPool                    Pool_; | ||||||
|  |  | ||||||
|         JobController() noexcept: |         JobController() noexcept: | ||||||
|             SubSystemServer("JobController", "JOB-SVR", "job") |             SubSystemServer("JobController", "JOB-SVR", "job") | ||||||
|   | |||||||
| @@ -228,10 +228,10 @@ namespace OpenWifi{ | |||||||
|  |  | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             SNL.serialNumbers = Existing.devices; |             SNL.serialNumbers = Existing.devices; | ||||||
|  |             auto JobId = MicroService::instance().CreateUUID(); | ||||||
|             auto Task = new VenueConfigUpdater(UUID,UserInfo_.userinfo,0,Logger()); |             Types::StringVec Parameters{UUID};; | ||||||
|             auto JobId = Task->Start(); |             auto NewJob = new VenueConfigUpdater(JobId,"VenueConfigurationUpdater", Parameters, 0, UserInfo_.userinfo, Logger()); | ||||||
|  |             JobController()->AddJob(dynamic_cast<Job*>(NewJob)); | ||||||
|             SNL.to_json(Answer); |             SNL.to_json(Answer); | ||||||
|             Answer.set("jobId",JobId); |             Answer.set("jobId",JobId); | ||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
| @@ -242,10 +242,10 @@ namespace OpenWifi{ | |||||||
|  |  | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             SNL.serialNumbers = Existing.devices; |             SNL.serialNumbers = Existing.devices; | ||||||
|  |             auto JobId = MicroService::instance().CreateUUID(); | ||||||
|             auto Task = new VenueUpgrade(UUID,UserInfo_.userinfo,0,Logger()); |             Types::StringVec Parameters{UUID};; | ||||||
|             auto JobId = Task->Start(); |             auto NewJob = new VenueUpgrade(JobId,"VenueFirmwareUpgrade", Parameters, 0, UserInfo_.userinfo, Logger()); | ||||||
|  |             JobController()->AddJob(dynamic_cast<Job*>(NewJob)); | ||||||
|             SNL.to_json(Answer); |             SNL.to_json(Answer); | ||||||
|             Answer.set("jobId",JobId); |             Answer.set("jobId",JobId); | ||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
| @@ -256,10 +256,10 @@ namespace OpenWifi{ | |||||||
|  |  | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             SNL.serialNumbers = Existing.devices; |             SNL.serialNumbers = Existing.devices; | ||||||
|  |             auto JobId = MicroService::instance().CreateUUID(); | ||||||
|             auto Task = new VenueRebooter(UUID,UserInfo_.userinfo,0,Logger()); |             Types::StringVec Parameters{UUID};; | ||||||
|             auto JobId = Task->Start(); |             auto NewJob = new VenueRebooter(JobId,"VenueRebooter", Parameters, 0, UserInfo_.userinfo, Logger()); | ||||||
|  |             JobController()->AddJob(dynamic_cast<Job*>(NewJob)); | ||||||
|             SNL.to_json(Answer); |             SNL.to_json(Answer); | ||||||
|             Answer.set("jobId",JobId); |             Answer.set("jobId",JobId); | ||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
|   | |||||||
| @@ -42,6 +42,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     void Signup::run() { |     void Signup::run() { | ||||||
|         Running_ = true; |         Running_ = true; | ||||||
|  |         Utils::SetThreadName("signup-mgr"); | ||||||
|         while(Running_) { |         while(Running_) { | ||||||
|             Poco::Thread::trySleep(5000); |             Poco::Thread::trySleep(5000); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -105,6 +105,7 @@ namespace OpenWifi { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void Storage::onTimer([[maybe_unused]] Poco::Timer &timer) { |     void Storage::onTimer([[maybe_unused]] Poco::Timer &timer) { | ||||||
|  |         Utils::SetThreadName("strg-janitor"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void Storage::Stop() { |     void Storage::Stop() { | ||||||
| @@ -279,11 +280,43 @@ namespace OpenWifi { | |||||||
|             return true; |             return true; | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  |         auto FixInventory = [&](const ProvObjects::InventoryTag &T) -> bool { | ||||||
|  |             // check the venue/entity for this device. | ||||||
|  |             ProvObjects::InventoryTag   NewTag{T}; | ||||||
|  |             bool modified=false; | ||||||
|  |             if(!T.venue.empty() && !VenueDB().Exists("id",T.venue)) { | ||||||
|  |                 NewTag.venue.clear(); | ||||||
|  |                 modified=true; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(!T.entity.empty() && !EntityDB().Exists("id",T.entity)) { | ||||||
|  |                 NewTag.entity.clear(); | ||||||
|  |                 modified=true; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(!T.location.empty() && !LocationDB().Exists("id",T.location)) { | ||||||
|  |                 NewTag.location.clear(); | ||||||
|  |                 modified=true; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(!T.contact.empty() && !ContactDB().Exists("id",T.contact)) { | ||||||
|  |                 NewTag.contact.clear(); | ||||||
|  |                 modified=true; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(modified) { | ||||||
|  |                 Logger().warning(fmt::format("  fixing entity: {}",T.info.name)); | ||||||
|  |                 InventoryDB().UpdateRecord("id", T.info.id, NewTag); | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         }; | ||||||
|  |  | ||||||
|         Logger().information("Checking DB consistency: venues"); |         Logger().information("Checking DB consistency: venues"); | ||||||
|         VenueDB().Iterate(FixVenueDevices); |         VenueDB().Iterate(FixVenueDevices); | ||||||
|         Logger().information("Checking DB consistency: entities"); |         Logger().information("Checking DB consistency: entities"); | ||||||
|         EntityDB().Iterate(FixEntity); |         EntityDB().Iterate(FixEntity); | ||||||
|  |         Logger().information("Checking DB consistency: inventory"); | ||||||
|  |         InventoryDB().Iterate(FixInventory); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void Storage::InitializeSystemDBs() { |     void Storage::InitializeSystemDBs() { | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ namespace OpenWifi { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void TagServer::run() { |     void TagServer::run() { | ||||||
|  |         Utils::SetThreadName("tag-server"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -9,6 +9,7 @@ | |||||||
| #include "APConfig.h" | #include "APConfig.h" | ||||||
| #include "sdks/SDK_gw.h" | #include "sdks/SDK_gw.h" | ||||||
| #include "framework/WebSocketClientNotifications.h" | #include "framework/WebSocketClientNotifications.h" | ||||||
|  | #include "JobController.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -19,8 +20,6 @@ namespace OpenWifi { | |||||||
|                 auto Status = Results->get("status").extract<Poco::JSON::Object::Ptr>(); |                 auto Status = Results->get("status").extract<Poco::JSON::Object::Ptr>(); | ||||||
|                 auto Rejected = Status->getArray("rejected"); |                 auto Rejected = Status->getArray("rejected"); | ||||||
|                 std::transform(Rejected->begin(),Rejected->end(),std::back_inserter(Warnings), [](auto i) -> auto { return i.toString(); }); |                 std::transform(Rejected->begin(),Rejected->end(),std::back_inserter(Warnings), [](auto i) -> auto { return i.toString(); }); | ||||||
| //                for(const auto &i:*Rejected) |  | ||||||
|                 //                  Warnings.push_back(i.toString()); |  | ||||||
|             } |             } | ||||||
|         } catch (...) { |         } catch (...) { | ||||||
|         } |         } | ||||||
| @@ -37,35 +36,42 @@ namespace OpenWifi { | |||||||
|         void run() final { |         void run() final { | ||||||
|             ProvObjects::InventoryTag   Device; |             ProvObjects::InventoryTag   Device; | ||||||
|             started_=true; |             started_=true; | ||||||
|  |             Utils::SetThreadName("venue-cfg"); | ||||||
|             if(StorageService()->InventoryDB().GetRecord("id",uuid_,Device)) { |             if(StorageService()->InventoryDB().GetRecord("id",uuid_,Device)) { | ||||||
|                 SerialNumber = Device.serialNumber; |                 SerialNumber = Device.serialNumber; | ||||||
|                 // std::cout << "Starting push for " << Device.serialNumber << std::endl; |                 // std::cout << "Starting push for " << Device.serialNumber << std::endl; | ||||||
|                 Logger().debug(fmt::format("{}: Computing configuration.",Device.serialNumber)); |                 Logger().debug(fmt::format("{}: Computing configuration.",Device.serialNumber)); | ||||||
|                 auto DeviceConfig = std::make_shared<APConfig>(Device.serialNumber, Device.deviceType, Logger(), false); |                 auto DeviceConfig = std::make_shared<APConfig>(Device.serialNumber, Device.deviceType, Logger(), false); | ||||||
|                 auto Configuration = Poco::makeShared<Poco::JSON::Object>(); |                 auto Configuration = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|                 if (DeviceConfig->Get(Configuration)) { |                 try { | ||||||
|                     std::ostringstream OS; |                     if (DeviceConfig->Get(Configuration)) { | ||||||
|                     Configuration->stringify(OS); |                         std::ostringstream OS; | ||||||
|                     auto Response=Poco::makeShared<Poco::JSON::Object>(); |                         Configuration->stringify(OS); | ||||||
|                     Logger().debug(fmt::format("{}: Pushing configuration.",Device.serialNumber)); |                         auto Response = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|                     if (SDK::GW::Device::Configure(nullptr, Device.serialNumber, Configuration, Response)) { |                         Logger().debug(fmt::format("{}: Pushing configuration.", Device.serialNumber)); | ||||||
|                         Logger().debug(fmt::format("{}: Configuration pushed.",Device.serialNumber)); |                         if (SDK::GW::Device::Configure(nullptr, Device.serialNumber, Configuration, Response)) { | ||||||
|                         Logger().information(fmt::format("{}: Updated.", Device.serialNumber)); |                             Logger().debug(fmt::format("{}: Configuration pushed.", Device.serialNumber)); | ||||||
|                         // std::cout << Device.serialNumber << ": Updated" << std::endl; |                             Logger().information(fmt::format("{}: Updated.", Device.serialNumber)); | ||||||
|                         updated_++; |                             // std::cout << Device.serialNumber << ": Updated" << std::endl; | ||||||
|  |                             updated_++; | ||||||
|  |                         } else { | ||||||
|  |                             Logger().information(fmt::format("{}: Not updated.", Device.serialNumber)); | ||||||
|  |                             // std::cout << Device.serialNumber << ": Failed" << std::endl; | ||||||
|  |                             failed_++; | ||||||
|  |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         Logger().information(fmt::format("{}: Not updated.", Device.serialNumber)); |                         Logger().debug(fmt::format("{}: Configuration is bad.", Device.serialNumber)); | ||||||
|                         // std::cout << Device.serialNumber << ": Failed" << std::endl; |                         bad_config_++; | ||||||
|                         failed_++; |                         // std::cout << Device.serialNumber << ": Bad config" << std::endl; | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } catch (...) { | ||||||
|                     Logger().debug(fmt::format("{}: Configuration is bad.",Device.serialNumber)); |                     Logger().debug(fmt::format("{}: Configuration is bad (caused an exception).", Device.serialNumber)); | ||||||
|                     bad_config_++; |                     bad_config_++; | ||||||
|                     // std::cout << Device.serialNumber << ": Bad config" << std::endl; |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             done_ = true; |             done_ = true; | ||||||
|             // std::cout << "Done push for " << Device.serialNumber << std::endl; |             // std::cout << "Done push for " << Device.serialNumber << std::endl; | ||||||
|  |             Utils::SetThreadName("free"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         uint64_t        updated_=0, failed_=0, bad_config_=0; |         uint64_t        updated_=0, failed_=0, bad_config_=0; | ||||||
| @@ -80,133 +86,101 @@ namespace OpenWifi { | |||||||
|         inline Poco::Logger & Logger() { return Logger_; } |         inline Poco::Logger & Logger() { return Logger_; } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class VenueConfigUpdater: public Poco::Runnable { |     class VenueConfigUpdater: public Job { | ||||||
|     public: |     public: | ||||||
|         explicit VenueConfigUpdater(const std::string & VenueUUID, const SecurityObjects::UserInfo &UI, uint64_t When, Poco::Logger &L) : |         VenueConfigUpdater(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) : | ||||||
|             VenueUUID_(VenueUUID), |                 Job(JobID, name, parameters, when, UI, L) { | ||||||
|             UI_(UI), |  | ||||||
|             When_(When), |  | ||||||
|             Logger_(L) |  | ||||||
|         { |  | ||||||
|  |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         inline std::string Start() { |         inline virtual void run() { | ||||||
|             JobId_ = MicroService::CreateUUID(); |             std::string                 VenueUUID_; | ||||||
|             Worker_.start(*this); |  | ||||||
|             return JobId_; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     private: |             Utils::SetThreadName("venue-update"); | ||||||
|         std::string                 VenueUUID_; |             VenueUUID_ = Parameter(0); | ||||||
|         SecurityObjects::UserInfo   UI_; |  | ||||||
|         uint64_t                    When_; |  | ||||||
|         Poco::Logger                &Logger_; |  | ||||||
|         Poco::Thread                Worker_; |  | ||||||
|         std::string                 JobId_; |  | ||||||
|         Poco::ThreadPool            Pool_{2,16,300}; |  | ||||||
|  |  | ||||||
|         inline Poco::Logger & Logger() { return Logger_; } |  | ||||||
|  |  | ||||||
|         inline void run() final { |  | ||||||
|  |  | ||||||
|             if(When_ && When_>OpenWifi::Now()) |  | ||||||
|                 Poco::Thread::trySleep( (long) (When_ - OpenWifi::Now()) * 1000 ); |  | ||||||
|  |  | ||||||
|             WebSocketNotification<WebSocketNotificationJobContent> N; |             WebSocketNotification<WebSocketNotificationJobContent> N; | ||||||
|  |  | ||||||
|             Logger().information(fmt::format("Job {} Starting.", JobId_)); |  | ||||||
|  |  | ||||||
|             ProvObjects::Venue  Venue; |             ProvObjects::Venue  Venue; | ||||||
|             uint64_t Updated = 0, Failed = 0 , BadConfigs = 0 ; |             uint64_t Updated = 0, Failed = 0 , BadConfigs = 0 ; | ||||||
|             if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { |             if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { | ||||||
|                 const std::size_t MaxThreads=16; |  | ||||||
|                 struct tState { |  | ||||||
|                     Poco::Thread                thr_; |  | ||||||
|                     VenueDeviceConfigUpdater    *task= nullptr; |  | ||||||
|                 }; |  | ||||||
|  |  | ||||||
|                 N.content.title = fmt::format("Updating {} configurations", Venue.info.name); |                 N.content.title = fmt::format("Updating {} configurations", Venue.info.name); | ||||||
|                 N.content.jobId = JobId_; |                 N.content.jobId = JobId(); | ||||||
|  |  | ||||||
|  |                 Poco::ThreadPool    Pool_; | ||||||
|  |                 std::list<VenueDeviceConfigUpdater*> JobList; | ||||||
|  |  | ||||||
|                 std::array<tState,MaxThreads> Tasks; |  | ||||||
|  |  | ||||||
|                 for(const auto &uuid:Venue.devices) { |                 for(const auto &uuid:Venue.devices) { | ||||||
|                     auto NewTask = new VenueDeviceConfigUpdater(uuid, Venue.info.name, Logger()); |                     auto NewTask = new VenueDeviceConfigUpdater(uuid, Venue.info.name, Logger()); | ||||||
|                     // std::cout << "Scheduling config push for " << uuid << std::endl; |                     bool TaskAdded=false; | ||||||
|                     bool found_slot = false; |                     while(!TaskAdded) { | ||||||
|                     while (!found_slot) { |                         if (Pool_.available()) { | ||||||
|                         for (auto &cur_task: Tasks) { |                             JobList.push_back(NewTask); | ||||||
|                             if (cur_task.task == nullptr) { |                             Pool_.start(*NewTask); | ||||||
|                                 cur_task.task = NewTask; |                             TaskAdded = true; | ||||||
|                                 cur_task.thr_.start(*NewTask); |                             continue; | ||||||
|                                 found_slot = true; |  | ||||||
|                                 break; |  | ||||||
|                             } |  | ||||||
|                         } |                         } | ||||||
|  |                     } | ||||||
|  |  | ||||||
|                         //  Let's look for a slot... |                     for(auto job_it = JobList.begin(); job_it !=JobList.end();) { | ||||||
|                         if (!found_slot) { |                         VenueDeviceConfigUpdater * current_job = *job_it; | ||||||
|                             for (auto &cur_task: Tasks) { |                         if(current_job!= nullptr && current_job->done_) { | ||||||
|                                 if (cur_task.task != nullptr && cur_task.task->started_) { |                             Updated += current_job->updated_; | ||||||
|                                     if (cur_task.thr_.isRunning()) |                             Failed += current_job->failed_; | ||||||
|                                         continue; |                             BadConfigs += current_job->bad_config_; | ||||||
|                                     if (!cur_task.thr_.isRunning() && cur_task.task->done_) { |                             if(current_job->updated_) { | ||||||
|                                         cur_task.thr_.join(); |                                 N.content.success.push_back(current_job->SerialNumber); | ||||||
|                                         Updated += cur_task.task->updated_; |                             } else if(current_job->failed_) { | ||||||
|                                         Failed += cur_task.task->failed_; |                                 N.content.warning.push_back(current_job->SerialNumber); | ||||||
|                                         BadConfigs += cur_task.task->bad_config_; |                             } else { | ||||||
|                                         cur_task.task->started_ = cur_task.task->done_ = false; |                                 N.content.error.push_back(current_job->SerialNumber); | ||||||
|                                         delete cur_task.task; |  | ||||||
|                                         cur_task.task = nullptr; |  | ||||||
|                                     } |  | ||||||
|                                 } |  | ||||||
|                             } |                             } | ||||||
|  |                             job_it = JobList.erase(job_it); | ||||||
|  |                             delete current_job; | ||||||
|  |                         } else { | ||||||
|  |                             ++job_it; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 Logger().debug("Waiting for outstanding update threads to finish."); |                 Logger().debug("Waiting for outstanding update threads to finish."); | ||||||
|                 bool stillTasksRunning=true; |                 Pool_.joinAll(); | ||||||
|                 while(stillTasksRunning) { |                 for(auto job_it = JobList.begin(); job_it !=JobList.end();) { | ||||||
|                     stillTasksRunning = false; |                     VenueDeviceConfigUpdater * current_job = *job_it; | ||||||
|                     for(auto &cur_task:Tasks) { |                     if(current_job!= nullptr && current_job->done_) { | ||||||
|                         if(cur_task.task!= nullptr && cur_task.task->started_) { |                         Updated += current_job->updated_; | ||||||
|                             if(cur_task.thr_.isRunning()) { |                         Failed += current_job->failed_; | ||||||
|                                 stillTasksRunning = true; |                         BadConfigs += current_job->bad_config_; | ||||||
|                                 continue; |                         if(current_job->updated_) { | ||||||
|                             } |                             N.content.success.push_back(current_job->SerialNumber); | ||||||
|                             if(!cur_task.thr_.isRunning() && cur_task.task->done_) { |                         } else if(current_job->failed_) { | ||||||
|                                 cur_task.thr_.join(); |                             N.content.warning.push_back(current_job->SerialNumber); | ||||||
|                                 if(cur_task.task->updated_) { |                         } else { | ||||||
|                                     Updated++; |                             N.content.error.push_back(current_job->SerialNumber); | ||||||
|                                     N.content.success.push_back(cur_task.task->SerialNumber); |  | ||||||
|                                 } else if(cur_task.task->failed_) { |  | ||||||
|                                     Failed++; |  | ||||||
|                                     N.content.warning.push_back(cur_task.task->SerialNumber); |  | ||||||
|                                 } else { |  | ||||||
|                                     BadConfigs++; |  | ||||||
|                                     N.content.error.push_back(cur_task.task->SerialNumber); |  | ||||||
|                                 } |  | ||||||
|                                 cur_task.task->started_ = cur_task.task->done_ = false; |  | ||||||
|                                 delete cur_task.task; |  | ||||||
|                                 cur_task.task = nullptr; |  | ||||||
|                             } |  | ||||||
|                         } |                         } | ||||||
|  |                         job_it = JobList.erase(job_it); | ||||||
|  |                         delete current_job; | ||||||
|  |                     } else { | ||||||
|  |                         ++job_it; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 N.content.details = fmt::format("Job {} Completed: {} updated, {} failed to update, {} bad configurations. ", |                 N.content.details = fmt::format("Job {} Completed: {} updated, {} failed to update, {} bad configurations. ", | ||||||
|                                                 JobId_, Updated ,Failed, BadConfigs); |                                                 JobId(), Updated ,Failed, BadConfigs); | ||||||
|  |  | ||||||
|             } else { |             } else { | ||||||
|                 N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); |                 N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); | ||||||
|                 Logger().warning(N.content.details); |                 Logger().warning(N.content.details); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             WebSocketClientNotificationVenueUpdateJobCompletionToUser(UI_.email, N); |             // std::cout << N.content.details << std::endl; | ||||||
|  |             WebSocketClientNotificationVenueUpdateJobCompletionToUser(UserInfo().email, N); | ||||||
|             Logger().information(fmt::format("Job {} Completed: {} updated, {} failed to update , {} bad configurations.", |             Logger().information(fmt::format("Job {} Completed: {} updated, {} failed to update , {} bad configurations.", | ||||||
|                                              JobId_, Updated ,Failed, BadConfigs)); |                                              JobId(), Updated ,Failed, BadConfigs)); | ||||||
|             delete this; |             Utils::SetThreadName("free"); | ||||||
|  |             Complete(); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "APConfig.h" | #include "APConfig.h" | ||||||
| #include "sdks/SDK_gw.h" | #include "sdks/SDK_gw.h" | ||||||
|  | #include "JobController.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -48,129 +49,90 @@ namespace OpenWifi { | |||||||
|         inline Poco::Logger & Logger() { return Logger_; } |         inline Poco::Logger & Logger() { return Logger_; } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class VenueRebooter: public Poco::Runnable { |     class VenueRebooter: public Job { | ||||||
|     public: |     public: | ||||||
|         explicit VenueRebooter(const std::string & VenueUUID, const SecurityObjects::UserInfo &UI, uint64_t When, Poco::Logger &L) : |         VenueRebooter(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) : | ||||||
|                 VenueUUID_(VenueUUID), |                 Job(JobID, name, parameters, when, UI, L) { | ||||||
|                 UI_(UI), |  | ||||||
|                 When_(When), |  | ||||||
|                 Logger_(L) |  | ||||||
|         { |  | ||||||
|  |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         inline std::string Start() { |         inline virtual void run() final { | ||||||
|             JobId_ = MicroService::CreateUUID(); |  | ||||||
|             Worker_.start(*this); |  | ||||||
|             return JobId_; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     private: |             Utils::SetThreadName("venue-reboot"); | ||||||
|         std::string                 VenueUUID_; |  | ||||||
|         SecurityObjects::UserInfo   UI_; |  | ||||||
|         uint64_t                    When_; |  | ||||||
|         Poco::Logger                &Logger_; |  | ||||||
|         Poco::Thread                Worker_; |  | ||||||
|         std::string                 JobId_; |  | ||||||
|         Poco::ThreadPool            Pool_{2,16,300}; |  | ||||||
|  |  | ||||||
|         inline Poco::Logger & Logger() { return Logger_; } |  | ||||||
|  |  | ||||||
|         inline void run() final { |  | ||||||
|  |  | ||||||
|             if(When_ && When_>OpenWifi::Now()) |  | ||||||
|                 Poco::Thread::trySleep( (long) (When_ - OpenWifi::Now()) * 1000 ); |  | ||||||
|  |  | ||||||
|             WebSocketClientNotificationVenueRebootList_t        N; |             WebSocketClientNotificationVenueRebootList_t        N; | ||||||
|  |             auto VenueUUID_ = Parameter(0); | ||||||
|             Logger().information(fmt::format("Job {} Starting.", JobId_)); |  | ||||||
|  |  | ||||||
|             ProvObjects::Venue  Venue; |             ProvObjects::Venue  Venue; | ||||||
|             uint64_t rebooted_ = 0, failed_ = 0; |             uint64_t rebooted_ = 0, failed_ = 0; | ||||||
|             if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { |             if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { | ||||||
|                 const std::size_t MaxThreads=16; |  | ||||||
|                 struct tState { |  | ||||||
|                     Poco::Thread                thr_; |  | ||||||
|                     VenueDeviceRebooter    *task= nullptr; |  | ||||||
|                 }; |  | ||||||
|  |  | ||||||
|                 N.content.title = fmt::format("Rebooting {} devices.", Venue.info.name); |                 N.content.title = fmt::format("Rebooting {} devices.", Venue.info.name); | ||||||
|                 N.content.jobId = JobId_; |                 N.content.jobId = JobId(); | ||||||
|  |  | ||||||
|                 std::array<tState,MaxThreads> Tasks; |                 Poco::ThreadPool    Pool_; | ||||||
|  |                 std::list<VenueDeviceRebooter*> JobList; | ||||||
|  |  | ||||||
|                 for(const auto &uuid:Venue.devices) { |                 for(const auto &uuid:Venue.devices) { | ||||||
|                     auto NewTask = new VenueDeviceRebooter(uuid, Venue.info.name, Logger()); |                     auto NewTask = new VenueDeviceRebooter(uuid, Venue.info.name, Logger()); | ||||||
|                     // std::cout << "Scheduling config push for " << uuid << std::endl; |                     bool TaskAdded=false; | ||||||
|                     bool found_slot = false; |                     while(!TaskAdded) { | ||||||
|                     while (!found_slot) { |                         if (Pool_.available()) { | ||||||
|                         for (auto &cur_task: Tasks) { |                             JobList.push_back(NewTask); | ||||||
|                             if (cur_task.task == nullptr) { |                             Pool_.start(*NewTask); | ||||||
|                                 cur_task.task = NewTask; |                             TaskAdded = true; | ||||||
|                                 cur_task.thr_.start(*NewTask); |                             continue; | ||||||
|                                 found_slot = true; |  | ||||||
|                                 break; |  | ||||||
|                             } |  | ||||||
|                         } |                         } | ||||||
|  |                     } | ||||||
|  |  | ||||||
|                         //  Let's look for a slot... |                     for(auto job_it = JobList.begin(); job_it !=JobList.end();) { | ||||||
|                         if (!found_slot) { |                         VenueDeviceRebooter * current_job = *job_it; | ||||||
|                             for (auto &cur_task: Tasks) { |                         if(current_job!= nullptr && current_job->done_) { | ||||||
|                                 if (cur_task.task != nullptr && cur_task.task->started_) { |                             if(current_job->rebooted_) | ||||||
|                                     if (cur_task.thr_.isRunning()) |                                 N.content.success.push_back(current_job->SerialNumber); | ||||||
|                                         continue; |                             else | ||||||
|                                     if (!cur_task.thr_.isRunning() && cur_task.task->done_) { |                                 N.content.warning.push_back(current_job->SerialNumber); | ||||||
|                                         cur_task.thr_.join(); |                             rebooted_ += current_job->rebooted_; | ||||||
|                                         rebooted_ += cur_task.task->rebooted_; |                             failed_ += current_job->failed_; | ||||||
|                                         failed_ += cur_task.task->failed_; |                             job_it = JobList.erase(job_it); | ||||||
|                                         cur_task.task->started_ = cur_task.task->done_ = false; |                             delete current_job; | ||||||
|                                         delete cur_task.task; |                         } else { | ||||||
|                                         cur_task.task = nullptr; |                             ++job_it; | ||||||
|                                     } |  | ||||||
|                                 } |  | ||||||
|                             } |  | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 Logger().debug("Waiting for outstanding update threads to finish."); |                 Logger().debug("Waiting for outstanding update threads to finish."); | ||||||
|                 bool stillTasksRunning=true; |                 Pool_.joinAll(); | ||||||
|                 while(stillTasksRunning) { |                 for(auto job_it = JobList.begin(); job_it !=JobList.end();) { | ||||||
|                     stillTasksRunning = false; |                     VenueDeviceRebooter * current_job = *job_it; | ||||||
|                     for(auto &cur_task:Tasks) { |                     if(current_job!= nullptr && current_job->done_) { | ||||||
|                         if(cur_task.task!= nullptr && cur_task.task->started_) { |                         if(current_job->rebooted_) | ||||||
|                             if(cur_task.thr_.isRunning()) { |                             N.content.success.push_back(current_job->SerialNumber); | ||||||
|                                 stillTasksRunning = true; |                         else | ||||||
|                                 continue; |                             N.content.warning.push_back(current_job->SerialNumber); | ||||||
|                             } |                         rebooted_ += current_job->rebooted_; | ||||||
|                             if(!cur_task.thr_.isRunning() && cur_task.task->done_) { |                         failed_ += current_job->failed_; | ||||||
|                                 cur_task.thr_.join(); |                         job_it = JobList.erase(job_it); | ||||||
|                                 if(cur_task.task->rebooted_) { |                         delete current_job; | ||||||
|                                     rebooted_++; |                     } else { | ||||||
|                                     N.content.success.push_back(cur_task.task->SerialNumber); |                         ++job_it; | ||||||
|                                 } else if(cur_task.task->failed_) { |  | ||||||
|                                     failed_++; |  | ||||||
|                                     N.content.warning.push_back(cur_task.task->SerialNumber); |  | ||||||
|                                 } |  | ||||||
|                                 cur_task.task->started_ = cur_task.task->done_ = false; |  | ||||||
|                                 delete cur_task.task; |  | ||||||
|                                 cur_task.task = nullptr; |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 N.content.details = fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.", |                 N.content.details = fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.", | ||||||
|                                                 JobId_, rebooted_ ,failed_); |                                                 JobId(), rebooted_ ,failed_); | ||||||
|  |  | ||||||
|             } else { |             } else { | ||||||
|                 N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); |                 N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); | ||||||
|                 Logger().warning(N.content.details); |                 Logger().warning(N.content.details); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             WebSocketClientNotificationVenueRebootCompletionToUser(UI_.email,N); |             // std::cout << N.content.details << std::endl; | ||||||
|  |             WebSocketClientNotificationVenueRebootCompletionToUser(UserInfo().email,N); | ||||||
|             Logger().information(fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.", |             Logger().information(fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.", | ||||||
|                                              JobId_, rebooted_ ,failed_)); |                                              JobId(), rebooted_ ,failed_)); | ||||||
|             delete this; |             Utils::SetThreadName("free"); | ||||||
|  |             Complete(); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
| #include "APConfig.h" | #include "APConfig.h" | ||||||
| #include "sdks/SDK_gw.h" | #include "sdks/SDK_gw.h" | ||||||
| #include "sdks/SDK_fms.h" | #include "sdks/SDK_fms.h" | ||||||
|  | #include "JobController.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|     class VenueDeviceUpgrade : public Poco::Runnable { |     class VenueDeviceUpgrade : public Poco::Runnable { | ||||||
| @@ -30,7 +31,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|                 Storage::ApplyRules(rules_,Device.deviceRules); |                 Storage::ApplyRules(rules_,Device.deviceRules); | ||||||
|                 if(Device.deviceRules.firmwareUpgrade=="no") { |                 if(Device.deviceRules.firmwareUpgrade=="no") { | ||||||
|                     std::cout << "Skipped Upgrade:" << Device.serialNumber << std::endl; |                     poco_debug(Logger(),fmt::format("Skipped Upgrade: {}", Device.serialNumber)); | ||||||
|                     skipped_++; |                     skipped_++; | ||||||
|                     done_=true; |                     done_=true; | ||||||
|                     return; |                     return; | ||||||
| @@ -39,16 +40,14 @@ namespace OpenWifi { | |||||||
|                 FMSObjects::Firmware    F; |                 FMSObjects::Firmware    F; | ||||||
|                 if(SDK::FMS::Firmware::GetLatest(Device.deviceType,Device.deviceRules.rcOnly=="yes",F)) { |                 if(SDK::FMS::Firmware::GetLatest(Device.deviceType,Device.deviceRules.rcOnly=="yes",F)) { | ||||||
|                     if (SDK::GW::Device::Upgrade(nullptr, Device.serialNumber, 0, F.uri)) { |                     if (SDK::GW::Device::Upgrade(nullptr, Device.serialNumber, 0, F.uri)) { | ||||||
|                         std::cout << "Upgraded:" << Device.serialNumber << " to " << F.uri << std::endl; |  | ||||||
|                         Logger().debug(fmt::format("{}: Upgraded.",Device.serialNumber)); |                         Logger().debug(fmt::format("{}: Upgraded.",Device.serialNumber)); | ||||||
|                         upgraded_++; |                         upgraded_++; | ||||||
|                     } else { |                     } else { | ||||||
|                         std::cout << "Did not Upgrade:" << Device.serialNumber << " to " << F.uri << std::endl; |  | ||||||
|                         Logger().information(fmt::format("{}: Not Upgraded.", Device.serialNumber)); |                         Logger().information(fmt::format("{}: Not Upgraded.", Device.serialNumber)); | ||||||
|                         failed_++; |                         failed_++; | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     std::cout << "Did not Upgrade:" << Device.serialNumber << " to <unknown>" << std::endl; |                     Logger().information(fmt::format("{}: Not Upgraded. No firmware available.", Device.serialNumber)); | ||||||
|                     failed_++; |                     failed_++; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -69,132 +68,94 @@ namespace OpenWifi { | |||||||
|         inline Poco::Logger & Logger() { return Logger_; } |         inline Poco::Logger & Logger() { return Logger_; } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class VenueUpgrade: public Poco::Runnable { |     class VenueUpgrade: public Job { | ||||||
|     public: |     public: | ||||||
|         explicit VenueUpgrade(const std::string & VenueUUID, const SecurityObjects::UserInfo &UI, uint64_t When, Poco::Logger &L) : |         VenueUpgrade(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) : | ||||||
|                 VenueUUID_(VenueUUID), |                 Job(JobID, name, parameters, when, UI, L) { | ||||||
|                 UI_(UI), |  | ||||||
|                 When_(When), |  | ||||||
|                 Logger_(L) |  | ||||||
|         { |  | ||||||
|  |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         inline std::string Start() { |         inline virtual void run() final { | ||||||
|             JobId_ = MicroService::CreateUUID(); |  | ||||||
|             Worker_.start(*this); |  | ||||||
|             return JobId_; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     private: |             Utils::SetThreadName("venue-upgr"); | ||||||
|         std::string                 VenueUUID_; |             auto VenueUUID_ = Parameter(0); | ||||||
|         SecurityObjects::UserInfo   UI_; |  | ||||||
|         uint64_t                    When_; |  | ||||||
|         Poco::Logger                &Logger_; |  | ||||||
|         Poco::Thread                Worker_; |  | ||||||
|         std::string                 JobId_; |  | ||||||
|         Poco::ThreadPool            Pool_{2,16,300}; |  | ||||||
|  |  | ||||||
|         inline Poco::Logger & Logger() { return Logger_; } |  | ||||||
|  |  | ||||||
|         inline void run() final { |  | ||||||
|  |  | ||||||
|             if(When_ && When_>OpenWifi::Now()) |  | ||||||
|                 Poco::Thread::trySleep( (long) (When_ - OpenWifi::Now()) * 1000 ); |  | ||||||
|  |  | ||||||
|             WebSocketClientNotificationVenueRebootList_t        N; |             WebSocketClientNotificationVenueRebootList_t        N; | ||||||
|  |  | ||||||
|             Logger().information(fmt::format("Job {} Starting.", JobId_)); |  | ||||||
|  |  | ||||||
|             ProvObjects::Venue  Venue; |             ProvObjects::Venue  Venue; | ||||||
|             uint64_t upgraded_ = 0, failed_ = 0; |             uint64_t upgraded_ = 0, failed_ = 0; | ||||||
|             if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { |             if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { | ||||||
|                 const std::size_t MaxThreads=16; |  | ||||||
|                 struct tState { |  | ||||||
|                     Poco::Thread                thr_; |  | ||||||
|                     VenueDeviceUpgrade    *task= nullptr; |  | ||||||
|                 }; |  | ||||||
|  |  | ||||||
|                 N.content.title = fmt::format("Upgrading {} devices.", Venue.info.name); |                 N.content.title = fmt::format("Upgrading {} devices.", Venue.info.name); | ||||||
|                 N.content.jobId = JobId_; |                 N.content.jobId = JobId(); | ||||||
|  |  | ||||||
|                 std::array<tState,MaxThreads> Tasks; |                 Poco::ThreadPool                Pool_; | ||||||
|                 ProvObjects::DeviceRules    Rules; |                 std::list<VenueDeviceUpgrade*>  JobList; | ||||||
|  |                 ProvObjects::DeviceRules        Rules; | ||||||
|  |  | ||||||
|                 StorageService()->VenueDB().EvaluateDeviceRules(Venue.info.id, Rules); |                 StorageService()->VenueDB().EvaluateDeviceRules(Venue.info.id, Rules); | ||||||
|  |  | ||||||
|                 for(const auto &uuid:Venue.devices) { |                 for(const auto &uuid:Venue.devices) { | ||||||
|                     auto NewTask = new VenueDeviceUpgrade(uuid, Venue.info.name, Rules,Logger()); |                     auto NewTask = new VenueDeviceUpgrade(uuid, Venue.info.name, Rules, Logger()); | ||||||
|                     // std::cout << "Scheduling config push for " << uuid << std::endl; |                     bool TaskAdded = false; | ||||||
|                     bool found_slot = false; |                     while (!TaskAdded) { | ||||||
|                     while (!found_slot) { |                         if (Pool_.available()) { | ||||||
|                         for (auto &cur_task: Tasks) { |                             JobList.push_back(NewTask); | ||||||
|                             if (cur_task.task == nullptr) { |                             Pool_.start(*NewTask); | ||||||
|                                 cur_task.task = NewTask; |                             TaskAdded = true; | ||||||
|                                 cur_task.thr_.start(*NewTask); |                             continue; | ||||||
|                                 found_slot = true; |  | ||||||
|                                 break; |  | ||||||
|                             } |  | ||||||
|                         } |                         } | ||||||
|  |                     } | ||||||
|  |  | ||||||
|                         //  Let's look for a slot... |                     for (auto job_it = JobList.begin(); job_it != JobList.end();) { | ||||||
|                         if (!found_slot) { |                         VenueDeviceUpgrade *current_job = *job_it; | ||||||
|                             for (auto &cur_task: Tasks) { |                         if (current_job != nullptr && current_job->done_) { | ||||||
|                                 if (cur_task.task != nullptr && cur_task.task->started_) { |                             if (current_job->upgraded_) | ||||||
|                                     if (cur_task.thr_.isRunning()) |                                 N.content.success.push_back(current_job->SerialNumber); | ||||||
|                                         continue; |                             else | ||||||
|                                     if (!cur_task.thr_.isRunning() && cur_task.task->done_) { |                                 N.content.warning.push_back(current_job->SerialNumber); | ||||||
|                                         cur_task.thr_.join(); |                             upgraded_ += current_job->upgraded_; | ||||||
|                                         upgraded_ += cur_task.task->upgraded_; |                             failed_ += current_job->failed_; | ||||||
|                                         failed_ += cur_task.task->failed_; |                             job_it = JobList.erase(job_it); | ||||||
|                                         cur_task.task->started_ = cur_task.task->done_ = false; |                             delete current_job; | ||||||
|                                         delete cur_task.task; |                         } else { | ||||||
|                                         cur_task.task = nullptr; |                             ++job_it; | ||||||
|                                     } |  | ||||||
|                                 } |  | ||||||
|                             } |  | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 Logger().debug("Waiting for outstanding update threads to finish."); |  | ||||||
|                 bool stillTasksRunning=true; |                 Logger().debug("Waiting for outstanding upgrade threads to finish."); | ||||||
|                 while(stillTasksRunning) { |                 Pool_.joinAll(); | ||||||
|                     stillTasksRunning = false; |                 for(auto job_it = JobList.begin(); job_it !=JobList.end();) { | ||||||
|                     for(auto &cur_task:Tasks) { |                     VenueDeviceUpgrade * current_job = *job_it; | ||||||
|                         if(cur_task.task!= nullptr && cur_task.task->started_) { |                     if(current_job!= nullptr && current_job->done_) { | ||||||
|                             if(cur_task.thr_.isRunning()) { |                         if(current_job->upgraded_) | ||||||
|                                 stillTasksRunning = true; |                             N.content.success.push_back(current_job->SerialNumber); | ||||||
|                                 continue; |                         else | ||||||
|                             } |                             N.content.warning.push_back(current_job->SerialNumber); | ||||||
|                             if(!cur_task.thr_.isRunning() && cur_task.task->done_) { |                         upgraded_ += current_job->upgraded_; | ||||||
|                                 cur_task.thr_.join(); |                         failed_ += current_job->failed_; | ||||||
|                                 if(cur_task.task->upgraded_) { |                         job_it = JobList.erase(job_it); | ||||||
|                                     upgraded_++; |                         delete current_job; | ||||||
|                                     N.content.success.push_back(cur_task.task->SerialNumber); |                     } else { | ||||||
|                                 } else if(cur_task.task->failed_) { |                         ++job_it; | ||||||
|                                     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: {} upgraded, {} failed to upgrade.", |                 N.content.details = fmt::format("Job {} Completed: {} upgraded, {} failed to upgrade.", | ||||||
|                                                 JobId_, upgraded_ ,failed_); |                                                 JobId(), upgraded_ ,failed_); | ||||||
|  |  | ||||||
|             } else { |             } else { | ||||||
|                 N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); |                 N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); | ||||||
|                 Logger().warning(N.content.details); |                 Logger().warning(N.content.details); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             WebSocketClientNotificationVenueRebootCompletionToUser(UI_.email,N); |             // std::cout << N.content.details << std::endl; | ||||||
|  |             WebSocketClientNotificationVenueRebootCompletionToUser(UserInfo().email,N); | ||||||
|             Logger().information(fmt::format("Job {} Completed: {} upgraded, {} failed to upgrade.", |             Logger().information(fmt::format("Job {} Completed: {} upgraded, {} failed to upgrade.", | ||||||
|                                              JobId_, upgraded_ ,failed_)); |                                              JobId(), upgraded_ ,failed_)); | ||||||
|             delete this; |             Utils::SetThreadName("free"); | ||||||
|  |  | ||||||
|  |             Complete(); | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| @@ -643,6 +643,27 @@ namespace OpenWifi::RESTAPI_utils { | |||||||
|  |  | ||||||
| namespace OpenWifi::Utils { | namespace OpenWifi::Utils { | ||||||
|  |  | ||||||
|  | 	inline void SetThreadName(const char *name) { | ||||||
|  | #ifdef __linux__ | ||||||
|  | 		Poco::Thread::current()->setName(name); | ||||||
|  | 		pthread_setname_np(pthread_self(), name); | ||||||
|  | #endif | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | 	Poco::Thread::current()->setName(name); | ||||||
|  | 	pthread_setname_np(name); | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	inline void SetThreadName(Poco::Thread &thr, const char *name) { | ||||||
|  | #ifdef __linux__ | ||||||
|  | 		thr.setName(name); | ||||||
|  | 		pthread_setname_np(thr.tid(), name); | ||||||
|  | #endif | ||||||
|  | #ifdef __APPLE__ | ||||||
|  | 		thr.setName(name); | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
|     enum MediaTypeEncodings { |     enum MediaTypeEncodings { | ||||||
|         PLAIN, |         PLAIN, | ||||||
|         BINARY, |         BINARY, | ||||||
| @@ -1316,7 +1337,7 @@ namespace OpenWifi { | |||||||
| 		inline void Start(); | 		inline void Start(); | ||||||
| 		inline void Stop(); | 		inline void Stop(); | ||||||
| 	  private: | 	  private: | ||||||
| 		std::atomic_bool 	Running_ = false; | 		mutable std::atomic_bool 	Running_ = false; | ||||||
| 		Poco::Thread		Thread_; | 		Poco::Thread		Thread_; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| @@ -1847,7 +1868,8 @@ namespace OpenWifi { | |||||||
| 	            Request = &RequestIn; | 	            Request = &RequestIn; | ||||||
| 	            Response = &ResponseIn; | 	            Response = &ResponseIn; | ||||||
|  |  | ||||||
| 				Poco::Thread::current()->setName("WebServerThread_" + std::to_string(TransactionId_)); | 				std::string th_name = "restsvr_" + std::to_string(TransactionId_); | ||||||
|  | 				Utils::SetThreadName(th_name.c_str()); | ||||||
|  |  | ||||||
|                 if(Request->getContentLength()>0) { |                 if(Request->getContentLength()>0) { | ||||||
|                     if(Request->getContentType().find("application/json")!=std::string::npos) { |                     if(Request->getContentType().find("application/json")!=std::string::npos) { | ||||||
| @@ -2579,7 +2601,7 @@ namespace OpenWifi { | |||||||
|     private: |     private: | ||||||
|         std::recursive_mutex  	Mutex_; |         std::recursive_mutex  	Mutex_; | ||||||
|         Poco::Thread        	Worker_; |         Poco::Thread        	Worker_; | ||||||
|         std::atomic_bool    	Running_=false; |         mutable std::atomic_bool    	Running_=false; | ||||||
| 		Poco::NotificationQueue	Queue_; | 		Poco::NotificationQueue	Queue_; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -2605,7 +2627,7 @@ namespace OpenWifi { | |||||||
| 	  private: | 	  private: | ||||||
| 		std::recursive_mutex  	Mutex_; | 		std::recursive_mutex  	Mutex_; | ||||||
|         Poco::Thread        	Worker_; |         Poco::Thread        	Worker_; | ||||||
|         std::atomic_bool    	Running_=false; |         mutable std::atomic_bool    	Running_=false; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| 	class KafkaDispatcher : public Poco::Runnable { | 	class KafkaDispatcher : public Poco::Runnable { | ||||||
| @@ -2662,6 +2684,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 		inline void run() override { | 		inline void run() override { | ||||||
| 			Poco::AutoPtr<Poco::Notification>	Note(Queue_.waitDequeueNotification()); | 			Poco::AutoPtr<Poco::Notification>	Note(Queue_.waitDequeueNotification()); | ||||||
|  | 			Utils::SetThreadName("kafka-dispatch"); | ||||||
| 			while(Note && Running_) { | 			while(Note && Running_) { | ||||||
| 				auto Msg = dynamic_cast<KafkaMessage*>(Note.get()); | 				auto Msg = dynamic_cast<KafkaMessage*>(Note.get()); | ||||||
| 				if(Msg!= nullptr) { | 				if(Msg!= nullptr) { | ||||||
| @@ -2687,7 +2710,7 @@ namespace OpenWifi { | |||||||
| 		std::recursive_mutex  	Mutex_; | 		std::recursive_mutex  	Mutex_; | ||||||
| 		Types::NotifyTable      Notifiers_; | 		Types::NotifyTable      Notifiers_; | ||||||
| 		Poco::Thread        	Worker_; | 		Poco::Thread        	Worker_; | ||||||
| 		std::atomic_bool    	Running_=false; | 		mutable std::atomic_bool    	Running_=false; | ||||||
| 		uint64_t          		FunctionId_=1; | 		uint64_t          		FunctionId_=1; | ||||||
| 		Poco::NotificationQueue	Queue_; | 		Poco::NotificationQueue	Queue_; | ||||||
| 	}; | 	}; | ||||||
| @@ -2882,6 +2905,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	            void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override | 	            void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override | ||||||
| 	            { | 	            { | ||||||
|  | 					Utils::SetThreadName("alb-request"); | ||||||
| 					try { | 					try { | ||||||
| 						if((id_ % 100) == 0) { | 						if((id_ % 100) == 0) { | ||||||
| 							Logger_.debug(fmt::format("ALB-REQUEST({}): ALB Request {}.", | 							Logger_.debug(fmt::format("ALB-REQUEST({}): ALB Request {}.", | ||||||
| @@ -2950,7 +2974,7 @@ namespace OpenWifi { | |||||||
| 	    std::unique_ptr<Poco::Net::HTTPServer>   	Server_; | 	    std::unique_ptr<Poco::Net::HTTPServer>   	Server_; | ||||||
| 	    std::unique_ptr<Poco::Net::ServerSocket> 	Socket_; | 	    std::unique_ptr<Poco::Net::ServerSocket> 	Socket_; | ||||||
| 	    int                                     	Port_ = 0; | 	    int                                     	Port_ = 0; | ||||||
| 	    std::atomic_bool                            Running_=false; | 	    mutable std::atomic_bool                            Running_=false; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline auto ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); } | 	inline auto ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); } | ||||||
| @@ -2982,7 +3006,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	    inline Poco::Net::HTTPRequestHandler *CallServer(const std::string &Path, uint64_t Id) { | 	    inline Poco::Net::HTTPRequestHandler *CallServer(const std::string &Path, uint64_t Id) { | ||||||
| 	        RESTAPIHandler::BindingMap Bindings; | 	        RESTAPIHandler::BindingMap Bindings; | ||||||
| 			Poco::Thread::current()->setName(fmt::format("RESTAPI_ExtServer_{}",Id)); | 			Utils::SetThreadName(fmt::format("rest_ext_{}",Id).c_str()); | ||||||
| 	        return RESTAPI_ExtRouter(Path, Bindings, Logger(), Server_, Id); | 	        return RESTAPI_ExtRouter(Path, Bindings, Logger(), Server_, Id); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| @@ -3006,7 +3030,7 @@ namespace OpenWifi { | |||||||
| 	    inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override { | 	    inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override { | ||||||
| 			try { | 			try { | ||||||
| 				Poco::URI uri(Request.getURI()); | 				Poco::URI uri(Request.getURI()); | ||||||
| 				Poco::Thread::current()->setName(fmt::format("ExtWebServer_{}",TransactionId_)); | 				Utils::SetThreadName(fmt::format("rest_ext_{}",TransactionId_).c_str()); | ||||||
| 				return RESTAPI_ExtServer()->CallServer(uri.getPath(), TransactionId_++); | 				return RESTAPI_ExtServer()->CallServer(uri.getPath(), TransactionId_++); | ||||||
| 			} catch (...) { | 			} catch (...) { | ||||||
|  |  | ||||||
| @@ -3115,7 +3139,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	    inline Poco::Net::HTTPRequestHandler *CallServer(const std::string &Path, uint64_t Id) { | 	    inline Poco::Net::HTTPRequestHandler *CallServer(const std::string &Path, uint64_t Id) { | ||||||
| 	        RESTAPIHandler::BindingMap Bindings; | 	        RESTAPIHandler::BindingMap Bindings; | ||||||
| 			Poco::Thread::current()->setName(fmt::format("RESTAPI_IntServer_{}",Id)); | 			Utils::SetThreadName(fmt::format("rest_int_{}",Id).c_str()); | ||||||
| 	        return RESTAPI_IntRouter(Path, Bindings, Logger(), Server_, Id); | 	        return RESTAPI_IntRouter(Path, Bindings, Logger(), Server_, Id); | ||||||
| 	    } | 	    } | ||||||
| 	private: | 	private: | ||||||
| @@ -3524,7 +3548,9 @@ namespace OpenWifi { | |||||||
|     void DaemonPostInitialization(Poco::Util::Application &self); |     void DaemonPostInitialization(Poco::Util::Application &self); | ||||||
|  |  | ||||||
| 	inline void MicroService::initialize(Poco::Util::Application &self) { | 	inline void MicroService::initialize(Poco::Util::Application &self) { | ||||||
| 	    // add the default services | 		// Utils::SetThreadName("microservice"); | ||||||
|  |  | ||||||
|  | 		// add the default services | ||||||
|         LoadConfigurationFile(); |         LoadConfigurationFile(); | ||||||
|         InitializeLoggingSystem(); |         InitializeLoggingSystem(); | ||||||
|  |  | ||||||
| @@ -3919,6 +3945,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     inline int MicroService::main([[maybe_unused]] const ArgVec &args) { |     inline int MicroService::main([[maybe_unused]] const ArgVec &args) { | ||||||
|  |  | ||||||
|  | 		// Utils::SetThreadName("main"); | ||||||
| 	    MyErrorHandler	ErrorHandler(*this); | 	    MyErrorHandler	ErrorHandler(*this); | ||||||
| 	    Poco::ErrorHandler::set(&ErrorHandler); | 	    Poco::ErrorHandler::set(&ErrorHandler); | ||||||
|  |  | ||||||
| @@ -4034,6 +4061,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     inline void BusEventManager::run() { |     inline void BusEventManager::run() { | ||||||
|         Running_ = true; |         Running_ = true; | ||||||
|  | 		Utils::SetThreadName("BusEventManager"); | ||||||
|         auto Msg = MicroService::instance().MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN); |         auto Msg = MicroService::instance().MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN); | ||||||
|         KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,MicroService::instance().PrivateEndPoint(),Msg, false); |         KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,MicroService::instance().PrivateEndPoint(),Msg, false); | ||||||
|         while(Running_) { |         while(Running_) { | ||||||
| @@ -4119,6 +4147,8 @@ namespace OpenWifi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	inline void KafkaProducer::run() { | 	inline void KafkaProducer::run() { | ||||||
|  |  | ||||||
|  | 		Utils::SetThreadName("KafkaProducer"); | ||||||
| 	    cppkafka::Configuration Config({ | 	    cppkafka::Configuration Config({ | ||||||
|             { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, |             { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | ||||||
|             { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") } |             { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") } | ||||||
| @@ -4157,6 +4187,8 @@ namespace OpenWifi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	inline void KafkaConsumer::run() { | 	inline void KafkaConsumer::run() { | ||||||
|  | 		Utils::SetThreadName("KafkaConsumer"); | ||||||
|  |  | ||||||
| 	    cppkafka::Configuration Config({ | 	    cppkafka::Configuration Config({ | ||||||
| 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | ||||||
| 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") }, | 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") }, | ||||||
| @@ -4815,7 +4847,7 @@ namespace OpenWifi { | |||||||
| 		[[nodiscard]] bool SendToUser(const std::string &userName, const std::string &Payload); | 		[[nodiscard]] bool SendToUser(const std::string &userName, const std::string &Payload); | ||||||
| 		void SendToAll(const std::string &Payload); | 		void SendToAll(const std::string &Payload); | ||||||
|     private: |     private: | ||||||
|         std::atomic_bool Running_ = false; |         mutable std::atomic_bool Running_ = false; | ||||||
|         Poco::Thread Thr_; |         Poco::Thread Thr_; | ||||||
|         // std::unique_ptr<MyParallelSocketReactor> ReactorPool_; |         // std::unique_ptr<MyParallelSocketReactor> ReactorPool_; | ||||||
| 		Poco::Net::SocketReactor					Reactor_; | 		Poco::Net::SocketReactor					Reactor_; | ||||||
| @@ -4912,6 +4944,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     inline void WebSocketClientServer::run() { |     inline void WebSocketClientServer::run() { | ||||||
|         Running_ = true ; |         Running_ = true ; | ||||||
|  | 		Utils::SetThreadName("ws:clnt-svr"); | ||||||
|         while(Running_) { |         while(Running_) { | ||||||
|             Poco::Thread::trySleep(2000); |             Poco::Thread::trySleep(2000); | ||||||
|  |  | ||||||
| @@ -4959,8 +4992,12 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|         for(const auto &client:Clients_) { |         for(const auto &client:Clients_) { | ||||||
|             if(client.second.second == UserName) { |             if(client.second.second == UserName) { | ||||||
|                 if(client.second.first->Send(Payload)) | 				try { | ||||||
|                     Sent++; | 					if (client.second.first->Send(Payload)) | ||||||
|  | 						Sent++; | ||||||
|  | 				} catch (...) { | ||||||
|  | 					return false; | ||||||
|  | 				} | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         return Sent>0; |         return Sent>0; | ||||||
| @@ -4982,70 +5019,70 @@ namespace OpenWifi { | |||||||
|         int flags; |         int flags; | ||||||
|         int n; |         int n; | ||||||
|         bool Done=false; |         bool Done=false; | ||||||
|         Poco::Buffer<char>			IncomingFrame(0); | 		try { | ||||||
|         n = WS_->receiveFrame(IncomingFrame, flags); | 			Poco::Buffer<char> IncomingFrame(0); | ||||||
|         auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; | 			n = WS_->receiveFrame(IncomingFrame, flags); | ||||||
|  | 			auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; | ||||||
|  |  | ||||||
|         if(n==0) { | 			if (n == 0) { | ||||||
|             return delete this; | 				return delete this; | ||||||
|         } | 			} | ||||||
|  |  | ||||||
|         switch(Op) { | 			switch (Op) { | ||||||
|             case Poco::Net::WebSocket::FRAME_OP_PING: { | 			case Poco::Net::WebSocket::FRAME_OP_PING: { | ||||||
|                 WS_->sendFrame("", 0, | 				WS_->sendFrame("", 0, | ||||||
|                                (int)Poco::Net::WebSocket::FRAME_OP_PONG | | 							   (int)Poco::Net::WebSocket::FRAME_OP_PONG | | ||||||
|                                (int)Poco::Net::WebSocket::FRAME_FLAG_FIN); | 								   (int)Poco::Net::WebSocket::FRAME_FLAG_FIN); | ||||||
|             } | 			} break; | ||||||
|                 break; | 			case Poco::Net::WebSocket::FRAME_OP_PONG: { | ||||||
|             case Poco::Net::WebSocket::FRAME_OP_PONG: { | 			} break; | ||||||
|             } | 			case Poco::Net::WebSocket::FRAME_OP_CLOSE: { | ||||||
|                 break; | 				Logger().warning(Poco::format("CLOSE(%s): Client is closing its connection.", Id_)); | ||||||
|             case Poco::Net::WebSocket::FRAME_OP_CLOSE: { | 				Done = true; | ||||||
|                 Logger().warning(Poco::format("CLOSE(%s): Client is closing its connection.",Id_)); | 			} break; | ||||||
|                 Done=true; | 			case Poco::Net::WebSocket::FRAME_OP_TEXT: { | ||||||
|             } | 				IncomingFrame.append(0); | ||||||
|                 break; | 				if (!Authenticated_) { | ||||||
|             case Poco::Net::WebSocket::FRAME_OP_TEXT: { | 					std::string Frame{IncomingFrame.begin()}; | ||||||
|                 IncomingFrame.append(0); | 					auto Tokens = Utils::Split(Frame, ':'); | ||||||
|                 if(!Authenticated_) { | 					bool Expired = false, Contacted = false; | ||||||
|                     std::string Frame{IncomingFrame.begin()}; | 					if (Tokens.size() == 2 && | ||||||
|                     auto Tokens = Utils::Split(Frame,':'); | 						AuthClient()->IsAuthorized(Tokens[1], UserInfo_, Expired, Contacted)) { | ||||||
|                     bool Expired = false, Contacted = false; | 						Authenticated_ = true; | ||||||
|                     if(Tokens.size()==2 && AuthClient()->IsAuthorized(Tokens[1], UserInfo_, Expired, Contacted)) { | 						std::string S{"Welcome! Bienvenue! Bienvenidos!"}; | ||||||
|                         Authenticated_=true; | 						WS_->sendFrame(S.c_str(), S.size()); | ||||||
|                         std::string S{"Welcome! Bienvenue! Bienvenidos!"}; | 						WebSocketClientServer()->SetUser(Id_, UserInfo_.userinfo.email); | ||||||
|                         WS_->sendFrame(S.c_str(),S.size()); | 					} else { | ||||||
|                         WebSocketClientServer()->SetUser(Id_,UserInfo_.userinfo.email); | 						std::string S{"Invalid token. Closing connection."}; | ||||||
|                     } else { | 						WS_->sendFrame(S.c_str(), S.size()); | ||||||
|                         std::string S{"Invalid token. Closing connection."}; | 						Done = true; | ||||||
|                         WS_->sendFrame(S.c_str(),S.size()); | 					} | ||||||
|                         Done=true; |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                 } else { | 				} else { | ||||||
|                     try { | 					try { | ||||||
|                         Poco::JSON::Parser P; | 						Poco::JSON::Parser P; | ||||||
|                         auto Obj = P.parse(IncomingFrame.begin()) | 						auto Obj = | ||||||
|                                 .extract<Poco::JSON::Object::Ptr>(); | 							P.parse(IncomingFrame.begin()).extract<Poco::JSON::Object::Ptr>(); | ||||||
|                         std::string Answer; | 						std::string Answer; | ||||||
|                         if(Processor_!= nullptr) | 						if (Processor_ != nullptr) | ||||||
|                             Processor_->Processor(Obj, Answer, Done); | 							Processor_->Processor(Obj, Answer, Done); | ||||||
|                         if (!Answer.empty()) | 						if (!Answer.empty()) | ||||||
|                             WS_->sendFrame(Answer.c_str(), (int) Answer.size()); | 							WS_->sendFrame(Answer.c_str(), (int)Answer.size()); | ||||||
|                         else { | 						else { | ||||||
|                             WS_->sendFrame("{}", 2); | 							WS_->sendFrame("{}", 2); | ||||||
|                         } | 						} | ||||||
|                     } catch (const Poco::JSON::JSONException & E) { | 					} catch (const Poco::JSON::JSONException &E) { | ||||||
|                         Logger().log(E); | 						Logger().log(E); | ||||||
|                     } | 						Done=true; | ||||||
|                 } | 					} | ||||||
|             } | 				} | ||||||
|                 break; | 			} break; | ||||||
|             default: | 			default: { | ||||||
|             { | 			} | ||||||
|  | 			} | ||||||
|             } | 		} catch (...) { | ||||||
|         } | 			Done=true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|         if(Done) { |         if(Done) { | ||||||
|             delete this; |             delete this; | ||||||
|   | |||||||
| @@ -133,6 +133,37 @@ namespace ORM { | |||||||
|         return R; |         return R; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     inline std::string WHERE_AND_(std::string Result) { | ||||||
|  |         return Result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename T, typename... Args> std::string WHERE_AND_(std::string Result, const char *fieldName, const T &Value, Args... args) { | ||||||
|  |         if constexpr(std::is_same_v<T,std::string>) | ||||||
|  |         { | ||||||
|  |             if(!Value.empty()) { | ||||||
|  |                 if(!Result.empty()) | ||||||
|  |                     Result += " and "; | ||||||
|  |                 Result += fieldName; | ||||||
|  |                 Result += '='; | ||||||
|  |                 Result += "'"; | ||||||
|  |                 Result += Escape(Value); | ||||||
|  |                 Result += "'"; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             if(!Result.empty()) | ||||||
|  |                 Result += " and "; | ||||||
|  |             Result += fieldName ; | ||||||
|  |             Result += '='; | ||||||
|  |             Result += std::to_string(Value); | ||||||
|  |         } | ||||||
|  |         return WHERE_AND_(Result,args...); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename... Args> std::string WHERE_AND(Args... args) { | ||||||
|  |         std::string Result; | ||||||
|  |         return WHERE_AND_(Result, args...); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     enum SqlComparison { EQ = 0, NEQ, LT, LTE, GT, GTE }; |     enum SqlComparison { EQ = 0, NEQ, LT, LTE, GT, GTE }; | ||||||
|     enum SqlBinaryOp { AND = 0 , OR }; |     enum SqlBinaryOp { AND = 0 , OR }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -96,40 +96,42 @@ namespace OpenWifi { | |||||||
|     void EntityDB::AddVenues(Poco::JSON::Object &Tree, const std::string & Node) { |     void EntityDB::AddVenues(Poco::JSON::Object &Tree, const std::string & Node) { | ||||||
|         ProvObjects::Venue E; |         ProvObjects::Venue E; | ||||||
|         // std::cout << "Adding venue:" << Node << std::endl; |         // std::cout << "Adding venue:" << Node << std::endl; | ||||||
|         StorageService()->VenueDB().GetRecord("id",Node,E); |         if(StorageService()->VenueDB().GetRecord("id",Node,E)) { | ||||||
|         Poco::JSON::Array   Venues; |             Poco::JSON::Array Venues; | ||||||
|         for(const auto &i:E.children) { |             for (const auto &i: E.children) { | ||||||
|             Poco::JSON::Object Venue; |                 Poco::JSON::Object Venue; | ||||||
|             AddVenues(Venue, i); |                 AddVenues(Venue, i); | ||||||
|             Venues.add(Venue); |                 Venues.add(Venue); | ||||||
|  |             } | ||||||
|  |             Tree.set("type", "venue"); | ||||||
|  |             Tree.set("name", E.info.name); | ||||||
|  |             Tree.set("uuid", E.info.id); | ||||||
|  |             Tree.set("children", Venues); | ||||||
|         } |         } | ||||||
|         Tree.set("type","venue"); |  | ||||||
|         Tree.set("name",E.info.name); |  | ||||||
|         Tree.set("uuid",E.info.id); |  | ||||||
|         Tree.set("children",Venues); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void EntityDB::BuildTree(Poco::JSON::Object &Tree, const std::string & Node) { |     void EntityDB::BuildTree(Poco::JSON::Object &Tree, const std::string & Node) { | ||||||
|         ProvObjects::Entity E; |         ProvObjects::Entity E; | ||||||
|         // std::cout << "Adding node:" << Node << std::endl; |         // std::cout << "Adding node:" << Node << std::endl; | ||||||
|         StorageService()->EntityDB().GetRecord("id",Node,E); |         if(StorageService()->EntityDB().GetRecord("id",Node,E)) { | ||||||
|         Poco::JSON::Array   Children; |             Poco::JSON::Array Children; | ||||||
|         for(const auto &i:E.children) { |             for (const auto &i: E.children) { | ||||||
|             Poco::JSON::Object  Child; |                 Poco::JSON::Object Child; | ||||||
|             BuildTree(Child,i); |                 BuildTree(Child, i); | ||||||
|             Children.add(Child); |                 Children.add(Child); | ||||||
|  |             } | ||||||
|  |             Poco::JSON::Array Venues; | ||||||
|  |             for (const auto &i: E.venues) { | ||||||
|  |                 Poco::JSON::Object Venue; | ||||||
|  |                 AddVenues(Venue, i); | ||||||
|  |                 Venues.add(Venue); | ||||||
|  |             } | ||||||
|  |             Tree.set("type", "entity"); | ||||||
|  |             Tree.set("name", E.info.name); | ||||||
|  |             Tree.set("uuid", E.info.id); | ||||||
|  |             Tree.set("children", Children); | ||||||
|  |             Tree.set("venues", Venues); | ||||||
|         } |         } | ||||||
|         Poco::JSON::Array   Venues; |  | ||||||
|         for(const auto &i:E.venues) { |  | ||||||
|             Poco::JSON::Object Venue; |  | ||||||
|             AddVenues(Venue, i); |  | ||||||
|             Venues.add(Venue); |  | ||||||
|         } |  | ||||||
|         Tree.set("type","entity"); |  | ||||||
|         Tree.set("name",E.info.name); |  | ||||||
|         Tree.set("uuid",E.info.id); |  | ||||||
|         Tree.set("children",Children); |  | ||||||
|         Tree.set("venues", Venues); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void EntityDB::ImportVenues(const Poco::JSON::Object::Ptr &O, const std::string &Parent) { |     void EntityDB::ImportVenues(const Poco::JSON::Object::Ptr &O, const std::string &Parent) { | ||||||
|   | |||||||
| @@ -1,51 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-10-28. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #include "storage_jobs.h" |  | ||||||
| #include "framework/OpenWifiTypes.h" |  | ||||||
| #include "framework/MicroService.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|  |  | ||||||
|     static  ORM::FieldVec    JobDB_Fields{ |  | ||||||
|         // object info |  | ||||||
|         ORM::Field{"id",64, true}, |  | ||||||
|         ORM::Field{"name",ORM::FieldType::FT_TEXT}, |  | ||||||
|         ORM::Field{"description",ORM::FieldType::FT_TEXT}, |  | ||||||
|         ORM::Field{"type",ORM::FieldType::FT_TEXT}, |  | ||||||
|         ORM::Field{"progress",ORM::FieldType::FT_BIGINT}, |  | ||||||
|         ORM::Field{"total",ORM::FieldType::FT_BIGINT}, |  | ||||||
|         ORM::Field{"parameters",ORM::FieldType::FT_TEXT} |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     static  ORM::IndexVec    JobDB_Indexes{ |  | ||||||
|         { std::string("job_name_index"), |  | ||||||
|           ORM::IndexEntryVec{ |  | ||||||
|             {std::string("name"), |  | ||||||
|              ORM::Indextype::ASC} } } |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     JobDB::JobDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) : |  | ||||||
|     DB(T, "jobs", JobDB_Fields, JobDB_Indexes, P, L, "job") {} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template<> void ORM::DB<OpenWifi::JobDBRecordType, OpenWifi::JobRecord>::Convert(const OpenWifi::JobDBRecordType &In, OpenWifi::JobRecord &Out) { |  | ||||||
|     Out.id = In.get<0>(); |  | ||||||
|     Out.name = In.get<1>(); |  | ||||||
|     Out.description = In.get<2>(); |  | ||||||
|     Out.type = In.get<3>(); |  | ||||||
|     Out.progress = In.get<4>(); |  | ||||||
|     Out.total = In.get<5>(); |  | ||||||
|     Out.parameters = OpenWifi::RESTAPI_utils::to_array_of_array_of_object<OpenWifi::Job::Parameter>(In.get<3>()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template<> void ORM::DB<OpenWifi::JobDBRecordType, OpenWifi::JobRecord>::Convert(const OpenWifi::JobRecord &In, OpenWifi::JobDBRecordType &Out) { |  | ||||||
|     Out.set<0>(In.id); |  | ||||||
|     Out.set<1>(In.name); |  | ||||||
|     Out.set<2>(In.description); |  | ||||||
|     Out.set<3>(In.type); |  | ||||||
|     Out.set<4>(In.progress); |  | ||||||
|     Out.set<5>(In.total); |  | ||||||
|     Out.set<6>(OpenWifi::RESTAPI_utils::to_string(In.parameters)); |  | ||||||
| } |  | ||||||
| @@ -1,40 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-10-28. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include "framework/orm.h" |  | ||||||
| #include "JobController.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|     typedef Poco::Tuple< |  | ||||||
|         std::string, |  | ||||||
|         std::string, |  | ||||||
|         std::string, |  | ||||||
|         std::string, |  | ||||||
|         uint64_t, |  | ||||||
|         uint64_t, |  | ||||||
|         std::string |  | ||||||
|     > JobDBRecordType; |  | ||||||
|  |  | ||||||
|     struct JobRecord { |  | ||||||
|         Types::UUID_t       id; |  | ||||||
|         std::string         name; |  | ||||||
|         std::string         description; |  | ||||||
|         std::string         type; |  | ||||||
|         uint64_t            progress; |  | ||||||
|         uint64_t            total; |  | ||||||
|         Job::ParametersVec  parameters; |  | ||||||
|  |  | ||||||
|         // void from_string(const std::string &S); |  | ||||||
|         // std::string to_string() const; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     class JobDB : public ORM::DB<JobDBRecordType, JobRecord> { |  | ||||||
|     public: |  | ||||||
|         JobDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); |  | ||||||
|         virtual ~JobDB() {}; |  | ||||||
|     private: |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
		Reference in New Issue
	
	Block a user