From 5df09fe5c3afb4d31fe0773b9075a6ec7556971d Mon Sep 17 00:00:00 2001 From: pronoob Date: Fri, 9 Sep 2022 13:31:20 +0530 Subject: [PATCH 01/48] fixed system tests (#814) Fixed system tests for authentication. FOGL-6894. --- tests/system/python/api/test_authentication.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/system/python/api/test_authentication.py b/tests/system/python/api/test_authentication.py index 7a172e264f..338d8effb1 100644 --- a/tests/system/python/api/test_authentication.py +++ b/tests/system/python/api/test_authentication.py @@ -53,7 +53,7 @@ def test_login_username_regular_user(self, change_to_auth_mandatory, fledge_url, assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert "Logged in successfully." == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] global TOKEN @@ -75,7 +75,7 @@ def test_login_username_admin(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert "Logged in successfully." == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] global TOKEN @@ -302,7 +302,7 @@ def test_login_with_user_certificate(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert "Logged in successfully." == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] @@ -315,7 +315,7 @@ def test_login_with_admin_certificate(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert "Logged in successfully." == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] @@ -337,7 +337,7 @@ def test_login_with_custom_certificate(self, fledge_url, remove_data_file): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert "Logged in successfully." == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] From 2518b11581fd726b3c133ee524df531de688c699 Mon Sep 17 00:00:00 2001 From: Innovative-ashwin <99904321+Innovative-ashwin@users.noreply.github.com> Date: Fri, 9 Sep 2022 16:14:18 +0530 Subject: [PATCH 02/48] Fogl 6744 storage asset tracker (#809) * Code to implement storage asset tracker Signed-off-by: Innovative-ashwin * Removed unwanted logs and added code for empty data column check Signed-off-by: Innovative-ashwin * Removed unused functions from storageAssetTracker class Signed-off-by: Innovative-ashwin * improved the logs Signed-off-by: Innovative-ashwin * added upgrade and downgrade files for postgres nd sqlitelb Signed-off-by: Innovative-ashwin * Added comments and removed extra newlines Signed-off-by: Innovative-ashwin * modified the license stuff Signed-off-by: Innovative-ashwin * removed commented code Signed-off-by: Innovative-ashwin * fixed python unit tests Signed-off-by: Innovative-ashwin * Fogl 6745. Added API endpoint for getting datapoint usage. (#771) Fogl 6745. Added API endpoint for getting datapoint usage. * improved the logging Signed-off-by: Innovative-ashwin * modified __FILE__ to __FUNCTION__ in logging Signed-off-by: Innovative-ashwin * changed the ___FILE__ macro to ___FUNCTION__ Signed-off-by: Innovative-ashwin * changed ==None to is None Signed-off-by: Innovative-ashwin * improved logs Signed-off-by: Innovative-ashwin * added code for storage_asset_tracking Signed-off-by: Innovative-ashwin * improved logs Signed-off-by: Innovative-ashwin * fixed code review comments regarding putting quotes in ingest Signed-off-by: Innovative-ashwin * fixed code review comment Signed-off-by: Innovative-ashwin * added comparator for set of iterators Signed-off-by: Innovative-ashwin * filter out extra data points and take only maximum data points. Signed-off-by: Deepanshu Yadav * fixed the code. Signed-off-by: Deepanshu Yadav * reduce variable usage Signed-off-by: Deepanshu Yadav Signed-off-by: Innovative-ashwin Signed-off-by: Deepanshu Yadav Co-authored-by: pronoob --- C/common/include/management_client.h | 19 +- C/common/include/storage_asset_tracking.h | 127 ++++++ C/common/management_client.cpp | 417 ++++++++++++++++++ C/common/storage_asset_tracking.cpp | 321 ++++++++++++++ C/services/south/include/ingest.h | 3 + C/services/south/include/south_service.h | 3 + C/services/south/ingest.cpp | 258 ++++++++++- C/services/south/south.cpp | 5 + VERSION | 2 +- .../fledge/services/core/api/asset_tracker.py | 98 +++- .../core/asset_tracker/asset_tracker.py | 9 +- python/fledge/services/core/routes.py | 1 + python/fledge/services/core/server.py | 21 +- .../plugins/storage/postgres/downgrade/56.sql | 2 + .../plugins/storage/postgres/upgrade/57.sql | 3 + .../plugins/storage/sqlite/downgrade/56.sql | 36 ++ scripts/plugins/storage/sqlite/init.sql | 3 +- scripts/plugins/storage/sqlite/upgrade/57.sql | 37 ++ .../plugins/storage/sqlitelb/downgrade/56.sql | 36 ++ .../plugins/storage/sqlitelb/upgrade/57.sql | 37 ++ .../core/api/test_asset_tracker_api.py | 6 +- .../core/asset_tracker/test_asset_tracker.py | 8 +- 22 files changed, 1422 insertions(+), 30 deletions(-) create mode 100644 C/common/include/storage_asset_tracking.h create mode 100644 C/common/storage_asset_tracking.cpp create mode 100644 scripts/plugins/storage/postgres/downgrade/56.sql create mode 100644 scripts/plugins/storage/postgres/upgrade/57.sql create mode 100644 scripts/plugins/storage/sqlite/downgrade/56.sql create mode 100644 scripts/plugins/storage/sqlite/upgrade/57.sql create mode 100644 scripts/plugins/storage/sqlitelb/downgrade/56.sql create mode 100644 scripts/plugins/storage/sqlitelb/upgrade/57.sql diff --git a/C/common/include/management_client.h b/C/common/include/management_client.h index 48c315daf5..86cd530f37 100644 --- a/C/common/include/management_client.h +++ b/C/common/include/management_client.h @@ -30,6 +30,7 @@ using HttpServer = SimpleWeb::Server; using namespace rapidjson; class AssetTrackingTuple; +class StorageAssetTrackingTuple; /** * The management client class used by services and tasks to communicate @@ -60,10 +61,25 @@ class ManagementClient { const std::vector& children); std::vector& getAssetTrackingTuples(const std::string serviceName = ""); + std::vector& + getStorageAssetTrackingTuples(const std::string serviceName); + + StorageAssetTrackingTuple* getStorageAssetTrackingTuple(const std::string& serviceName, + const std::string& assetName, + const std::string& event, const std::string & dp, const unsigned int& c); + bool addAssetTrackingTuple(const std::string& service, const std::string& plugin, const std::string& asset, const std::string& event); + + bool addStorageAssetTrackingTuple(const std::string& service, + const std::string& plugin, + const std::string& asset, + const std::string& event, + const bool& deprecated = false, + const std::string& datapoints = "", + const int& count = 0); ConfigCategories getChildCategories(const std::string& categoryName); HttpClient *getHttpClient(); bool addAuditEntry(const std::string& serviceName, @@ -94,10 +110,11 @@ class ManagementClient { std::vector > >& endpoints); bool deleteProxy(const std::string& serviceName); const std::string getUrlbase() { return m_urlbase.str(); } - ACL getACL(const std::string& aclName); + ACL getACL(const std::string& aclName); AssetTrackingTuple* getAssetTrackingTuple(const std::string& serviceName, const std::string& assetName, const std::string& event); + int validateDatapoints(std::string dp1, std::string dp2); private: std::ostringstream m_urlbase; diff --git a/C/common/include/storage_asset_tracking.h b/C/common/include/storage_asset_tracking.h new file mode 100644 index 0000000000..32c7d2d8fe --- /dev/null +++ b/C/common/include/storage_asset_tracking.h @@ -0,0 +1,127 @@ +#ifndef _STORAGE_ASSET_TRACKING_H +#define _STORAGE_ASSET_TRACKING_H +/* + * Fledge storage asset tracking related + * + * Copyright (c) 2022 Dianomic Systems + * + * Released under the Apache 2.0 Licence + * + * Author: Ashwini Sinha + */ +#include +#include +#include +#include +#include +#include +#include + + +/** + * The StorageAssetTrackingTuple class is used to represent ai storage asset + * tracking tuple. Hash function and '==' operator are defined for + * this class and pointer to this class that would be required + * to create an unordered_set of this class. + */ + +class StorageAssetTrackingTuple : public AssetTrackingTuple { + +public: + std::string m_datapoints; + unsigned int m_maxCount; + + std::string assetToString() + { + std::ostringstream o; + o << AssetTrackingTuple::assetToString() << ", m_datapoints:" << m_datapoints << ", m_maxCount:" << m_maxCount; + return o.str(); + } + + unsigned int getMaxCount() { return m_maxCount; } + std::string getDataPoints() { return m_datapoints; } + + StorageAssetTrackingTuple(const std::string& service, + const std::string& plugin, + const std::string& asset, + const std::string& event, + const bool& deprecated = false, + const std::string& datapoints = "", + unsigned int c = 0) : + AssetTrackingTuple(service, plugin, asset, event, deprecated), m_datapoints(datapoints), m_maxCount(c) + {} + +private: +}; + +struct StorageAssetTrackingTuplePtrEqual { + bool operator()(StorageAssetTrackingTuple const* a, StorageAssetTrackingTuple const* b) const { + return *a == *b; + } +}; + +namespace std +{ + template <> + struct hash + { + size_t operator()(const StorageAssetTrackingTuple& t) const + { + return (std::hash()(t.m_serviceName + t.m_pluginName + t.m_assetName + t.m_eventName)); + } + }; + + template <> + struct hash + { + size_t operator()(StorageAssetTrackingTuple* t) const + { + return (std::hash()(t->m_serviceName + t->m_pluginName + t->m_assetName + t->m_eventName)); + } + }; +} + +class ManagementClient; + +typedef std::unordered_multiset, StorageAssetTrackingTuplePtrEqual> StorageAssetCacheSet; + +typedef std::unordered_multiset, StorageAssetTrackingTuplePtrEqual>::iterator StorageAssetCacheSetItr; + +struct StorageAssetCacheSetItrCmp{ + + bool operator ()(StorageAssetCacheSetItr x, StorageAssetCacheSetItr y) + { + return x != y; + } + +}; +/** + * The StorageAssetTracker class provides the asset tracking functionality. + * There are methods to populate asset tracking cache from asset_tracker DB table, + * and methods to check/add asset tracking tuples to DB and to cache + */ +class StorageAssetTracker { + +public: + StorageAssetTracker(ManagementClient *mgtClient, std::string m_service); + ~StorageAssetTracker() {} + void populateStorageAssetTrackingCache(); + StorageAssetTrackingTuple* + findStorageAssetTrackingCache(StorageAssetTrackingTuple& tuple); + void addStorageAssetTrackingTuple(StorageAssetTrackingTuple& tuple); + bool getFledgeConfigInfo(); + static StorageAssetTracker *getStorageAssetTracker(); + static void releaseStorageAssetTracker(); + int compareDatapoints(const std::string& dp1, const std::string& dp2); + +private: + static StorageAssetTracker *instance; + ManagementClient *m_mgtClient; + std::string m_fledgeService; + std::string m_service; + std::string m_event; + + StorageAssetCacheSet storageAssetTrackerTuplesCache; +}; + +#endif diff --git a/C/common/management_client.cpp b/C/common/management_client.cpp index 4ed71a34bb..f719616210 100644 --- a/C/common/management_client.cpp +++ b/C/common/management_client.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -1540,3 +1541,419 @@ ACL ManagementClient::getACL(const string& aclName) throw; } } + +/** + * Get the asset tracking tuple + * for a service and asset name + * + * @param serviceName The serviceName to restrict data fetch + * @param assetName The asset name that belongs to the service + * @param event The associated event type + * @param dp The datapoints Type + * @param c The count of datapoints + * @return A pointer to AssetTrackingTuple objects allocated on heap + */ +StorageAssetTrackingTuple* ManagementClient::getStorageAssetTrackingTuple(const std::string& serviceName, + const std::string& assetName, + const std::string& event, const std::string& dp, const unsigned int& c) +{ + + StorageAssetTrackingTuple* tuple = NULL; + try { + string url = "/fledge/track"; + if (serviceName == "" || assetName == "" || event == "") + { + m_logger->error("Failed to fetch storage asset tracking tuple: " \ + "service name, asset name and event type are required."); + throw new exception(); + } + + url += "?service=" + urlEncode(serviceName); + url += "&asset=" + urlEncode(assetName) + "&event=" + event; + + auto res = this->getHttpClient()->request("GET", url.c_str()); + Document doc; + string response = res->content.string(); + doc.Parse(response.c_str()); + if (doc.HasParseError()) + { + bool httpError = (isdigit(response[0]) && + isdigit(response[1]) && + isdigit(response[2]) && + response[3]==':'); + m_logger->error("%s fetch storage asset tracking tuple: %s\n", + httpError?"HTTP error during":"Failed to parse result of", + response.c_str()); + throw new exception(); + } + else if (doc.HasMember("message")) + { + m_logger->error("Failed to fetch storage asset tracking tuple: %s.", + doc["message"].GetString()); + throw new exception(); + } + else + { + const rapidjson::Value& trackArray = doc["track"]; + if (trackArray.IsArray()) + { + // Process every row and create the AssetTrackingTuple object + for (auto& rec : trackArray.GetArray()) + { + m_logger->debug("%s:%d Inside for loop of trackArray ", __FUNCTION__, __LINE__); + + if (!rec.IsObject()) + { + throw runtime_error("Expected storage asset tracker tuple to be an object"); + } + + // Note: deprecatedTimestamp NULL value is returned as "" + // otherwise it's a string DATE + bool deprecated = rec.HasMember("deprecatedTimestamp") && + strlen(rec["deprecatedTimestamp"].GetString()); + + std::string data ; + if (!rec.HasMember("data")) + { + throw runtime_error("Expected storage asset tracker tuple to contain member data"); + } + + const rapidjson::Value& dataVal = rec["data"]; + if (!dataVal.IsObject()) + { + throw runtime_error("Expected data in storage asset tracker tuple to be an object"); + } + + if (!dataVal.HasMember("datapoints")) + { + throw runtime_error("Expected asset tracker tuple to contain datapoints"); + } + + if (dataVal.ObjectEmpty()) + { + m_logger->error("%s:%d dataVal Object empty " , __FUNCTION__, __LINE__); + continue; + } + + if (!dataVal["datapoints"].IsArray()) + { + throw runtime_error("Expected datapoints to be object"); + } + + std::string datapoints; + for (auto& r : dataVal["datapoints"].GetArray()) + { + if (!r.IsString()) + { + throw runtime_error("Expected r to be string"); + } + else + { + datapoints.append(r.GetString()); + datapoints.append(","); + } + } + + + if (datapoints[datapoints.size()-1] == ',') + { + datapoints.pop_back(); + } + + if(validateDatapoints(dp,datapoints)) + { + //datapoints in db not same as in arg, continue + m_logger->debug("%s:%d :Datapoints in db not same as in arg",__FUNCTION__, __LINE__); + continue; + } + + if (!dataVal.HasMember("count")) + { + throw runtime_error("Expected asset tracker tuple to contain count"); + } + + if (!dataVal["count"].IsInt()) + { + throw runtime_error("Expected count in data to be int"); + } + int count = dataVal["count"].GetInt(); + if ( count != c) + { + // count not same, continue + m_logger->debug("%s:%d :count in db not same as received in arg", __FUNCTION__, __LINE__); + continue; + } + + // Create a new AssetTrackingTuple object, to be freed by the caller + tuple = new StorageAssetTrackingTuple(rec["service"].GetString(), + rec["plugin"].GetString(), + rec["asset"].GetString(), + rec["event"].GetString(), + deprecated, datapoints, count); + + m_logger->debug("%s:%d : Adding StorageAssetTracker tuple for service %s: %s:%s:%s, " \ + "deprecated state is %d, datapoints %s , count %d",__FUNCTION__, __LINE__, + rec["service"].GetString(), + rec["plugin"].GetString(), + rec["asset"].GetString(), + rec["event"].GetString(), + deprecated, datapoints.c_str(), count); + + + } + } + else + { + throw runtime_error("Expected array of rows in storage asset track tuples array"); + } + + return tuple; + } + } catch (const SimpleWeb::system_error &e) { + m_logger->error("Fetch/parse of storage asset tracking tuples for service %s failed: %s.", + serviceName.c_str(), + e.what()); + } catch (...) { + m_logger->error("Unexpected exception when retrieving storage asset tuples for service %s", + serviceName.c_str()); + } + + return tuple; +} + +/** + * Add a new asset tracking tuple + * + * @param service Service name + * @param plugin Plugin name + * @param asset Asset name + * @param event Event type + * @param deprecated Deprecated or not + * @param datapoints Datapoints type + * @param count Count Type + * @return whether operation was successful + */ +bool ManagementClient::addStorageAssetTrackingTuple(const std::string& service, + const std::string& plugin, + const std::string& asset, + const std::string& event, + const bool& deprecated, + const std::string& datapoints, + const int& count) +{ + ostringstream convert; + + std::string d = datapoints; + for ( int i = 0; i < datapoints.size(); ++i) + { + if (d[i] == ',') d.insert(i, "\",\"" ); + i = i+2; + } + + try { + convert << "{ \"service\" : \"" << JSONescape(service) << "\", "; + convert << " \"plugin\" : \"" << plugin << "\", "; + convert << " \"asset\" : \"" << asset << "\", "; + convert << " \"event\" : \"" << event << "\", "; + convert << " \"deprecated\" :\"" << deprecated << "\", "; + convert << " \"data\" : { \"datapoints\" : \[ \"" << d << "\" \], "; + convert << " \"count\" : " << count << " } }"; + + auto res = this->getHttpClient()->request("POST", "/fledge/track", convert.str()); + Document doc; + string content = res->content.string(); + doc.Parse(content.c_str()); + if (doc.HasParseError()) + { + bool httpError = (isdigit(content[0]) && isdigit(content[1]) && isdigit(content[2]) && content[3]==':'); + m_logger->error("%s:%d , %s storage asset tracking tuple addition: %s\n",__FUNCTION__, __LINE__, + httpError?"HTTP error during":"Failed to parse result of", + content.c_str()); + return false; + } + if (doc.HasMember("fledge")) + { + const char *reg_id = doc["fledge"].GetString(); + return true; + } + else if (doc.HasMember("message")) + { + m_logger->error("%s:%d Failed to add storage asset tracking tuple: %s.",__FUNCTION__, __LINE__, + doc["message"].GetString()); + } + else + { + m_logger->error("%s:%d Failed to add storage asset tracking tuple: %s.",__FUNCTION__, __LINE__, + content.c_str()); + } + } catch (const SimpleWeb::system_error &e) { + m_logger->error("%s:%d Failed to add storage asset tracking tuple: %s.",__FUNCTION__, __LINE__, e.what()); + return false; + } + return false; +} + +/** + * Get the storage asset tracking tuples + * for a service or all services + * + * @param serviceName The serviceName to restrict data fetch + * If empty records for all services are fetched + * @return A vector of pointers to AssetTrackingTuple objects allocated on heap + */ +std::vector& ManagementClient::getStorageAssetTrackingTuples(const std::string serviceName) +{ + std::vector *vec = new std::vector(); + + try { + string url = "/fledge/track"; + if (serviceName != "") + { + url += "?service="+urlEncode(serviceName); + } + auto res = this->getHttpClient()->request("GET", url.c_str()); + Document doc; + string response = res->content.string(); + doc.Parse(response.c_str()); + if (doc.HasParseError()) + { + bool httpError = (isdigit(response[0]) && isdigit(response[1]) && isdigit(response[2]) && response[3]==':'); + m_logger->error("%s fetch asset tracking tuples: %s\n", + httpError?"HTTP error during":"Failed to parse result of", + response.c_str()); + throw new exception(); + } + else if (doc.HasMember("message")) + { + m_logger->error("Failed to fetch asset tracking tuples: %s.", + doc["message"].GetString()); + throw new exception(); + } + else + { + const rapidjson::Value& trackArray = doc["track"]; + if (trackArray.IsArray()) + { + // Process every row and create the AssetTrackingTuple object + for (auto& rec : trackArray.GetArray()) + { + if (!rec.IsObject()) + { + throw runtime_error("Expected asset tracker tuple to be an object"); + } + + // Note: deprecatedTimestamp NULL value is returned as "" + // otherwise it's a string DATE + bool deprecated = rec.HasMember("deprecatedTimestamp") && + strlen(rec["deprecatedTimestamp"].GetString()); + + std::string data ; + if (!rec.HasMember("data")) + { + throw runtime_error("Expected asset tracker tuple to contain member data"); + } + + const rapidjson::Value& dataVal = rec["data"]; + if (!dataVal.IsObject()) + { + throw runtime_error("Expected data asset tracker tuple to be an object"); + } + + if (dataVal.ObjectEmpty()) + { + m_logger->debug("%s:%d dataVal Object empty " , __FUNCTION__, __LINE__); + continue; + } + + if (!dataVal.HasMember("datapoints")) + { + throw runtime_error("Expected asset tracker tuple to contain datapoints"); + } + + if (!dataVal["datapoints"].IsArray()) + { + throw runtime_error("Expected datapoints to be array"); + } + + std::string datapoints; + for (auto& r : dataVal["datapoints"].GetArray()) + { + if (!r.IsString()) + { + throw runtime_error("Expected individual datapoints in datapoints array to be string"); + } + else + { + datapoints.append(r.GetString()); + datapoints.append(","); + } + } + + if( datapoints[datapoints.size()-1] == ',') + { + datapoints.pop_back(); + } + + if (!dataVal.HasMember("count")) + { + throw runtime_error("Expected asset tracker tuple to contain count"); + } + + if (!dataVal["count"].IsInt()) + { + throw runtime_error("Expected count in data to be int"); + } + int count = dataVal["count"].GetInt(); + m_logger->debug("%s:%d count = %d ", __FUNCTION__, __LINE__, count); + + StorageAssetTrackingTuple *tuple = new StorageAssetTrackingTuple(rec["service"].GetString(), + rec["plugin"].GetString(), + rec["asset"].GetString(), + rec["event"].GetString(), + deprecated, datapoints, count); + + m_logger->debug("%s:%d: Adding StorageAssetTracker tuple for service %s: %s:%s:%s, " \ + "deprecated state is %d, datapoints %s , count %d" ,__FUNCTION__, __LINE__, + rec["service"].GetString(), + rec["plugin"].GetString(), + rec["asset"].GetString(), + rec["event"].GetString(), + deprecated, datapoints.c_str(), count); + vec->push_back(tuple); + } + } + else + { + throw runtime_error("Expected array of rows in asset track tuples array"); + } + + return (*vec); + } + } catch (const SimpleWeb::system_error &e) { + m_logger->error("Fetch/parse of asset tracking tuples for service %s failed: %s.", serviceName.c_str(), e.what()); + } + catch (...) { + m_logger->error("Unexpected exception when retrieving asset tuples for service %s", serviceName.c_str()); + } + return *vec; +} + +/** + * Compare the datapoints to be equal or not, they can be '"' enclosed + * + * @param dp1 The datapoint to compare, enclosed in '"' + * @param dp2 The datapoint to compare + * @return int integer depicting result of comparison, 0 on equal + */ + +int ManagementClient::validateDatapoints(std::string dp1, std::string dp2) +{ + std::string temp; + for (int i = 0; i < dp1.size(); ++i) + { + if ( dp1[i] != '"') + temp.push_back(dp1[i]); + } + + return temp.compare(dp2); +} diff --git a/C/common/storage_asset_tracking.cpp b/C/common/storage_asset_tracking.cpp new file mode 100644 index 0000000000..5d85379541 --- /dev/null +++ b/C/common/storage_asset_tracking.cpp @@ -0,0 +1,321 @@ +/* + * Fledge Storage asset tracking related + * + * Copyright (c) 2022 Dianomic Systems + * + * Released under the Apache 2.0 Licence + * + * Author: Ashwini Sinha + */ + +#include +#include + +using namespace std; + +StorageAssetTracker *StorageAssetTracker::instance = 0; + +/** + * Get asset tracker singleton instance for the current south service + * + * @return Singleton asset tracker instance + */ +StorageAssetTracker *StorageAssetTracker::getStorageAssetTracker() +{ + return instance; +} + +/** + * Release the storage asset tracker singleton instance + * + * @return void + */ + +void StorageAssetTracker::releaseStorageAssetTracker() +{ + if (instance) + delete instance; + instance = nullptr; +} + + +/** + * AssetTracker class constructor + * + * @param mgtClient Management client object for this south service + * @param service Service name + */ +StorageAssetTracker::StorageAssetTracker(ManagementClient *mgtClient, std::string service) + : m_mgtClient(mgtClient), m_service(service), m_event("store") +{ + instance = this; +} + +/** + * Fetch all storage asset tracking tuples from DB and populate local cache + * + * Return the vector of deprecated asset names + * + */ +void StorageAssetTracker::populateStorageAssetTrackingCache() +{ + + try { + std::vector& vec = m_mgtClient->getStorageAssetTrackingTuples(m_service); + for (StorageAssetTrackingTuple* & rec : vec) + { + auto it = storageAssetTrackerTuplesCache.find(rec); + if (it == storageAssetTrackerTuplesCache.end()) + { + // tuple not found in cache , so add it + storageAssetTrackerTuplesCache.insert(rec); + } + else + { + // tuple present and count value < count of reading, update cache + if ((*it)->m_maxCount < rec->m_maxCount) + { + storageAssetTrackerTuplesCache.erase(it); + storageAssetTrackerTuplesCache.insert(rec); + } + else if ((*it)->m_maxCount == rec->m_maxCount) + { + // case where counts are same but datapoints are different + // "a", "b", "c" and "a", "b", "foo" + // keep both the records + if ((*it)->m_datapoints.compare(rec->m_datapoints)) + { + storageAssetTrackerTuplesCache.insert(rec); + } + } + } + + Logger::getLogger()->debug("%s:%d Added storage asset tracker tuple to cache: '%s'", __FUNCTION__, __LINE__, + rec->assetToString().c_str()); + } + delete (&vec); + } + catch (...) + { + Logger::getLogger()->error("%s:%d Failed to populate storage asset tracking tuples' cache", __FUNCTION__, __LINE__); + return; + } + + + return; +} + +/** + * Find whether the Storage asset tracking tuple exists in the cache or not + * + * Return the pointer to the tuple + * + * @param tuple StorageAssetTrackingTuple Type + * @return A pointer to StorageAssetTrackingTuple in cache or null + */ + + +StorageAssetTrackingTuple* StorageAssetTracker::findStorageAssetTrackingCache(StorageAssetTrackingTuple& tuple) +{ + StorageAssetTrackingTuple *ptr = &tuple; + std::unordered_multiset::const_iterator it = storageAssetTrackerTuplesCache.find(ptr); + + if (it == storageAssetTrackerTuplesCache.end()) + { + Logger::getLogger()->debug("%s:%d :tuple not found in cache ", __FUNCTION__, __LINE__); + return NULL; + } + else + { + auto rangeItr = storageAssetTrackerTuplesCache.equal_range(ptr); + + unsigned int max = 0; + std::set maxItr; + for(auto r = rangeItr.first; r != rangeItr.second; ++r) + { + // case where maxcount in cache greater than tuple arg, simply return that itr to cache + if ((*r)->m_maxCount > ptr->m_maxCount) + { + return (*r); + } + if ((*r)->m_maxCount > max) + { + max = (*r)->m_maxCount; + + Logger::getLogger()->debug("%s:%d, max value = %d", __FILE__, __LINE__, max); + } + } + + for(auto r = rangeItr.first; r != rangeItr.second; ++r) + { + //prepare set of iterators with maxiumum value + if ((*r)->m_maxCount == max) + { + maxItr.insert(r); + } + } + + + for(auto r = rangeItr.first; r != rangeItr.second; ++r) + { + + // tuple present and its value > count of max in cache, update in cache, remove rest + if ( ptr->m_maxCount > max) + { + Logger::getLogger()->debug("%s:%d tuple present and count value < count of reading, update cache, erased dp%s ", __FUNCTION__, __LINE__, (*it)->m_datapoints.c_str()); + + storageAssetTrackerTuplesCache.erase(rangeItr.first, rangeItr.second); + return NULL; + } + + else if (ptr->m_maxCount == max) + { + // case where counts are same but datapoints are different + // "a", "b", "c" and "a", "b", "foo" + // keep both the records incoming and max already present in cache + // delete rest + + // for all the records which have less count than maxItr and incoming, delete + if (maxItr.find(r) == maxItr.end()) + { + storageAssetTrackerTuplesCache.erase(r); + } + else + { + + // incoming has same count as maximum, check their dps + + if (compareDatapoints(ptr->m_datapoints,(*r)->m_datapoints)) + { + // dps different however count same , need to update in cache + return NULL; + } + else + { + // dps same and count also same , dont update + return *r; + } + } + } + + } + + // dont need updation , return pointer to tuple in cache + return *it; + } +} + +/** + * Add storage asset tracking tuple via microservice management API and in cache + * + * @param tuple New tuple to add in DB and in cache + */ +void StorageAssetTracker::addStorageAssetTrackingTuple(StorageAssetTrackingTuple& tuple) +{ + std::unordered_multiset::const_iterator it = storageAssetTrackerTuplesCache.find(&tuple); + + bool rv = m_mgtClient->addStorageAssetTrackingTuple(tuple.m_serviceName, tuple.m_pluginName, tuple.m_assetName, tuple.m_eventName, false, tuple.m_datapoints, tuple.m_maxCount); + + if (rv) // insert into cache only if DB operation succeeded + { + StorageAssetTrackingTuple *ptr = new StorageAssetTrackingTuple(tuple); + storageAssetTrackerTuplesCache.insert(ptr); + Logger::getLogger()->info("%s:%d: Added tuple to cache: %s, insert in db successful ", __FUNCTION__, __LINE__, tuple.assetToString().c_str()); + } + else + Logger::getLogger()->error("%s:%d: Failed to insert storage asset tracking tuple into DB: '%s'", __FUNCTION__, __LINE__, tuple.assetToString().c_str()); +} + +/** + * Return Plugin Information in the Fledge configuration + * + * @return bool True if the plugin info could be obtained + */ +bool StorageAssetTracker::getFledgeConfigInfo() +{ + Logger::getLogger()->error("StorageAssetTracker::getPluginInfo start"); + try { + string url = "/fledge/category/service"; + if (!m_mgtClient) + { + Logger::getLogger()->error("%s:%d, m_mgtClient Ptr is NULL", __FUNCTION__, __LINE__); + return false; + } + + auto res = m_mgtClient->getHttpClient()->request("GET", url.c_str()); + Document doc; + string response = res->content.string(); + doc.Parse(response.c_str()); + if (doc.HasParseError()) + { + bool httpError = (isdigit(response[0]) && isdigit(response[1]) && isdigit(response[2]) && response[3]==':'); + Logger::getLogger()->error("%s fetching service record: %s\n", + httpError?"HTTP error while":"Failed to parse result of", + response.c_str()); + return false; + } + else if (doc.HasMember("message")) + { + Logger::getLogger()->error("Failed to fetch /fledge/category/service %s.", + doc["message"].GetString()); + return false; + } + else + { + Value& serviceName = doc["name"]; + if (!serviceName.IsObject()) + { + Logger::getLogger()->error("%s:%d, serviceName is not an object", __FUNCTION__, __LINE__); + return false; + } + + if (!serviceName.HasMember("value")) + { + Logger::getLogger()->error("%s:%d, serviceName has no member value", __FUNCTION__, __LINE__); + return false; + + } + Value& serviceVal = serviceName["value"]; + if ( !serviceVal.IsString()) + { + Logger::getLogger()->error("%s:%d, serviceVal is not a string", __FUNCTION__, __LINE__); + return false; + } + + m_fledgeService = serviceVal.GetString(); + Logger::getLogger()->error("%s:%d, m_plugin value = %s", __FUNCTION__, __LINE__, m_fledgeService.c_str()); + return true; + } + + } catch (const SimpleWeb::system_error &e) { + Logger::getLogger()->error("Get service failed %s.", e.what()); + return false; + } + return false; +} + + +/** + * Compare the Datapoints in StorageAssetTracker, they can be '"' enclosed + * + * @return int result of comparison of datapoints strings , 0 when equal + */ +int StorageAssetTracker::compareDatapoints(const std::string& dp1, const std::string& dp2) +{ + std::string temp1, temp2; + for( int i = 0; i < dp1.size() ; ++i) + { + if (dp1[i] != '"') + temp1.push_back(dp1[i]); + } + + for( int i = 0; i < dp2.size() ; ++i) + { + if (dp2[i] != '"') + temp2.push_back(dp2[i]); + } + + return temp1.compare(temp2); +} + + diff --git a/C/services/south/include/ingest.h b/C/services/south/include/ingest.h index 00a4f23807..38b8d5ad02 100644 --- a/C/services/south/include/ingest.h +++ b/C/services/south/include/ingest.h @@ -73,6 +73,9 @@ class Ingest : public ServiceHandler { void unDeprecateAssetTrackingRecord(AssetTrackingTuple* currentTuple, const std::string& assetName, const std::string& event); + void unDeprecateStorageAssetTrackingRecord(StorageAssetTrackingTuple* currentTuple, + const std::string& assetName, const std::string&, const unsigned int&); + private: void signalStatsUpdate() { diff --git a/C/services/south/include/south_service.h b/C/services/south/include/south_service.h index 96329fa369..18b870ee14 100644 --- a/C/services/south/include/south_service.h +++ b/C/services/south/include/south_service.h @@ -17,6 +17,7 @@ #include #include #include +#include #define MAX_SLEEP 5 // Maximum number of seconds the service will sleep during a poll cycle @@ -93,5 +94,7 @@ class SouthService : public ServiceAuthHandler { std::string m_dataKey; bool m_dryRun; bool m_requestRestart; + StorageAssetTracker *m_storageAssetTracker; + }; #endif diff --git a/C/services/south/ingest.cpp b/C/services/south/ingest.cpp index 4cc2d33425..0d680d5872 100755 --- a/C/services/south/ingest.cpp +++ b/C/services/south/ingest.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include using namespace std; @@ -271,6 +273,7 @@ Ingest::Ingest(StorageClient& storage, // populate asset tracking cache AssetTracker::getAssetTracker()->populateAssetTrackingCache(m_pluginName, "Ingest"); + StorageAssetTracker::getStorageAssetTracker()->populateStorageAssetTrackingCache(); // Create the stats entry for the service createServiceStatsDbEntry(); @@ -452,6 +455,13 @@ void Ingest::waitForQueue() */ void Ingest::processQueue() { + +/* typedef struct{ + std::set setDp; + unsigned int count; + }dpCountObj; +*/ + do { /* * If we have some data that has been previously filtered but failed to send, @@ -499,14 +509,52 @@ void Ingest::processQueue() m_failCnt = 0; std::map statsEntriesCurrQueue; AssetTracker *tracker = AssetTracker::getAssetTracker(); + StorageAssetTracker *satracker = StorageAssetTracker::getStorageAssetTracker(); + if ( satracker == nullptr) + { + Logger::getLogger()->error("%s could not initialize satracker ", __FUNCTION__); + return; + } string lastAsset = ""; int *lastStat = NULL; + std::map > assetDatapointMap; + for (vector::iterator it = q->begin(); it != q->end(); ++it) { Reading *reading = *it; string assetName = reading->getAssetName(); + const std::vector dpVec = reading->getReadingData(); + std::string temp; + + std::set tempSet; + // first sort the individual datapoints + // e.g. dp2, dp3, dp1 push them in a set,to make them + // dp1,dp2,dp3 + for ( auto dp : dpVec) + { + temp.clear(); + temp.append(dp->getName()); + tempSet.insert(temp); + } + + temp.clear(); + + // make a string from sorted datapoints in a reading + int i = 0; + for (auto setItr: tempSet) + { + if ( i> 0) temp.append(","); + temp.append(setItr); + ++i; + } + + // Push them in a set so as to avoid duplication of datapoints + // a reading of d1, d2, d3 and another d2,d3,d1 , second will be discarded + + assetDatapointMap[assetName].insert(temp); + if (lastAsset.compare(assetName)) { AssetTrackingTuple tuple(m_serviceName, @@ -538,6 +586,36 @@ void Ingest::processQueue() } delete reading; } + + for (auto itr : assetDatapointMap) + { + std::set &s = itr.second; + + for (auto dp : s) + { + unsigned int c = count(dp.begin(), dp.end(), ','); + StorageAssetTrackingTuple storageTuple(m_serviceName, + m_pluginName, + itr.first, + "store", false, dp, c+1); + + + StorageAssetTrackingTuple* rv = satracker->findStorageAssetTrackingCache(storageTuple); + if (rv == NULL) + { + // Record not found in cache , please update cache + Logger::getLogger()->debug("%s:%d record not found in cache ", __FUNCTION__, __LINE__); + satracker->addStorageAssetTrackingTuple(storageTuple); + } + else + { + //record found undeprecate the record + Logger::getLogger()->debug("%s:%d Record found in cache , undeprecate it", __FUNCTION__,__LINE__); + unDeprecateStorageAssetTrackingRecord(rv, itr.first, dp, c+1); + } + } + } + delete q; m_resendQueues.erase(m_resendQueues.begin()); unique_lock lck(m_statsMutex); @@ -674,20 +752,54 @@ void Ingest::processQueue() // check if this requires addition of a new asset tracker tuple // Remove the Readings in the vector AssetTracker *tracker = AssetTracker::getAssetTracker(); + StorageAssetTracker *satracker = StorageAssetTracker::getStorageAssetTracker(); string lastAsset; int *lastStat = NULL; + + std::map > assetDatapointMap; + for (vector::iterator it = m_data->begin(); it != m_data->end(); ++it) { - Reading *reading = *it; + Reading *reading = *it; string assetName = reading->getAssetName(); - if (lastAsset.compare(assetName)) - { + const std::vector dpVec = reading->getReadingData(); + std::string temp; + std::set tempSet; + // first sort the individual datapoints + // e.g. dp2, dp3, dp1 push them in a set,to make them + // dp1,dp2,dp3 + + for ( auto dp : dpVec) + { + temp.clear(); + temp.append(dp->getName()); + tempSet.insert(temp); + } + temp.clear(); + // make a string from sorted datapoints in a reading + int i = 0; + for (auto setItr: tempSet) + { + if ( i> 0) temp.append(","); + temp.append(setItr); + ++i; + } + + // Push them in a set so as to avoid duplication of datapoints + // a reading of d1, d2, d3 and another d2,d3,d1 , second will be discarded + + assetDatapointMap[assetName].insert(temp); + + if (lastAsset.compare(assetName)) + { + AssetTrackingTuple tuple(m_serviceName, m_pluginName, assetName, "Ingest"); + // Check Asset record exists AssetTrackingTuple* res = tracker->findAssetTrackingCache(tuple); if (res == NULL) @@ -702,16 +814,52 @@ void Ingest::processQueue() assetName, "Ingest"); } + lastAsset = assetName; - lastStat = &statsEntriesCurrQueue[assetName]; - (*lastStat)++; - } - else if (lastStat) + lastStat = &statsEntriesCurrQueue[assetName]; + (*lastStat)++; + } + else if (lastStat) + { + (*lastStat)++; + } + delete reading; + + } + + + for (auto itr : assetDatapointMap) + { + for (auto dp : itr.second) { - (*lastStat)++; + unsigned int c= count(dp.begin(), dp.end(), ','); + + StorageAssetTrackingTuple storageTuple(m_serviceName, + m_pluginName, + itr.first, + "store", false, dp, c+1); + + Logger::getLogger()->debug("%s Dp string dp = %s", __FUNCTION__, dp.c_str()); + + StorageAssetTrackingTuple* rv = satracker->findStorageAssetTrackingCache(storageTuple); + + + if (rv == NULL) + { + // Record not found in cache , please update cache + Logger::getLogger()->debug("%s:%d record not found in cache add it", __FUNCTION__, __LINE__); + satracker->addStorageAssetTrackingTuple(storageTuple); + } + else + { + //record found undeprecate the record + Logger::getLogger()->debug("%s:%d No need for updation , undeprecate it", __FUNCTION__,__LINE__); + + unDeprecateStorageAssetTrackingRecord(rv, itr.first, dp, c+1); + } } - delete reading; } + { unique_lock lck(m_statsMutex); for (auto &it : statsEntriesCurrQueue) @@ -1005,7 +1153,95 @@ void Ingest::unDeprecateAssetTrackingRecord(AssetTrackingTuple* currentTuple, } else { - m_logger->error("Failure to get AssetTracking record " + m_logger->error("Failure to get AssetTracking record " + "for service '%s', asset '%s'", + m_serviceName.c_str(), + assetName.c_str()); + } + + delete updatedTuple; +} + +/** + * Load an up-to-date StorageAssetTracking record for the given parameters + * and un-deprecate StorageAssetTracking record it has been found as deprecated + * Existing cache element is updated + * + * @param currentTuple Current StorageAssetTracking record for given assetName + * @param assetName AssetName to fetch from AssetTracking + * @param event The event type to fetch + */ +void Ingest::unDeprecateStorageAssetTrackingRecord(StorageAssetTrackingTuple* currentTuple, + const string& assetName, const string& datapoints, const unsigned int& count) + +{ + + // Get up-to-date Asset Tracking record + StorageAssetTrackingTuple* updatedTuple = + m_mgtClient->getStorageAssetTrackingTuple( + m_serviceName, + assetName, + "store", + datapoints, + count); + + std::string data = "{\"datapoints\":["; + data.append(datapoints); + data.append("],\"count\":"); + data.append(to_string(count)); + data.append("}"); + + if (updatedTuple) + { + if (updatedTuple->isDeprecated()) + { + + // Update un-deprecated state in cached object + currentTuple->unDeprecate(); + + m_logger->error(" storage Asset '%s' is being un-deprecated", + assetName.c_str()); + + // Prepare UPDATE query + const Condition conditionParams(Equals); + Where * wAsset = new Where("asset", + conditionParams, + assetName); + Where *wService = new Where("service", + conditionParams, + m_serviceName, + wAsset); + Where *wEvent = new Where("event", + conditionParams, + "store", + wService); + Where *wData = new Where("data", + conditionParams, + data, + wEvent); + + InsertValues unDeprecated; + + // Set NULL value + unDeprecated.push_back(InsertValue("deprecated_ts")); + + // Update storage with NULL value + int rv = m_storage.updateTable("asset_tracker", + unDeprecated, + *wData); + + + // Check update operation + if (rv < 0) + { + m_logger->error("Failure while un-deprecating asset '%s'", + assetName.c_str()); + } + } + } + else + { + m_logger->error("Failure to get StorageAssetTracking record " "for service '%s', asset '%s'", m_serviceName.c_str(), assetName.c_str()); @@ -1013,3 +1249,5 @@ void Ingest::unDeprecateAssetTrackingRecord(AssetTrackingTuple* currentTuple, delete updatedTuple; } + + diff --git a/C/services/south/south.cpp b/C/services/south/south.cpp index 8da23586af..8c8b0a610a 100755 --- a/C/services/south/south.cpp +++ b/C/services/south/south.cpp @@ -384,6 +384,7 @@ void SouthService::start(string& coreAddress, unsigned short corePort) } m_assetTracker = new AssetTracker(m_mgtClient, m_name); + m_storageAssetTracker = new StorageAssetTracker(m_mgtClient, m_name); { // Instantiate the Ingest class @@ -663,6 +664,10 @@ void SouthService::start(string& coreAddress, unsigned short corePort) */ void SouthService::stop() { + if (m_storageAssetTracker) + { + m_storageAssetTracker->releaseStorageAssetTracker(); + } logger->info("Stopping south service...\n"); } diff --git a/VERSION b/VERSION index ecea005f07..d4d97dc5ab 100755 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ fledge_version=1.9.2 -fledge_schema=56 +fledge_schema=57 diff --git a/python/fledge/services/core/api/asset_tracker.py b/python/fledge/services/core/api/asset_tracker.py index 83a4e1ddd4..f4d9903b88 100644 --- a/python/fledge/services/core/api/asset_tracker.py +++ b/python/fledge/services/core/api/asset_tracker.py @@ -4,6 +4,7 @@ # See: http://fledge-iot.readthedocs.io/ # FLEDGE_END import json +import logging from aiohttp import web import urllib.parse @@ -12,9 +13,10 @@ from fledge.common.storage_client.exceptions import StorageServerError from fledge.common.storage_client.payload_builder import PayloadBuilder from fledge.services.core import connect + from fledge.common.audit_logger import AuditLogger from fledge.common import logger -import logging + __author__ = "Ashish Jabble" __copyright__ = "Copyright (c) 2018 OSIsoft, LLC" @@ -30,6 +32,7 @@ _logger = logger.setup(__name__, level=logging.INFO) + async def get_asset_tracker_events(request: web.Request) -> web.Response: """ Args: @@ -45,7 +48,7 @@ async def get_asset_tracker_events(request: web.Request) -> web.Response: curl -sX GET http://localhost:8081/fledge/track?service=XXX curl -sX GET http://localhost:8081/fledge/track?event=XXX&asset=XXX&service=XXX """ - payload = PayloadBuilder().SELECT("asset", "event", "service", "fledge", "plugin", "ts", "deprecated_ts") \ + payload = PayloadBuilder().SELECT("asset", "event", "service", "fledge", "plugin", "ts", "deprecated_ts", "data") \ .ALIAS("return", ("ts", 'timestamp')).FORMAT("return", ("ts", "YYYY-MM-DD HH24:MI:SS.MS")) \ .ALIAS("return", ("deprecated_ts", 'deprecatedTimestamp')) \ .WHERE(['1', '=', 1]) @@ -141,3 +144,94 @@ async def deprecate_asset_track_entry(request: web.Request) -> web.Response: else: _logger.info("Asset '{}' has been deprecated".format(asset_name)) return web.json_response({'success': "Asset record entry has been deprecated."}) + + +async def get_datapoint_usage(request: web.Request) -> web.Response: + """ + Args: + request: a GET request to the /fledge/track/storage/assets Endpoint. + + Returns: + A JSON response. An example would be. + { + "count" : 5, + "assets" : [ + { + "asset" : "sinusoid", + "datapoints" : [ "sinusoid" ] + }, + { + "asset" : "motor", + "datapoints" : [ "rpm", "current", "voltage", "temperature" ] + } + ] + } + + :Example: + curl -sX GET http://localhost:8081/fledge/track/storage/assets + + """ + + response = {"count": 0, + "assets": [] + } + try: + storage_client = connect.get_storage_async() + q_payload = PayloadBuilder().SELECT(). \ + DISTINCT(["asset", "data"]). \ + WHERE(["event", "=", "store"]). \ + payload() + + results = await storage_client.query_tbl_with_payload('asset_tracker', q_payload) + + total_datapoints = 0 + asset_info_list = [] + for row in results["rows"]: + # The no of datapoints for this asset. + asset_name = row["asset"] + # Construct a dict that contains information about a single asset. + current_count = int(row["data"]["count"]) + dict_to_add = {"asset": row["asset"], "datapoints": row["data"]["datapoints"], 'count': current_count} + # appending information of single asset to the asset information list. + + # now find that this is a new asset or not. + # Initialize index_of_found_asset by -1 . -1 means not found. + index_of_found_asset = -1 + for (idx, asset_info) in enumerate(asset_info_list): + if 'asset' in asset_info and asset_info['asset'] == asset_name: + index_of_found_asset = idx + + if index_of_found_asset != -1: + # If current data point count exceed the maximum data point then replace + # this new data point information else do nothing + if current_count >= asset_info_list[index_of_found_asset]['count']: + asset_info_list.pop(index_of_found_asset) + asset_info_list.append(dict_to_add) + else: + # This is a new asset simply add to list. + asset_info_list.append(dict_to_add) + + # finally calculate the total data points + for asset_info in asset_info_list: + total_datapoints += int(asset_info['count']) + + # Remove count for each asset_info + for ast_info in asset_info_list: + ast_info.pop('count') + + # update the required information. + response['assets'] = asset_info_list + response["count"] = total_datapoints + + except KeyError as msg: + raise web.HTTPBadRequest(reason=str(msg), body=json.dumps({"message": str(msg)})) + except TypeError as ex: + raise web.HTTPBadRequest(reason=str(ex), body=json.dumps({"message": str(ex)})) + except StorageServerError as ex: + err_response = ex.error + raise web.HTTPBadRequest(reason=err_response, body=json.dumps({"message": err_response})) + except Exception as ex: + msg = str(ex) + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + else: + return web.json_response(response) diff --git a/python/fledge/services/core/asset_tracker/asset_tracker.py b/python/fledge/services/core/asset_tracker/asset_tracker.py index bcc1f6b072..d8098b49da 100644 --- a/python/fledge/services/core/asset_tracker/asset_tracker.py +++ b/python/fledge/services/core/asset_tracker/asset_tracker.py @@ -43,14 +43,14 @@ async def load_asset_records(self): self._registered_asset_records = [] try: - payload = PayloadBuilder().SELECT("asset", "event", "service", "plugin").payload() + payload = PayloadBuilder().SELECT("asset", "event", "service", "plugin", "data").payload() results = await self._storage.query_tbl_with_payload('asset_tracker', payload) for row in results['rows']: self._registered_asset_records.append(row) except Exception as ex: _logger.exception('Failed to retrieve asset records, %s', str(ex)) - async def add_asset_record(self, *, asset, event, service, plugin): + async def add_asset_record(self, *, asset, event, service, plugin, jsondata = {}): """ Args: asset: asset code of the record @@ -59,7 +59,7 @@ async def add_asset_record(self, *, asset, event, service, plugin): plugin: The name of the plugin, that has been loaded by the service. """ # If (asset + event + service + plugin) row combination exists in _find_registered_asset_record then return - d = {"asset": asset, "event": event, "service": service, "plugin": plugin} + d = {"asset": asset, "event": event, "service": service, "plugin": plugin, "data":jsondata} if d in self._registered_asset_records: return {} @@ -72,7 +72,8 @@ async def add_asset_record(self, *, asset, event, service, plugin): self.fledge_svc_name = svc_config['value'] try: - payload = PayloadBuilder().INSERT(asset=asset, event=event, service=service, plugin=plugin, fledge=self.fledge_svc_name).payload() + payload = PayloadBuilder().INSERT(asset=asset, event=event, service=service, plugin=plugin, fledge=self.fledge_svc_name, data=jsondata).payload() + result = await self._storage.insert_into_tbl('asset_tracker', payload) response = result['response'] self._registered_asset_records.append(d) diff --git a/python/fledge/services/core/routes.py b/python/fledge/services/core/routes.py index 95d2467030..183edb268e 100644 --- a/python/fledge/services/core/routes.py +++ b/python/fledge/services/core/routes.py @@ -141,6 +141,7 @@ def setup(app): app.router.add_route('GET', '/fledge/track', asset_tracker.get_asset_tracker_events) app.router.add_route('PUT', '/fledge/track/service/{service}/asset/{asset}/event/{event}', asset_tracker.deprecate_asset_track_entry) + app.router.add_route('GET', '/fledge/track/storage/assets', asset_tracker.get_datapoint_usage) # Statistics - As per doc app.router.add_route('GET', '/fledge/statistics', api_statistics.get_statistics) diff --git a/python/fledge/services/core/server.py b/python/fledge/services/core/server.py index 87c90ddd58..3961063b58 100755 --- a/python/fledge/services/core/server.py +++ b/python/fledge/services/core/server.py @@ -1620,15 +1620,28 @@ async def get_track(cls, request): @classmethod async def add_track(cls, request): + data = await request.json() + if not isinstance(data, dict): raise ValueError('Data payload must be a dictionary') + jsondata=data.get("data") + try: - result = await cls._asset_tracker.add_asset_record(asset=data.get("asset"), - plugin=data.get("plugin"), - service=data.get("service"), - event=data.get("event")) + if jsondata is None: + + result = await cls._asset_tracker.add_asset_record(asset=data.get("asset"), + plugin=data.get("plugin"), + service=data.get("service"), + event=data.get("event")) + else: + result = await cls._asset_tracker.add_asset_record(asset=data.get("asset"), + plugin=data.get("plugin"), + service=data.get("service"), + event=data.get("event"), + jsondata=data.get("data")) + except (TypeError, StorageServerError) as ex: raise web.HTTPBadRequest(reason=str(ex)) except ValueError as ex: diff --git a/scripts/plugins/storage/postgres/downgrade/56.sql b/scripts/plugins/storage/postgres/downgrade/56.sql new file mode 100644 index 0000000000..56cdf037c6 --- /dev/null +++ b/scripts/plugins/storage/postgres/downgrade/56.sql @@ -0,0 +1,2 @@ +--Remove data column from asset_tracker table +ALTER TABLE fledge.asset_tracker DROP COLUMN IF EXISTS data; diff --git a/scripts/plugins/storage/postgres/upgrade/57.sql b/scripts/plugins/storage/postgres/upgrade/57.sql new file mode 100644 index 0000000000..7be416489d --- /dev/null +++ b/scripts/plugins/storage/postgres/upgrade/57.sql @@ -0,0 +1,3 @@ +-- Add new column name 'data' for asset_tracker + +ALTER TABLE fledge.asset_tracker ADD COLUMN data JSONB DEFAULT '{}'::jsonb; diff --git a/scripts/plugins/storage/sqlite/downgrade/56.sql b/scripts/plugins/storage/sqlite/downgrade/56.sql new file mode 100644 index 0000000000..d6900d6c6d --- /dev/null +++ b/scripts/plugins/storage/sqlite/downgrade/56.sql @@ -0,0 +1,36 @@ +-- From: http://www.sqlite.org/faq.html: +-- SQLite has limited ALTER TABLE support that you can use to change type of column. +-- If you want to change the type of any column you will have to recreate the table. +-- You can save existing data to a temporary table and then drop the old table +-- Now, create the new table, then copy the data back in from the temporary table + + + +-- Drop existing index +DROP INDEX IF EXISTS asset_tracker_ix1; +DROP INDEX IF EXISTS asset_tracker_ix2; + +-- Rename existing table into a temp one +ALTER TABLE fledge.asset_tracker RENAME TO asset_tracker_old; + +-- Create new table +CREATE TABLE IF NOT EXISTS fledge.asset_tracker ( + id integer PRIMARY KEY AUTOINCREMENT, + asset character(50) NOT NULL, -- asset name + event character varying(50) NOT NULL, -- event name + service character varying(255) NOT NULL, -- service name + fledge character varying(50) NOT NULL, -- FL service name + plugin character varying(50) NOT NULL, -- Plugin name + deprecated_ts DATETIME, + ts DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime')) +); + +-- Copy data +INSERT INTO fledge.asset_tracker ( id, asset, event, service, fledge, plugin, deprecated_ts, ts ) SELECT id, asset, event, service, fledge, plugin, deprecated_ts, ts FROM fledge.asset_tracker_old; + +-- Create Index +CREATE INDEX asset_tracker_ix1 ON asset_tracker (asset); +CREATE INDEX asset_tracker_ix2 ON asset_tracker (service); + +-- Remove old table +DROP TABLE IF EXISTS fledge.asset_tracker_old; diff --git a/scripts/plugins/storage/sqlite/init.sql b/scripts/plugins/storage/sqlite/init.sql index 3f92464ccb..de17d8aa6f 100644 --- a/scripts/plugins/storage/sqlite/init.sql +++ b/scripts/plugins/storage/sqlite/init.sql @@ -566,7 +566,8 @@ CREATE TABLE fledge.asset_tracker ( fledge character varying(50) NOT NULL, -- FL service name plugin character varying(50) NOT NULL, -- Plugin name deprecated_ts DATETIME , -- When an asset record is removed then time will be set else empty and that mean entry has not been deprecated - ts DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime')) + ts DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime')), + data JSON DEFAULT '{}' ); CREATE INDEX asset_tracker_ix1 ON asset_tracker (asset); diff --git a/scripts/plugins/storage/sqlite/upgrade/57.sql b/scripts/plugins/storage/sqlite/upgrade/57.sql new file mode 100644 index 0000000000..990c98da54 --- /dev/null +++ b/scripts/plugins/storage/sqlite/upgrade/57.sql @@ -0,0 +1,37 @@ +-- From: http://www.sqlite.org/faq.html: +-- SQLite has limited ALTER TABLE support that you can use to change type of column. +-- If you want to change the type of any column you will have to recreate the table. +-- You can save existing data to a temporary table and then drop the old table +-- Now, create the new table, then copy the data back in from the temporary table + + + +-- Drop existing index +DROP INDEX IF EXISTS asset_tracker_ix1; +DROP INDEX IF EXISTS asset_tracker_ix2; + +-- Rename existing table into a temp one +ALTER TABLE fledge.asset_tracker RENAME TO asset_tracker_old; + +-- Create new table +CREATE TABLE IF NOT EXISTS fledge.asset_tracker ( + id integer PRIMARY KEY AUTOINCREMENT, + asset character(50) NOT NULL, -- asset name + event character varying(50) NOT NULL, -- event name + service character varying(255) NOT NULL, -- service name + fledge character varying(50) NOT NULL, -- FL service name + plugin character varying(50) NOT NULL, -- Plugin name + deprecated_ts DATETIME, + ts DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime')), + data JSON DEFAULT '{}' +); + +-- Copy data +INSERT INTO fledge.asset_tracker ( id, asset, event, service, fledge, plugin, deprecated_ts, ts ) SELECT id, asset, event, service, fledge, plugin, deprecated_ts, ts FROM fledge.asset_tracker_old; + +-- Create Index +CREATE INDEX asset_tracker_ix1 ON asset_tracker (asset); +CREATE INDEX asset_tracker_ix2 ON asset_tracker (service); + +-- Remote old table +DROP TABLE IF EXISTS fledge.asset_tracker_old; diff --git a/scripts/plugins/storage/sqlitelb/downgrade/56.sql b/scripts/plugins/storage/sqlitelb/downgrade/56.sql new file mode 100644 index 0000000000..d6900d6c6d --- /dev/null +++ b/scripts/plugins/storage/sqlitelb/downgrade/56.sql @@ -0,0 +1,36 @@ +-- From: http://www.sqlite.org/faq.html: +-- SQLite has limited ALTER TABLE support that you can use to change type of column. +-- If you want to change the type of any column you will have to recreate the table. +-- You can save existing data to a temporary table and then drop the old table +-- Now, create the new table, then copy the data back in from the temporary table + + + +-- Drop existing index +DROP INDEX IF EXISTS asset_tracker_ix1; +DROP INDEX IF EXISTS asset_tracker_ix2; + +-- Rename existing table into a temp one +ALTER TABLE fledge.asset_tracker RENAME TO asset_tracker_old; + +-- Create new table +CREATE TABLE IF NOT EXISTS fledge.asset_tracker ( + id integer PRIMARY KEY AUTOINCREMENT, + asset character(50) NOT NULL, -- asset name + event character varying(50) NOT NULL, -- event name + service character varying(255) NOT NULL, -- service name + fledge character varying(50) NOT NULL, -- FL service name + plugin character varying(50) NOT NULL, -- Plugin name + deprecated_ts DATETIME, + ts DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime')) +); + +-- Copy data +INSERT INTO fledge.asset_tracker ( id, asset, event, service, fledge, plugin, deprecated_ts, ts ) SELECT id, asset, event, service, fledge, plugin, deprecated_ts, ts FROM fledge.asset_tracker_old; + +-- Create Index +CREATE INDEX asset_tracker_ix1 ON asset_tracker (asset); +CREATE INDEX asset_tracker_ix2 ON asset_tracker (service); + +-- Remove old table +DROP TABLE IF EXISTS fledge.asset_tracker_old; diff --git a/scripts/plugins/storage/sqlitelb/upgrade/57.sql b/scripts/plugins/storage/sqlitelb/upgrade/57.sql new file mode 100644 index 0000000000..990c98da54 --- /dev/null +++ b/scripts/plugins/storage/sqlitelb/upgrade/57.sql @@ -0,0 +1,37 @@ +-- From: http://www.sqlite.org/faq.html: +-- SQLite has limited ALTER TABLE support that you can use to change type of column. +-- If you want to change the type of any column you will have to recreate the table. +-- You can save existing data to a temporary table and then drop the old table +-- Now, create the new table, then copy the data back in from the temporary table + + + +-- Drop existing index +DROP INDEX IF EXISTS asset_tracker_ix1; +DROP INDEX IF EXISTS asset_tracker_ix2; + +-- Rename existing table into a temp one +ALTER TABLE fledge.asset_tracker RENAME TO asset_tracker_old; + +-- Create new table +CREATE TABLE IF NOT EXISTS fledge.asset_tracker ( + id integer PRIMARY KEY AUTOINCREMENT, + asset character(50) NOT NULL, -- asset name + event character varying(50) NOT NULL, -- event name + service character varying(255) NOT NULL, -- service name + fledge character varying(50) NOT NULL, -- FL service name + plugin character varying(50) NOT NULL, -- Plugin name + deprecated_ts DATETIME, + ts DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime')), + data JSON DEFAULT '{}' +); + +-- Copy data +INSERT INTO fledge.asset_tracker ( id, asset, event, service, fledge, plugin, deprecated_ts, ts ) SELECT id, asset, event, service, fledge, plugin, deprecated_ts, ts FROM fledge.asset_tracker_old; + +-- Create Index +CREATE INDEX asset_tracker_ix1 ON asset_tracker (asset); +CREATE INDEX asset_tracker_ix2 ON asset_tracker (service); + +-- Remote old table +DROP TABLE IF EXISTS fledge.asset_tracker_old; diff --git a/tests/unit/python/fledge/services/core/api/test_asset_tracker_api.py b/tests/unit/python/fledge/services/core/api/test_asset_tracker_api.py index 1b60fdb022..ed295552f7 100644 --- a/tests/unit/python/fledge/services/core/api/test_asset_tracker_api.py +++ b/tests/unit/python/fledge/services/core/api/test_asset_tracker_api.py @@ -42,16 +42,16 @@ async def async_mock(): storage_client_mock = MagicMock(StorageClientAsync) rows = [{'asset': 'AirIntake', 'event': 'Ingest', 'fledge': 'Booth1', 'service': 'PT100_In1', - 'plugin': 'PT100', "timestamp": "2018-08-13 15:39:48.796263", "deprecatedTimestamp": "" + 'plugin': 'PT100', "timestamp": "2018-08-13 15:39:48.796263", "deprecatedTimestamp": "", 'data':'{}' }, {'asset': 'AirIntake', 'event': 'Egress', 'fledge': 'Booth1', 'service': 'Display', - 'plugin': 'ShopFloorDisplay', "timestamp": "2018-08-13 16:00:00.134563", "deprecatedTimestamp": "" + 'plugin': 'ShopFloorDisplay', "timestamp": "2018-08-13 16:00:00.134563", "deprecatedTimestamp": "", 'data':'{}' } ] payload = {'where': {'condition': '=', 'value': 1, 'column': '1'}, 'return': ['asset', 'event', 'service', 'fledge', 'plugin', {'alias': 'timestamp', 'column': 'ts', 'format': 'YYYY-MM-DD HH24:MI:SS.MS'}, - {'alias': 'deprecatedTimestamp', 'column': 'deprecated_ts'} + {'alias': 'deprecatedTimestamp', 'column': 'deprecated_ts'}, 'data' ] } diff --git a/tests/unit/python/fledge/services/core/asset_tracker/test_asset_tracker.py b/tests/unit/python/fledge/services/core/asset_tracker/test_asset_tracker.py index e291409b1d..dbb3e72d1f 100644 --- a/tests/unit/python/fledge/services/core/asset_tracker/test_asset_tracker.py +++ b/tests/unit/python/fledge/services/core/asset_tracker/test_asset_tracker.py @@ -32,7 +32,7 @@ async def test_init_with_no_storage(self): @pytest.mark.parametrize("result, asset_list", [ ({'rows': [], 'count': 0}, []), - ({'rows': [{'event': 'Ingest', 'service': 'sine', 'plugin': 'sinusoid', 'asset': 'sinusoid'}], 'count': 1}, [{'event': 'Ingest', 'service': 'sine', 'asset': 'sinusoid', 'plugin': 'sinusoid'}]) + ({'rows': [{'event': 'Ingest', 'service': 'sine', 'plugin': 'sinusoid', 'asset': 'sinusoid', 'data': '{}'}], 'count': 1}, [{'event': 'Ingest', 'service': 'sine', 'asset': 'sinusoid', 'plugin': 'sinusoid', 'data':'{}'}]) ]) async def test_load_asset_records(self, result, asset_list): storage_client_mock = MagicMock(spec=StorageClientAsync) @@ -51,14 +51,14 @@ async def mock_coro(): with patch.object(asset_tracker._storage, 'query_tbl_with_payload', return_value=_rv) as patch_query_tbl: await asset_tracker.load_asset_records() assert asset_list == asset_tracker._registered_asset_records - patch_query_tbl.assert_called_once_with('asset_tracker', '{"return": ["asset", "event", "service", "plugin"]}') + patch_query_tbl.assert_called_once_with('asset_tracker', '{"return": ["asset", "event", "service", "plugin", "data"]}') async def test_add_asset_record(self): storage_client_mock = MagicMock(spec=StorageClientAsync) asset_tracker = AssetTracker(storage_client_mock) cfg_manager = ConfigurationManager(storage_client_mock) asset_tracker._registered_asset_records = [] - payload = {"plugin": "sinusoid", "asset": "sinusoid", "event": "Ingest", "fledge": "Fledge", "service": "sine"} + payload = {"plugin": "sinusoid", "asset": "sinusoid", "event": "Ingest", "fledge": "Fledge", "service": "sine", "data":"{}"} async def mock_coro(): return {"default": "Fledge", "value": "Fledge", "type": "string", "description": "Name of this Fledge service"} @@ -76,7 +76,7 @@ async def mock_coro2(): with patch.object(cfg_manager, 'get_category_item', return_value=_rv1) as patch_get_cat_item: with patch.object(asset_tracker._storage, 'insert_into_tbl', return_value=_rv2) as patch_insert_tbl: - result = await asset_tracker.add_asset_record(asset='sinusoid', event='Ingest', service='sine', plugin='sinusoid') + result = await asset_tracker.add_asset_record(asset='sinusoid', event='Ingest', service='sine', plugin='sinusoid', jsondata='{}') assert payload == result args, kwargs = patch_insert_tbl.call_args assert 'asset_tracker' == args[0] From d1ad88f3ce20632e0d9af219789c2164d29f3dea Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Fri, 9 Sep 2022 16:42:57 +0100 Subject: [PATCH 03/48] FOGL-6897 - Fix issue if reading rate unit is changed without changing (#815) the reading rate value Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/services/south/include/south_service.h | 1 + C/services/south/south.cpp | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/C/services/south/include/south_service.h b/C/services/south/include/south_service.h index 18b870ee14..7233043de0 100644 --- a/C/services/south/include/south_service.h +++ b/C/services/south/include/south_service.h @@ -94,6 +94,7 @@ class SouthService : public ServiceAuthHandler { std::string m_dataKey; bool m_dryRun; bool m_requestRestart; + std::string m_rateUnits; StorageAssetTracker *m_storageAssetTracker; }; diff --git a/C/services/south/south.cpp b/C/services/south/south.cpp index 8c8b0a610a..ccc5dac5de 100755 --- a/C/services/south/south.cpp +++ b/C/services/south/south.cpp @@ -430,6 +430,7 @@ void SouthService::start(string& coreAddress, unsigned short corePort) dividend = 60000000; else if (units.compare("hour") == 0) dividend = 3600000000; + m_rateUnits = units; unsigned long usecs = dividend / m_readingsPerSec; if (usecs > MAX_SLEEP * 1000000) @@ -836,9 +837,10 @@ void SouthService::configChange(const string& categoryName, const string& catego dividend = 60000000; else if (units.compare("hour") == 0) dividend = 3600000000; - if (newval != m_readingsPerSec) + if (newval != m_readingsPerSec || m_rateUnits.compare(units) != 0) { m_readingsPerSec = newval; + m_rateUnits = units; close(m_timerfd); unsigned long usecs = dividend / m_readingsPerSec; if (usecs > MAX_SLEEP * 1000000) From fc3c294c88d9bdfb2031119ac90b5fa25072e1c6 Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Fri, 9 Sep 2022 17:03:48 +0100 Subject: [PATCH 04/48] FOGL-6896 Enforce minimum value for reading rate (#816) Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/common/config_category.cpp | 9 +++++++++ C/common/include/config_category.h | 5 ++++- C/services/south/south.cpp | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/C/common/config_category.cpp b/C/common/config_category.cpp index 862a24d89e..0ff76b10e7 100644 --- a/C/common/config_category.cpp +++ b/C/common/config_category.cpp @@ -505,6 +505,15 @@ bool ConfigCategory::setItemAttribute(const string& itemName, case FILE_ATTR: m_items[i]->m_file = value; return true; + case MINIMUM_ATTR: + m_items[i]->m_minimum = value; + return true; + case MAXIMUM_ATTR: + m_items[i]->m_maximum = value; + return true; + case LENGTH_ATTR: + m_items[i]->m_length = value; + return true; default: return false; } diff --git a/C/common/include/config_category.h b/C/common/include/config_category.h index df9606a42c..76803e0f77 100644 --- a/C/common/include/config_category.h +++ b/C/common/include/config_category.h @@ -121,7 +121,10 @@ class ConfigCategory { ORDER_ATTR, READONLY_ATTR, MANDATORY_ATTR, - FILE_ATTR}; + FILE_ATTR, + MINIMUM_ATTR, + MAXIMUM_ATTR, + LENGTH_ATTR}; std::string getItemAttribute(const std::string& itemName, ItemAttribute itemAttribute) const; diff --git a/C/services/south/south.cpp b/C/services/south/south.cpp index ccc5dac5de..f03c7d4140 100755 --- a/C/services/south/south.cpp +++ b/C/services/south/south.cpp @@ -395,6 +395,11 @@ void SouthService::start(string& coreAddress, unsigned short corePort) m_readingsPerSec = 1; if (m_configAdvanced.itemExists("readingsPerSec")) m_readingsPerSec = (unsigned long)strtol(m_configAdvanced.getValue("readingsPerSec").c_str(), NULL, 10); + if (m_readingsPerSec < 1) + { + logger->warn("Invalid setting of reading rate, defaulting to 1"); + m_readingsPerSec = 1; + } } catch (ConfigItemNotFound e) { logger->info("Defaulting to inline default for poll interval"); } @@ -829,6 +834,11 @@ void SouthService::configChange(const string& categoryName, const string& catego { try { unsigned long newval = (unsigned long)strtol(m_configAdvanced.getValue("readingsPerSec").c_str(), NULL, 10); + if (newval < 1) + { + logger->warn("Invalid setting of reading rate, defaulting to 1"); + m_readingsPerSec = 1; + } string units = m_configAdvanced.getValue("units"); unsigned long dividend = 1000000; if (units.compare("second") == 0) @@ -939,6 +949,11 @@ void SouthService::addConfigDefaults(DefaultConfigCategory& defaultConfig) defaultConfig.addItem(defaults[i].name, defaults[i].description, defaults[i].type, defaults[i].value, defaults[i].value); defaultConfig.setItemDisplayName(defaults[i].name, defaults[i].displayName); + if (!strcmp(defaults[i].name, "readingsPerSec")) + { + defaultConfig.setItemAttribute(defaults[i].name, ConfigCategory::MINIMUM_ATTR, "1"); + + } } if (!isAsync) From 51e4e8bc9cda367922befc05b73560d1479868cc Mon Sep 17 00:00:00 2001 From: Praveen Garg Date: Mon, 12 Sep 2022 14:01:38 +0530 Subject: [PATCH 05/48] FOGL-6894 (patch) package system test fix - auth tests (#818) * package system test fix Signed-off-by: Praveen Garg --- .../python/packages/test_authentication.py | 114 +++++++++--------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/tests/system/python/packages/test_authentication.py b/tests/system/python/packages/test_authentication.py index 329534945a..1c029478cf 100644 --- a/tests/system/python/packages/test_authentication.py +++ b/tests/system/python/packages/test_authentication.py @@ -33,6 +33,8 @@ SCRIPTS_DIR_ROOT = "{}/tests/system/python/packages/data/".format(PROJECT_ROOT) context = ssl._create_unverified_context() +LOGIN_SUCCESS_MSG = "Logged in successfully." + def send_data_using_fogbench(wait_time): execute_fogbench = 'cd {}/extras/python ;python3 -m fogbench -t $FLEDGE_ROOT/data/tests/{} ' \ @@ -220,7 +222,7 @@ def generate_password_based_auth_token(asset_name, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert not jdoc['admin'] global PASSWORD_TOKEN PASSWORD_TOKEN = jdoc["token"] @@ -236,7 +238,7 @@ def generate_certificate_based_auth_token(asset_name, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] global CERT_TOKEN @@ -324,7 +326,7 @@ def test_login_regular_user_using_password(self, reset_fledge, change_to_auth_ma assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert not jdoc['admin'] global PASSWORD_TOKEN PASSWORD_TOKEN = jdoc["token"] @@ -352,7 +354,7 @@ def test_login_username_admin_using_password(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] global PASSWORD_TOKEN @@ -374,7 +376,7 @@ def test_login_with_user_certificate(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] @@ -387,7 +389,7 @@ def test_login_with_admin_certificate(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] global CERT_TOKEN @@ -414,7 +416,7 @@ def test_login_with_custom_certificate(self, fledge_url, remove_data_file): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] @@ -466,7 +468,7 @@ def test_ping_with_allow_ping_false_with_password_token(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] _token = jdoc["token"] conn = http.client.HTTPConnection(fledge_url) @@ -495,7 +497,7 @@ def test_ping_with_allow_ping_false_with_certificate_token(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] _token = jdoc["token"] conn = http.client.HTTPConnection(fledge_url) @@ -616,10 +618,10 @@ def test_create_user_with_certificate_token(self, fledge_url, form_data, expecte assert expected_values == jdoc @pytest.mark.parametrize(("form_data", "expected_values"), [ - ({"username": "any1", "password": "User@123"}, 'Logged in successfully'), - ({"username": "admin1", "password": "F0gl@mp!"}, 'Logged in successfully'), - ({"username": "any2", "password": "User@123"}, 'Logged in successfully'), - ({"username": "admin2", "password": "F0gl@mp!"}, 'Logged in successfully') + ({"username": "any1", "password": "User@123"}, LOGIN_SUCCESS_MSG), + ({"username": "admin1", "password": "F0gl@mp!"}, LOGIN_SUCCESS_MSG), + ({"username": "any2", "password": "User@123"}, LOGIN_SUCCESS_MSG), + ({"username": "admin2", "password": "F0gl@mp!"}, LOGIN_SUCCESS_MSG) ]) def test_login_of_newly_created_user(self, fledge_url, form_data, expected_values): conn = http.client.HTTPConnection(fledge_url) @@ -655,8 +657,8 @@ def test_update_password_with_certificate_token(self, fledge_url): assert {'message': 'Password has been updated successfully for user id:<{}>'.format(uid)} == jdoc @pytest.mark.parametrize(("form_data", "expected_values"), [ - ({"username": "any1", "password": "F0gl@mp1"}, 'Logged in successfully'), - ({"username": "any2", "password": "F0gl@mp2"}, 'Logged in successfully') + ({"username": "any1", "password": "F0gl@mp1"}, LOGIN_SUCCESS_MSG), + ({"username": "any2", "password": "F0gl@mp2"}, LOGIN_SUCCESS_MSG) ]) def test_login_with_updated_password(self, fledge_url, form_data, expected_values): conn = http.client.HTTPConnection(fledge_url) @@ -688,8 +690,8 @@ def test_reset_user_with_certificate_token(self, fledge_url): assert {'message': 'User with id:<5> has been updated successfully'} == jdoc @pytest.mark.parametrize(("form_data", "expected_values"), [ - ({"username": "any1", "password": "F0gl@mp!#1"}, 'Logged in successfully'), - ({"username": "any2", "password": "F0gl@mp!#2"}, 'Logged in successfully') + ({"username": "any1", "password": "F0gl@mp!#1"}, LOGIN_SUCCESS_MSG), + ({"username": "any2", "password": "F0gl@mp!#2"}, LOGIN_SUCCESS_MSG) ]) def test_login_with_resetted_password(self, fledge_url, form_data, expected_values): conn = http.client.HTTPConnection(fledge_url) @@ -832,7 +834,7 @@ def test_login_username_regular_user(self, reset_fledge, change_to_auth_mandator assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert not jdoc['admin'] global PASSWORD_TOKEN PASSWORD_TOKEN = jdoc["token"] @@ -860,7 +862,7 @@ def test_login_username_admin(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] global PASSWORD_TOKEN @@ -880,7 +882,7 @@ def test_login_with_admin_certificate(self, fledge_url): conn.request("POST", "/fledge/login", body=f) r = conn.getresponse() assert 400 == r.status - assert "Use a valid username and password to login." == r.reason + assert "Use valid username & password to log in." == r.reason def test_ping_with_allow_ping_true(self, fledge_url): conn = http.client.HTTPConnection(fledge_url) @@ -911,7 +913,7 @@ def test_ping_with_allow_ping_false(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] _token = jdoc["token"] conn = http.client.HTTPConnection(fledge_url) @@ -982,8 +984,8 @@ def test_create_user(self, fledge_url, form_data, expected_values): assert expected_values == jdoc @pytest.mark.parametrize(("form_data", "expected_values"), [ - ({"username": "any1", "password": "User@123"}, 'Logged in successfully'), - ({"username": "admin1", "password": "F0gl@mp!"}, 'Logged in successfully') + ({"username": "any1", "password": "User@123"}, LOGIN_SUCCESS_MSG), + ({"username": "admin1", "password": "F0gl@mp!"}, LOGIN_SUCCESS_MSG) ]) def test_login_of_newly_created_user(self, fledge_url, form_data, expected_values): conn = http.client.HTTPConnection(fledge_url) @@ -1013,7 +1015,7 @@ def test_login_with_updated_password(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert 'Logged in successfully' == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] def test_reset_user(self, fledge_url): conn = http.client.HTTPConnection(fledge_url) @@ -1032,7 +1034,7 @@ def test_login_with_resetted_password(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert 'Logged in successfully' == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] def test_delete_user(self, fledge_url): conn = http.client.HTTPConnection(fledge_url) @@ -1117,7 +1119,7 @@ def test_login_with_user_certificate(self, fledge_url, reset_fledge, assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] @@ -1130,7 +1132,7 @@ def test_login_with_admin_certificate(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] global CERT_TOKEN @@ -1157,7 +1159,7 @@ def test_login_with_custom_certificate(self, fledge_url, remove_data_file): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] @@ -1222,7 +1224,7 @@ def test_ping_with_allow_ping_false(self, fledge_url): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] _token = jdoc["token"] conn = http.client.HTTPConnection(fledge_url) @@ -1430,7 +1432,7 @@ def test_login_regular_user_using_password(self, reset_fledge, change_to_auth_ma assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert not jdoc['admin'] global PASSWORD_TOKEN PASSWORD_TOKEN = jdoc["token"] @@ -1458,7 +1460,7 @@ def test_login_username_admin_using_password(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] global PASSWORD_TOKEN @@ -1480,7 +1482,7 @@ def test_login_with_user_certificate(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] @@ -1493,7 +1495,7 @@ def test_login_with_admin_certificate(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] global CERT_TOKEN @@ -1520,7 +1522,7 @@ def test_login_with_custom_certificate(self, remove_data_file): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] @@ -1572,7 +1574,7 @@ def test_ping_with_allow_ping_false_with_password_token(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] _token = jdoc["token"] conn = http.client.HTTPSConnection("localhost", 1995, context=context) @@ -1601,7 +1603,7 @@ def test_ping_with_allow_ping_false_with_certificate_token(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] _token = jdoc["token"] conn = http.client.HTTPSConnection("localhost", 1995, context=context) @@ -1722,10 +1724,10 @@ def test_create_user_with_certificate_token(self, form_data, expected_values): assert expected_values == jdoc @pytest.mark.parametrize(("form_data", "expected_values"), [ - ({"username": "any1", "password": "User@123"}, 'Logged in successfully'), - ({"username": "admin1", "password": "F0gl@mp!"}, 'Logged in successfully'), - ({"username": "any2", "password": "User@123"}, 'Logged in successfully'), - ({"username": "admin2", "password": "F0gl@mp!"}, 'Logged in successfully') + ({"username": "any1", "password": "User@123"}, LOGIN_SUCCESS_MSG), + ({"username": "admin1", "password": "F0gl@mp!"}, LOGIN_SUCCESS_MSG), + ({"username": "any2", "password": "User@123"}, LOGIN_SUCCESS_MSG), + ({"username": "admin2", "password": "F0gl@mp!"}, LOGIN_SUCCESS_MSG) ]) def test_login_of_newly_created_user(self, form_data, expected_values): conn = http.client.HTTPSConnection("localhost", 1995, context=context) @@ -1761,8 +1763,8 @@ def test_update_password_with_certificate_token(self): assert {'message': 'Password has been updated successfully for user id:<{}>'.format(uid)} == jdoc @pytest.mark.parametrize(("form_data", "expected_values"), [ - ({"username": "any1", "password": "F0gl@mp1"}, 'Logged in successfully'), - ({"username": "any2", "password": "F0gl@mp2"}, 'Logged in successfully') + ({"username": "any1", "password": "F0gl@mp1"}, LOGIN_SUCCESS_MSG), + ({"username": "any2", "password": "F0gl@mp2"}, LOGIN_SUCCESS_MSG) ]) def test_login_with_updated_password(self, form_data, expected_values): conn = http.client.HTTPSConnection("localhost", 1995, context=context) @@ -1794,8 +1796,8 @@ def test_reset_user_with_certificate_token(self): assert {'message': 'User with id:<5> has been updated successfully'} == jdoc @pytest.mark.parametrize(("form_data", "expected_values"), [ - ({"username": "any1", "password": "F0gl@mp!#1"}, 'Logged in successfully'), - ({"username": "any2", "password": "F0gl@mp!#2"}, 'Logged in successfully') + ({"username": "any1", "password": "F0gl@mp!#1"}, LOGIN_SUCCESS_MSG), + ({"username": "any2", "password": "F0gl@mp!#2"}, LOGIN_SUCCESS_MSG) ]) def test_login_with_resetted_password(self, form_data, expected_values): conn = http.client.HTTPSConnection("localhost", 1995, context=context) @@ -1942,7 +1944,7 @@ def test_login_username_regular_user(self, reset_fledge, change_to_auth_mandator assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert not jdoc['admin'] global PASSWORD_TOKEN PASSWORD_TOKEN = jdoc["token"] @@ -1970,7 +1972,7 @@ def test_login_username_admin(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] global PASSWORD_TOKEN @@ -1990,7 +1992,7 @@ def test_login_with_admin_certificate(self): conn.request("POST", "/fledge/login", body=f) r = conn.getresponse() assert 400 == r.status - assert "Use a valid username and password to login." == r.reason + assert "Use valid username & password to log in." == r.reason def test_ping_with_allow_ping_true(self): conn = http.client.HTTPSConnection("localhost", 1995, context=context) @@ -2021,7 +2023,7 @@ def test_ping_with_allow_ping_false(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] _token = jdoc["token"] conn = http.client.HTTPSConnection("localhost", 1995, context=context) @@ -2092,8 +2094,8 @@ def test_create_user(self, form_data, expected_values): assert expected_values == jdoc @pytest.mark.parametrize(("form_data", "expected_values"), [ - ({"username": "any1", "password": "User@123"}, 'Logged in successfully'), - ({"username": "admin1", "password": "F0gl@mp!"}, 'Logged in successfully') + ({"username": "any1", "password": "User@123"}, LOGIN_SUCCESS_MSG), + ({"username": "admin1", "password": "F0gl@mp!"}, LOGIN_SUCCESS_MSG) ]) def test_login_of_newly_created_user(self, form_data, expected_values): conn = http.client.HTTPSConnection("localhost", 1995, context=context) @@ -2123,7 +2125,7 @@ def test_login_with_updated_password(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert 'Logged in successfully' == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] def test_reset_user(self): conn = http.client.HTTPSConnection("localhost", 1995, context=context) @@ -2142,7 +2144,7 @@ def test_login_with_resetted_password(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert 'Logged in successfully' == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] def test_delete_user(self): conn = http.client.HTTPSConnection("localhost", 1995, context=context) @@ -2230,7 +2232,7 @@ def test_login_with_user_certificate(self, fledge_url, reset_fledge, change_to_a assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] @@ -2243,7 +2245,7 @@ def test_login_with_admin_certificate(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert jdoc['admin'] global CERT_TOKEN @@ -2270,7 +2272,7 @@ def test_login_with_custom_certificate(self, remove_data_file): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] assert "token" in jdoc assert not jdoc['admin'] @@ -2335,7 +2337,7 @@ def test_ping_with_allow_ping_false(self): assert 200 == r.status r = r.read().decode() jdoc = json.loads(r) - assert "Logged in successfully" == jdoc['message'] + assert LOGIN_SUCCESS_MSG == jdoc['message'] _token = jdoc["token"] conn = http.client.HTTPSConnection("localhost", 1995, context=context) From 6e9294a4d3857c9db1886352d1458a8f68a25aef Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Mon, 12 Sep 2022 10:52:05 +0100 Subject: [PATCH 06/48] FOGL-6898 Add description for securioty category (#819) Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/services/common/service_security.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/C/services/common/service_security.cpp b/C/services/common/service_security.cpp index 89e23d50d9..7836695e36 100644 --- a/C/services/common/service_security.cpp +++ b/C/services/common/service_security.cpp @@ -53,6 +53,8 @@ bool ServiceAuthHandler::createSecurityCategories(ManagementClient* mgtClient, b defConfigSecurity.setItemDisplayName("ACL", "Service ACL"); + defConfigSecurity.setDescription(m_name + " Security"); + // Create/Update category name (we pass keep_original_items=true) mgtClient->addCategory(defConfigSecurity, true); From 0f048fb68fb529c1a9d5564e02da0d1239957f28 Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Mon, 12 Sep 2022 14:07:48 +0100 Subject: [PATCH 07/48] FOGL-6677 Update API Documentation (#741) * checkpoint Signed-off-by: Mark Riddoch * Check point commit Signed-off-by: Mark Riddoch * Check point commit Signed-off-by: Mark Riddoch * FOGL-6677 Updates to REST API documentation Signed-off-by: Mark Riddoch * Update wiuth review comments Signed-off-by: Mark Riddoch * Add Grafana Examples Signed-off-by: Mark Riddoch * Update from review comments Signed-off-by: Mark Riddoch * Statistics rates API didn;t work with lowercase statistics keys Signed-off-by: Mark Riddoch * Start of services section Signed-off-by: Mark Riddoch * Add section on workign with services Signed-off-by: Mark Riddoch * Update with review comments Signed-off-by: Mark Riddoch * Add deprecation discussion Signed-off-by: Mark Riddoch * Fix typo Signed-off-by: Mark Riddoch * REST authentication doc fixes as per 6677 changes Signed-off-by: ashish-jabble * other minor fixes into documentation Signed-off-by: ashish-jabble Signed-off-by: Mark Riddoch Signed-off-by: ashish-jabble Co-authored-by: ashish-jabble --- docs/images/Grafana_Timestamp.jpg | Bin 0 -> 31168 bytes docs/images/Grafana_asset.jpg | Bin 0 -> 77112 bytes docs/images/Grafana_ping.jpg | Bin 0 -> 185001 bytes docs/images/Grafana_reading.jpg | Bin 0 -> 192440 bytes docs/images/Grafana_statistics.jpg | Bin 0 -> 202272 bytes docs/rest_api_guide/02_RESTauthentication.rst | 421 ++++++++++++++++++ .../{02_RESTadmin.rst => 03_RESTadmin.rst} | 223 ++++------ docs/rest_api_guide/03_RESTassetTracker.rst | 129 ++++++ docs/rest_api_guide/03_RESTservices.rst | 398 +++++++++++++++++ docs/rest_api_guide/03_RESTstatistics.rst | 177 ++++++++ docs/rest_api_guide/03_RESTupdate.rst | 42 ++ .../{03_RESTuser.rst => 04_RESTuser.rst} | 0 docs/rest_api_guide/05_RESTdeveloper.rst | 164 +++++++ docs/rest_api_guide/06_GrafanaExamples.rst | 159 +++++++ docs/rest_api_guide/index.rst | 11 +- python/fledge/services/core/api/statistics.py | 2 +- .../services/core/api/test_statistics_api.py | 2 +- 17 files changed, 1593 insertions(+), 135 deletions(-) create mode 100644 docs/images/Grafana_Timestamp.jpg create mode 100644 docs/images/Grafana_asset.jpg create mode 100644 docs/images/Grafana_ping.jpg create mode 100644 docs/images/Grafana_reading.jpg create mode 100644 docs/images/Grafana_statistics.jpg create mode 100644 docs/rest_api_guide/02_RESTauthentication.rst rename docs/rest_api_guide/{02_RESTadmin.rst => 03_RESTadmin.rst} (92%) create mode 100644 docs/rest_api_guide/03_RESTassetTracker.rst create mode 100644 docs/rest_api_guide/03_RESTservices.rst create mode 100644 docs/rest_api_guide/03_RESTstatistics.rst create mode 100644 docs/rest_api_guide/03_RESTupdate.rst rename docs/rest_api_guide/{03_RESTuser.rst => 04_RESTuser.rst} (100%) create mode 100644 docs/rest_api_guide/05_RESTdeveloper.rst create mode 100644 docs/rest_api_guide/06_GrafanaExamples.rst diff --git a/docs/images/Grafana_Timestamp.jpg b/docs/images/Grafana_Timestamp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1bd609671464946eb0184ecf95021e7c90e874d1 GIT binary patch literal 31168 zcmeFZ2V7Ijwm7^Mkfu@uL=b{>=~7in1f+>bQRxurAiaY`f+9r_5L8eQP!SMm(mSCe zz4scB-VzXqkn-Q2d(XLg&%5Wnuf6a6?sH%#YwygSvSzhevu22+#94s$nyQ8>aO4O8 zsDpn15e3{;@pG^R04*&*0000A;OG&0fCPk&fPX-k13>y43;?{~Hvo{tg#zT@H$8ai zygB;&ucQudNPdTbk?$E5Zz^kOfZsQ*JZx-SJndb*h$zZ)_Fi6YmqkTgJVh+5T`g@y ztX!Q%{Vd!>FNlbV0&-A4Hw!CA8!rw^8#@OVdCsjWBqxW1wLGVRl$My5o3f3)gZe!W zo16D;+_JjoXm!b&6RN-==Xcr9+0EI;%Ywtt*~!K8vY$NXZ-rk5;qQ+{IXQmI;^ipM zX{e>cq3r5m!yzpqCL+cOzU^Ucds*+Q>fhf5@8miE-bi0xUlCsk5myg8(F>O@T@n=& z7Zn#526G5|`nz~p_zAmsa{XSyRU1z$4+l3d2Ui!4?pdVc-`A{`X7m+yE}>fTofwXfL^ONQj65 z7nL-$NWYt4VEPT_`3W*p8~s01pr8THwzDozm*4m9@!)H zw3PsB`3_T;0RUM%k+@?3cKJL2;75qW!!jZfp8?wJ;{Z^%N2~+rD1Z@C2a+S4z)`v* zBy>lJO#lRZm+Z)I>9>Numvxkcl?oBl}K>NA82a1Eh3h z^ye-p9y_ILLC)#UApRisEd`fSK|P~hADUaj(&Hf|71L?vGb}v3eEjDHB&DQfE?&B< zd{sqNOnJHH2`TyaejPdL`@Q3Iq-5tV9HUp%CAV-t#VP)P zf00jtwEmc`TM{Jzj_40Evr7WV?NT*vJz24 zBCyquz(^uo@0u47ftmM2V9t>};^^m5!t`K`6%jyc5P_yXd`;H9Rw5Aij0il=xyMh< zWpx;!w;Myi^AUklYI}R>YY_Z_Hi5Tb`HfK24;4Ws#uIW7`zugvV(Yu0!e3SXLhQc{ z`Q(gE-j7>wkq(Pv&7K#5?N240978_Hf^36cv ziV^D%qx6Hwm5Nb0V(s*!+_nD^^TYBCWU&Q5%H6ad2Ga1W4wGu@KjiKYBG;<#SCzjI z`|m_P4yJcUMs!~CSbW-6dY9+ER(yQenL&q~*h}D9eiyMUK_yt0fJ$fzmxN+9me7Rv zi7qntb8~rU?;Kz1oG8nzac2N@%~T)HB3Q6VH!6qaE~QPcGR1RwckT^uYo6sA8oLz& z(GyH~b2NeED#o-|OdiVH^99Hn!L)k1bs9J*}JP6?TNmc~WoY{M%?qT}(8DQL?QB8OnZQ1g>V| zdj6qFl<1A}>c>2Qbc1+P-wHlhkTlSk+amX?s$)M_j!uaFn%#BkcJbKK z7_4q@gw8*L&9{}qz^uJKRE;CJcSPn28H2&wQ5-imH483PgYB?-1JgjsU)~TB@pdP< zA1#{&2vR1nUVmxBqsV=XG>GCed5W$Ih&>fA7V=Q382amd4(^+j`^n|HyOKwG`pol* z098QK%+B-(;lP!^TONgIWN8guG%Qiy3p>oK&N^TLmcStb_}^uglvLDKM7Os~Cpx_3 zc7G$(-RTA{UTDl7xk9U}9Vhd6{QRx#^BfPw6xpK0gQx_vOVOfHBGpQATqmFTcq`Mr zG-fuk-5%z;;QZ)V>vNeUh;Pb^cAX{aaJ#qQ^V>XX^W>4Jh?(ZZ_q6<1H7ka0gDYCy09#PLN5WnnHjDQS{OTwB*tJKS zgb^+FHrL<>L2LYB3s1f2`A^cED}u>r3O!RFxZXU~W@~$iJLP?1g@$|(UKh*t25y1L z3=X6!TmQzrVfS{`Kr25|Lz<^#tY*4@I>hFfO!0O@0yBU5F>S^yRL{e}BiQtLHu4q% z33~lxU9Elba(_vdMOa$(t@)JpN1Z$`xPYm5g4+cxZ5^-n$fpH!H=; zqxB~CTzYpSVKkaq${*}~5N=S?oD}!ZbRf`TSux7< zJx$u73LL$XF((YMBnHmc$P2?8?D{25vh)tlFc-P{TX+Xfw$=fbNN!(g>80rMJR;Bt zp|94M-J*63WI$uf9ztoa#_#*GUrT!Cl5^&rhIVIc1xY7$)F^G9Lju18FW=RsPHCuq@4SqS<^HXK2grf*F6g>qx`9?A9u#v!euWz zZ^hyG1>9zWZ-=k^2c7Q@UZ^ayBRK3SWwi?`XjpRe`B}(S9%Lix{ z4?2Ivl4J*yRrfI~A5A;{dD6}EHd9V7`wkHxlf-UdB=&+aOONDiFiR?f)xz^@_t_oI ztdwhuD+?ZWOI4Q#NVuLD=?ow4eo%_bX)DLAw-i8UUnvM-RAUd7%^g_G)4d(-3G|pJ z8>BZctJ-KC!)CuAJ=%VY*8S;~uldgdFB5tZOhmu|##}#71fnh%IT|b zPiYwxK4cKpbn+rI8<2nc~Cu$nn{w;fm( zWAF)1l`W}r)S4IbAX=e&%O;;ocYwagxHE2M3{~j}sarXn>qgxgU!G~*(r_aGI)wJz zGsm*c!y;LR79-I}?JCz(D}hIc08NRHE5>3YlEsy^8bWc~)K#*V7U1|AIh11=z|UD7 zP_GZAsgN`-0B#+9cns zHkY?^uc#(I6swQ(v|!uxxdHN>?agiJCGOOlVBO!2?9*&?pg_79Tbnsq9WXmZ)!G;} z?@F>#x%bv8<6K0Ss7>M`B@1(hOne@P{^&`PQ%|TsG73RhgHtV4(W3dzX@YCsI)(^D z&()ge1z*7^6rd^+%|x``61HUo0^b$6Y|aLznVXy3g%w#}AC`9OvdUL;DWk1>EEm4F zeQAe>Bw(la)PrasKe|@n{xbsInZUjniF^L$RYg4n*~A?f)>MI)2&6C}_d5`n+f9xH zzF|2H@s5ug<$O~rD79Xl(X)64UG<~2DEtdJDKS#_&e^zOZ~hMuSyhFa>?Mt!Vj&ZNUPA)B(}#^cWII*&Oo zseRJ`UT}Mp(w?|jC4XfT$bqX@M4;tvZBw zAWzj^fM3V9=GG!HT!s}xydq}wY6{mc0haus^cO-%sM6l#OJQjD6R$5#ntJH8!+!w9#dRp?KYzlH*VZ{o&pjlD6(ZlAho%)$(U?Tq% zZ!XF;hCq!rcvKuZXXJ3&;oZj^8D zr_{*Y*&qU~1*R`;VU_MF{QA~+KD()LL?j44IA}hUH);!*GqaG)zPPnp+%E!Cf2giM zTQc{&<@0MXf6_n;#p2|;J9dn*7((Oq0R^GEKKD#@OhPpEQv_{pMaX89Mdi`m25wVd za4!aqU4W%lBAQ(p4X=EXd7&^JB@j3Bk~5MBMAV+IEt6hZFxi|fzNQ>#o#@+NXW_TC zo{CO@-H&89#|&hwpP0e!ImV^i+F5pcXmclCdrHOsF6iIkf)e`)Vu+$*#HJPzK%6E5 z;c17mYJ@K{`xpc^A~9lFtm+)0yN?J|$l!4>0%y$n2ITM=Vx}4NfC}8@r!Iv2@PPlv zoEh(e{(D{(+=ZYFaEy-gz73Et7MVuKNk7NNo1@D-Ne-K)fsjiDp?M0&#ai5%sV&uvcrOVH!kuT|g>9BmeV(0CKSU8Q}pJ zmI%CpVd$}`gy1DCBKBYuFW|E4zy{Rd0_5QrP^mcb3L@|&0{7-! zHeS08xy%F&2Zxr=T^oO#?|b#7h}pauc5PgT0{B*4Kny|sLky0wW4_88-4lvLvxB{l z6Wq>-K&(b<6M-uQI7DYYHsb7UBA`r3fP4x3kct(wYrP2~peGdcqBn#7aqe4Sn|d&P zl~~6{#QxmhN@$PB-__;^+iwrHABv5TGXP6qNdw6c15VP43)};JUoGj>^7lC5& za81n4yh7IDRqRS2hhKZcc*}-!+@M;f=rg9zV=w7h10?8Mg$ywddZ{ppg8Afecic+k z^VlPvlvc`B&qsT%kI?Lzww}5Cd^0&Y*Slym><5;C{>V#NAM$T~Gx;CDBme(!=C4}+ z2aC;LgY#=}{zvHVUxfHC2{C#4)g7UQ@{%3KcSpi~j#F@-th37X^d1FmHI517!6Nd2 zWdx$AkxCpO$cMhL!uJgJ;a^yQU*J^Q>z;H%hhpAaafaO4Kw&xL?(HrH;gu8*+c%GP>5VElW&sDgTIB9BX-pQ#g zu0j?sdF16ry(RFu%h?zwg>}I2F6m*)LR@DW0#Ek~<#G>>i!S;MR6xQ6^=JZuPUfGDQnFG}<@&G(4)N4K&QM@4EG{-H>>0ot$Ppm6x|+ zlTqfY-#4F>vLw3g@9yMN8*O?skL{tiLmVvs|CbA;|Hl2$O`AiTI9gR(QK8Cj#-Yi;=`h8 z<&NnUsu8T*$_uKP&mTTg+e}#4O#>X~^P#DGN|@cU`ZSD(!&#d3;^B}_MdjO3k)LTH zB~IINQ|~nvT&5OwUSn>Hu(fyyJfC}C;h&t+5idT{-ES;>wFoXF@n}X6DNs2zl`EHj zI=dIU_6I%vPGR}|OZb-r2xOf5gzeslDtfT?LTT^1WE=gQe(ku0|J=!-=Voyqw`>o) zk6j^+NeMiSJC7!h#+l7)Ni<)6J${viDfNT-c(|4Lmx)tRQyw2Kyg((%(cLIJIhS=S z>b%EPyRLD5QSQ{9cKZ5^vrg6`*1x`s&-&Rtg&Mi>HOJ9!us^q`L{9z?;uqY+(wzSK z-cYf$aoTe1%7`$67XN1OTTtB_4a9HNvhvj^qyy2?5DV=3W7L0g& z$vuUU>8WP}_gN;f^M7uUCw2<$YKrBW>p+}vys@3W``lo!U(;3iebn*v=dPi5@>vDB z&flDLQ_pA1mpB!g6_za^mFA$P8a*y$p-+`A<5%-!>z|3C*gnT8%IQCP{_eBTug5u<|%fAcWC7D3XT)jhi4RBR=@P1o&EZfMNT_=f=r8PkVM;A3m;o9X#o>NH`xh^iOYAOLE zWs1%`)l^9Z^rjX5?l{s1N>L4;alOA=Xfc217{}p2K|cU4jd_v+DXTp6e%)&_JvPa( zJ#Aw0dDz}){u2MfS(lr=OQcUuwPFKLh_9I!mJC<-*>PiX2&!^DLZ42Q`LY%a$l1OK zv-X(zd)xnE4hJ@w!kMwcZZT-B>I(rUUK3oyBCyt`JCY@5WM??)&yDB|ZIF!UP*ZNy@naB%R+tEO6exXrLk8nFX`R3zTe5(C8Q}m=gacV_4k_oQRTs<6yE2I z7jG4sNv;LtOJ(=1WDn?j4A$$se!aj3+eMf$RV`ORZa6}Ukxjw@H?<6IMYL;JjX0Nl zZMq&&WPJ5gBL&qgg`VVX>itg&yH19 zymy}5dg#mf8tu8Wv^SNx58H;!tNjk#mYX;&;&L~Cx@LF!aAr`q4)r3JEIoI@xpsbS zN_p=SCiLxGk~Ujy$h(ZH<1-EwNJHBlSDx(@`u^YxDwAi6DD=g89(q18h;|?Xbl%jW zp^0G)V>ugnPOkaq2DuWi%mp}xKhIchugsc$ltymA{KXI-thCv^((84(5f9T2F< z6Ug?+(%WC$*o)KqRwY=om3I)GLQO+vuR0OPl3(?1BcruffgZayw{@%)W&gD*;1c;G zmwcCX+@NR8)&dCO@R)m+ElNfZT{@#K=n!>;M@&&opEqE@toMnyVf1k2CPExPqadW`{jF$vg zXQc@{>yb3$hpo~C?sCkH%y;&c$&G6obJVvhLoMTdSLrkxn7l7~N0A67K=`>xNz9?M zsS%0Dhj6nGetCj|T37B4@B5U+Cn#xi8oC~#7u}rVHm@KvrMn6Ef{F<_%sQe(BN)%6d8p z=6?Rk6J57&%bF>Luu9L>>Jlc332Ovpa1!};u# zzG9)bL$%6Srw_kXNN-H-KzqL;+5DR2oO4C8PbS!;H8W@)_bKI6r2iP_VQdhuW~srG zJi50GoVBqc0?y+IZz6DxAc^=LlKL|AaaE(+)nFSJqeS%&K_00t*xnd&=o-)Px&t)GdU;&X93DJIwkE!}`t5`m|nd-ey=#elJ|FsHr# z`E0ZzsCga+%8oS zukF$U?+^c3;c2xWMlA0_LK6tA{W$;hRd&&;K_RbEyA$#)&+A>ebZ9OxaUAQuv@U;7 zzdQG%A3H2eD`RCmw177kpD)zmd`bHg{z(Rt63MB(xXBAG()+s@*hZE1Ch`lkCFXbF zMXQ&SLF$N(ca^DI?l-E1RqN{yUB4ZhA_5~)M4)%L{9qllEuK2h;5}jZ6OJ)iXSIn# zgbUw;t}k_MoM0%9R^wvEd73eL9-PLN5P=|Ydkg*&KBXFpes&H2Y&ZWgK_a-JBfE9Z zYhX6DX|FP>UxQ|J9LCEy(CF+j%hnH+6V4ecnwAuN>rx4hm!hBeiTrLu`v0w&EA#G)gUniez4K03wYmNE)a$;(>8YD~#N)ta;Cu zCS%nRB`iLnGLU1LGOSqvm$3LSrFFknW#Vj)ApLDki8GMokQ*so(Mu@Dcc0VGTC>dM z@3JZ1=*x{xm3w-IH_1IJ;#rARi~Gv6ZzHbezPUu;GgA+t3Ji&O(`+Orfk1I%PUDEc zB)C^@_&X{7(>?xs1cEQN=W1(A^{F|qQLrYT1A}0YssfC5bJ?d47G*bNwZ-d53$t9$ zn{!O-`^1?Xw$x~&66&(*wj75@v&)BkdO5T$wR&-X&S{rj;~0cjy!vX zRA05j`SB}Vqn8h<3o_n}_dWOq?!lwv3r8*ymI#D0Y~N3JBWpBK2n!-Gb^}2Qju03E zjm^;Vyp8qu#PDeb-zqLKv3GJxG+Zn$k2_B-w?4cht{(B>Slz8S^{qf5FvdeTkQ&bG z3~4YI!6rMWIS!9^2WL9=Ps1EMo19B*jx7dg3OZJZ_8J!PyOt<3$Fg>k>9EMZ4#I&| zK6=&!+aUsA5C_5pXa7(4j(Y>w@L<@4jc6!A93u|UCGSuTRh4&&6)HJ6Mun3J@8 zl-->JtRzbl?tD-S7o3w8dUkF$^;{%@vTrt^XDmWA(tYjTi?Hww$z*D?sv_ilg>&w9 zx#lM0L?CU9r(>1wJGYe&C2W(8dXj}h6zMzfcPT?d1sfVeD2Q%|(Ki$EK0|oHG z2n!hX>NH1DB?b|-=Vv#^k9F{R*V3G5rsR{*UKv$g$25JxRphIHxpHyTD-O?TW^lOO zaMX@?5)|YK?q)t;4BRRkTcp&_U07P?%qxgIq0LRP&#Pwi$n!a{K?Dqvo90rBo$(_vu-v;U_VT(SBzC#L+O+b3F1^*E-t3FLMT zf8a^H*hBV$`Ge)lZ;2C#U*?;9WUNBe6I+tmhm}1WQe87@W7aElbU5 zpJ^}p(6-wCbEnR6i^XwG0c$2IrG-!FYXL{P5e*u1qTj&SEN}yAESSI9bMf^iBAP@2N9b{!5}a>N!+AnCf;-?P$FnZ!!i#O8ddK<%5G+~F znG1Yw9JYR*n=_zX0|RRM3i=1nOs?=}Tj!7qzb1I68y&!Kerh1INx*W4p=fQ$(Vp2J z3cnbAj7VC#_Wcj`rHNm~$D6%{bBu?R+_T_Q{d!I?b@|E59p6H@)N=Mf>A^S zZZo(jrrLNnFDlJ3)ay{t#4(=ku5`V%H_xM+$8_dhNUS*MWk=Sa8$4i~E2STD?-f3c zz_@JAh(?Bfbq%>k6VB6rQ?qyDPHeoeQVYWj=Nl`|^9@@2y%IrJeA1bx%;%v@|Ecgx z!@fNvCp5sQcSXbX5Aq|c-Gvaxt8Zpv4Q?8)=V+SsWK%v7uWPwNckWQG))syJrP*5< zcZ3qiLmD`RzFfF6c{38y_+GtM00Rm68nEJ8TqE5r@#fPLGqa4hzNFhZ{gqh}eb)A2 zovklUn73aE1l7||lp^_0g!4r8r2Kh7*-z5Qf0EPxEVrBAMgDhY8bHegZ^_-COM+22 zlnzI7a5XeqOEbq|n>ZIis)-hYA2D2U@>K*Y+| ztFUwLTV)GU8_GpbB0e{Q@)<^lSXQdSpCZVc;CFB#l3bP%cy?^Sp)8yO13Cv$schJq z&9C_dD+=d_r390ur4kp{9TKE79=r>$%-xGCUMW-AY`s;+QqHk_z+nIbQ<8og0@qu+>2s|1zmuEQ|uN^htdM+Um*(RzcMm1(7l%EA`1vN~VP}S@Ed(FMyT5d=ho)b4i2M5ac?^ zY%Vn_9yt$Xb-ed*2J2!n(Z=!ESxHJ^%HG^e&1|%!gfh5rKP>Ue?xOZsBGHv%)%Ab-KaYP49V$V^y(f2FQ?K< zuE7}m0-D_%52WG~an}fjGbAhlqID*o%ad5)=^K7jYqTk1m3=*aB(Qs zxb0=M0W)sx`AA8wWjo&4X>&1DD)cy~tiY3&_h^dM8;-d{(D?@K#%~dz$_HiEXA{Dx z2@zO+|KX1EU#PN?wV7bap0S&RGn^xP3xi(rl4}I|ev>+SthuJy-o3ELi%}t=*_^ai z-iI{Fa;r0etCNs<-s0-J2%A)zz|OF}ujrYuul{hA`6LQCHanDtknYzF!6qNYli43~ zj@PP3*JB4IF?TMcSrP`e|yR4eBVrLN`RC zJ^7-%KzBB67vn=e*GBa`i-G2@?!jo^s?&7pt238PS}J6_6x1eZTD7qna^NO4=st9R z7ugc?(;d=J3N}j90AWXfUbBbh3|LuFS@xt;P5x zzF_hC#&#y@*&{Ghzu-L>{xLz=5kUv1K~FSPy1YooX4eN&7o+vxSw!)a4tXmF3gxj} zKgzymFFgM`IG*0(F)(l|eUfG&^+%2Wv-%&OiGUX52UUaNs-&A}yP&0lelJ+0Os(*M zD_k+#@uqTS5`|QhjBaJwz+(C9{5Z0blIkwjr*dOKEvsW#&Doex^V7WuJIL5pGm-`_ zIIkYaw_4c}mcOe1sa4_4{Gmlo|6+$;nYUB@nJHFR`-l&pxf0F0c1h4n|GG^xsU&a_ ztf1>WEC^Dtmo>{q(sUrxl%!?ecx%M6h;GdiJdf8_ADHcfv$!~UPu-wgDlJHsa#lF!_Hg>l64|`Z6XrSFrbq0Q zlCL3d3Sj*4Ut78RjdjpM-*s@d07#l#^6sHp?eIn~wH!Q}7Sp8OD&!f;$g(+ms zc?o?FyY(Z^yqE26Ea66o3b|_yIGE1{g6{jj)QSgS9JJ^tVowka4THlFb6X79&KbBY zdOuW7Emy_S!5TBwI;ZYTWinoL`MLc7IscnS8E1}Ck{=LienpXZoGLcM5de^fopy6b2X^N@P(yoCYcy+oi^w@_u$Qo+t%mzjHXvPXA9ya zj~`oX4!GZgJ2fzCJ#zwgV%|)m)i<=qs207OSCg;CSTg-A6XC?W_B{R~uZ)k!SXn#S z7u_5z&$S5CIFfC|zb2(mNaxhCmFf4caQZio|k)-BD^&wR+E2u($g0-J>f<9|VyDRNjn-eTR~h4l^eRbXa{NfZ_`-Zb@ij z@k!2djJta|>hq!X25$jH$dIMma9*Ny6gT&VD97xBSe-Bl4&3SdB!cj}{KxYGV#ZUH z`?4<$Rv;U8C>Vg{o7Wl%RbX|{N?Un4>QF?%g4)!6ak#jqyk{WX-G&bFx;F z1f_W29Ut#PHdeG_0`5Yzr!MN+-YE+lDD#nsmWY`3GTgny<2{i3zG9ZiaIkMteflUkADZRK zG@lhHcqe^ZhYa9vHbQT0P-333Jc3Gk4eA6PpxS&YoQn5N zB?5{ORZGPf+4Gd?lUcjlqeNi6wT)<}Eblfqq5DN_5zU6b4ym zP8Ez=dbEoywBPGpb5nEOvxhhZa+XH-=&(*pdoI<}^J?14xx_fqYYP$qikpaDEY->ed@IA;JqX)%9-)K*jj*oYr{S}b)JWTe< zHbiVuwy}!wO9$>s&PZ6DpRZ1c}U`YTsyNrMLXq-nb z(`5xB@EOr|lOoYQ#`vsSIls^~{hDE^nagIL%^LHL1AC6%JKm$XsWL;uAXESCz!mq? zUHccA4}y(BRi1$Jfsz-y9`#e*b&{HaHkGj~=I!b0^>~VgFYVX{7_pG>B#9@eNpG+# z-??)nCKCEDk#JWVM1qxyPgJHoMKk;K7qN>Roo|A{T_Gz-3-lHa{e314TD~o-O3U;1 zc^&HtY~Xgn)6o5I2<#N(ryR@FX;JU0L_cAD34W#^Z7zU&P`vJkH6nK!mIy>Z6l9P$ zBGJ-iIN>>GSbYj-5k@~~g>Cmywj>R=gLqD4dubcVd5&#y&`F%R2RTUudZ<$maY&p? z%+E!V_1WoTljd^~jh=qmut6JSVG6!P`t-$kMQ;vH4JI|R!M4|*8G}3+KJh4?y8wAp(S&Rzg&C z9{#5uWz&MbsIf+ILuG;LcG_3mCy$1nsH3Qlp$S@Jf@;Fx*pwqzgfHcYS0=dPRD^$lWwrIhp>^_#{C}?Qac`ZTua}h4! z0YIX-0PxVCTj_VMe~meVooPYPRjYZ0y~!HH`4+x>+fp0b`95ZnV63IMa-}FicXxXj=!{M z_E0R=C63#v>4T~m1!=_2U!paAhdOPb+Uigb?t{S*z_kRIs=YEyZGm0>n%(*^2A{3_ z=@bReH%^%7o$`b)F?Xf6Ufnp&o(xVo$;j}zIglpt7zPzL0`E{>$wXPjfRG4_@QtsQ z0olsJRrjNf$jNfyX?3lNF)s;?sF`mlPtbn|+TT%qKhaXE#O7%=Ruv!E&!l@u6NXp{ z>A@3V1Q~UZNF&y3|Duqf%8TQIg+IQdHVT&|0&*gVE%2} z*d-YzvVFnUYE`36YUpQDO#6x9j(A!5c@k7vX%4WFL_mpgW;qqJI< zQ`2>MkzhhvL-b6;Ei-3nI) z0~m8a59RdpME)t>?%*PzRkq_ zR_&^PX5v#W-joY;MmK=CDUwSQ)IlVw3i>3ZEDeaqsdQhIPho@g z1lnxQ9NW~Ra`;H!7r3u!bHsv;i-hulxh@`@id{!ywg@FZaFTB4X|-AnaBXb9x|XpP z&0Q-sl5}-&A;qyvZdK;k@SJA+jD+UtR|Vs$-(G*>NqY9oRQrjX!#qv6IY&}+t^AOy zRE_?El~KOv63D%z`~`0uxP`h(7;k&{>5wa$d;ZHhv;82g<6A+ZOI7_$)ZwC>+aenx zb4D9^mXoa3v1O#kblO$V7#@93mpF-uX}%9@z9)b+Z@n?_Rha);8I41Rl9fh=j#72r z26rLj@p_pG>hcW|-fEdcU&1TI{0w-iR~cd@fgu0={IHiIQ73K^Wr z2tg7euC3%t=~sreQ5LgTFCE<0Oz+$JViNh8SDf@J56|tJ1xmpW!#?e1If*FHM6h2f z!S`^fpI()Y7m)q}Xz-@~%yJ4p@oWFLkUq~Q1ZdRE z^^jscQ9a?JwS8%RS}xD7m2IbK7v-+kdd*z^;5)4q-7*qO|{D>FdXOWY@v`v{e$Fiw~5!OuS<`~#rz}~e%8b*Q=m~b7$^`p1cd}j zk7FP9%q4`w473^6o?>He?r=Ofe(<82-b6*jD(V_(sG3R?Rm%~GC<$BGLxhX=crXeH z4gw1Dpjw0dRoco0b7c$e%id21g}IQn0U-}@6G@|wo~)Z#&*y`F0_b0ftFt`;A$?z& zLJmCx2hC4oO)Sv9je$JTjVk@?E?ymKWdrMJgXfB><239-q{xEI!@u~y7pe_BId|FJ z{M78sW5OjY;vF`oahk67kS8_L3zdGi@0)JhUgQNi15UZh0`2K~Ru`q*?fHw`EQo(C z&sApJD&+-L@tI(G0d-(Z0hw3HaS$nHfr@3-#5LVIHfRP^N!lx2GYSiwm@wdXunsq z{;k8NX!I_mv~}asM{KYX2AtnKt_D^33CB_b&w$M#+na4~O_Kl<^~~{eR1QDn`)n6?|9-O;-k!L_Sb6DhES$RQ8vYzuj($X6D zMWt4+*sBk2AiNB`0$6!#Y>=~Whyb{_v}YcbG2vIg0aH%WE`PW=-rY~V0@E;yN8GK9 zW-PBV@&0CI@|auaVl%w$KWl|Af(2=x8VM_A+f4GtC=sUTI0d$X;;GrfKHjxEJy#!dPvJv5$`( zGi+I5k$`ri+Ux-KE9UL8I=nq4+3Q=Rfg{oc2%7itERw+wcBu80+O@#M%y@OA(y^wp z%Uja&R@rma4Oa6>f!bal^;`Qr3kNuxJ8u+TQ(MLH)b-$ZZh&WdbP)la8C(<*7}a?{ z+>~kxH^sjAfHTL2ATT61OCC0FUA>TAQajHeHgWZ7Q-s;8=+SxIikES!+Pt;rv7oih zB?;SIM;@Hg-^Yo#9)L5WSuBZdZoYU_EAp$QG@CD$a^4hBCQJf+srqRry zT6s2L_*0F2;wgcT1*1*$VyH0glY;<~7EYZDm&8QvKfo#VNiC+d7rrzsq;Efa=P4yB z?Czdx7^28}S{kj8I&X$(z9$nh0;?$>C{~v;cy;3IUL>pLD|)^NiuxC{8WQgkoZQ~N zl-YZZPnWYgRKzxH=?=OqU6#G^Y<#>sHuUi$3rZgHOG_1N25=J0THR%}#wfu$B!k>p z_-(#W*Uhc3Mkn^i?kL|Ypya4}q!f+O&)$}WlxT6%On2v$0&trNTgfQ4=4f}ghXLYXE z&wt_RY?+n_(pYq})J)KaExe%v9MM)QG%XbQ8uu+nQ6B?|(6yS(j_NFKnl)o`<5)k>M*<(Ke z;aVCS7Vo}iQXHz2>GrhsN!}*g+ew;Jse7jQx595r%aa-|2Ssn`v0N8k_#!`l!}-M# z^0XTnJc#mcs!(p0q&b@PddxEvtnn*0Y924;)uB4X)6Y(611nMSWNvmJm5?WGZ(00Ma&bH^j43;Dtw`$j1w#m)bEIZWK78&M_mv-BR>ZR*ghv+R` zobOrB#JIF-jzCf8`ZsgDqs|vMmku01rjg&BB|Fjlg@GHoMf+i*N{DKg)F9jM^d4%6 zz`lCmgM5Pxl&%^OuD;-UCUM@&2`)X>!T;o}=}9qW=7UfxGe2-b{?Ob(fwy#|S^~B5 zM4#S4+*tX8d85p8$%!#nGiYDVh7NbG1pjzM+y1^poWppko19=XqENIMM&b9YE|7F+ zmT8&;GwIShIyom=^r0of%oJSQrQ zIAeuH$Z~S>PEwp=yy522(aKo~J4@&_XBhPE2^)c)fJ;a}&VM8Az3D?Wj@S8v&fT; zfb`t02EO<*DESk`@CE zDa1;%aMwR~qEFScRmxUsiAs|NtCgAvg?lj}U5-J9ah&)z% z26rAaoZ#yoknJ}P3)!pXd~Ir6H||}y>T3+|!zXHW@h9@9-?D3A4G6k*T!sYAIt#6f ziG%<+QTBq9>5g+qTAW&cwaCE}k{Q`xchsjAA9Qy{n0Kv{FB<%WgERu2 z>j^}!!UO>?iZxi9X@HJ;&bqcB8SY+Id$gNMYq+w#*4lW_jF5>>cA%?@kP=$wDOW8Q z<^qIsZ!cUu_n7;Exu^3XH=Ls!YnItLzL=LHIS8l8@*CpZws4lR9N?`~dsK@$??6A+ z{@OzQO!wCFJw1{g!5^#D{TVlcyWe9r3Nq`~C~DcTbMvWP>x58%LpU-Dst;~qDnM1O6%_2^YEmu0n zrN54MJbK23E37T1O*KVQeI6#&%Oqryy?33aCI7F8WT=NKuo*`Fr55WtOT*@PuL~Ig zcl6FlUnz>F6msV1%gc8*eQQ;#=IKNg&2W6@b5o_k`m;k(>{4SbV+|S-UaiHHHa{h5 zTGjV|_Hh5!t)JGeGf|njMBHEc>7-&Y;nOk4=WNWIvUf_upLwWB0zDtNPX1=_qjXu_ zdHD}JOYeGzZr^)p%U<=kD{G!qODx^7@k(A|>(Q<2=Y7u*ObeDh@{uF$4Vzo-`{VaF zo1bpM5*J z^va^0AD&LSH(5w$Ud+U^BHfJ>0vm(w^46^U?e<6GL;hjj_`^~Chfm)=eU|^|F5Z2+ z(@a@hcD1Ta%aGEv*%a8dhqo<;iQ_>~L1qm9G<%d{q~_-1)7r82N2ixf3tSVZcSfs+ zaY|5qaD2q|Q^55=_D@Ro{%6=$|4TQE;UVM{VbDp!BLk};ue)A%2(`fG?gXA~m-%8n zZ+y=h5%$ZC7Ed}0fPJ(YU@2W(e+5`KE7yM$y-+;g@ATt-A>RiPcG5NvUVQuh=~X7* z(GxponRL!BGcTIB;#lFa!dXvN9|lgX!LuASSH(nR6*|zPw8gO-Yq3WKGCKq?Ry>gRIWW22LaLR-_;G$`yE=b+u^^9>iFDE;`vLzY!-UuyM|eJ>e7o{zZ{s)a?X>q zSymdb{^?u3#o0_2>uml32P!0@vMYg2@dMehT<;GDCf#EY_uij5tHMC}__;h)>wmxA z{fuDP@niNsar3{<^`C&zl<1B$Gyt5@V1EG|c7NOd+bt`~Zu+9TKN@|iTz=J_30gaK z)g5oOsr?&g&pe_OJu$!W>6-US{az~{@ZWm=t?5Ui+FJdluUEI#rv2R-dCS{6x@r2` zId={|I|AIiJe#H8NVbQK!G@=<9wll~y?<8kLG8vR|1R8@_~Pq+IBMVAwMKU37ldr+c`5Y{%i_=^!7gE&Lr>if9o;uE=v%j= zeZJrFIx%fKuS%e@$;QrjJ-?U<@rB&|z{%+!G55a$o1-W0|7`^pwEJHH<9Oo!-&{49 zfY$qW?a#5lrF^Vv)~i|f_DZB|xKeVo?bfkN*Y4(itvD0Dqe&u2QT33akeBcob@l>< z{;fqHzRjBzHg8{)`s9pBo?6GJgzC0WJ@@R+oyQgo{L_*0 zBTB~7v^3w%d`J6feW&~rD- zA`M3&hs%Qwm>(H<_CLq%^WfmH+?% literal 0 HcmV?d00001 diff --git a/docs/images/Grafana_asset.jpg b/docs/images/Grafana_asset.jpg new file mode 100644 index 0000000000000000000000000000000000000000..53860746c41af6ae00fb58268d7997f0332d29f6 GIT binary patch literal 77112 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 aRbTd)wt!wlkhEN_fFi2@?eoo|MZsUbjtWNr literal 0 HcmV?d00001 diff --git a/docs/images/Grafana_ping.jpg b/docs/images/Grafana_ping.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e1dfb0933f3a0f9f473f518b2c0fb0c5aa165a08 GIT binary patch literal 185001 zcmeFa2V7I#wlBIUQba_gDIg$KsnVrJMY@Pc@6wwPs`NxadJ_;35Ks^hY0^ZbgpP=a z6hVqYf`T+jC?Sw`m)~x>-`VG#d*1!sd+s~m3@aIPl{x1av#e46YeD`*UIb3)Y3XVK z6chlU1AYK967bXv@o)tI0|P)50026GlHw#l1yU5?2Z;9osQ;h=Kp6Z50IJM5fEN5c z32rwYQ~vGfk-EoJf1{~Nex7*QSVLDA{55v+cX9CvaEAtxk@RQX0|R}PrKEfUBpsZg zjxLf;P;aRa2VW^^$qQ0|DkQ|$!O6=dkk8S@&BI5Hf2$3_&*$N+#&0ffaKXS=!^Pc0 zC(Pf)IPAKKQ<#^Nk~2RhHp*AbCOZ0zY`Qzq70I&8u2}y%x-=@&C1v!NI|j!LpK2e>W*J4vx^EKsA1TDX<2qzgF>+ z{Ciu~`Tk6QO5jfk{3(GyCGe*N{*=IfKMDLp+i~#$Rh(c@mjTF|z{MM&sssh~C0{;S z$qT^6E4l{MKUFX={Xq-;L7tdAlQNSIG*GYJrGL1Ay8Tl zeSgyTK$_JbY!pa8{7Jk0g|7ZdJN||4`r{mvn;PIblOTP<$=$&jq`!i+xZ^MT-F~6} zS}%ACKzrkwjGVmmPx60l3Umnpc>n+nsBfshhnssK-(^rjE_}K^PLkq$G8bfI0N|&* z|5EGDr$6LK!A|#&eI8crx%nUa&VL5kJ_-PclfDlA4u2^R z{HDNC2e`_Dwfv+RS^(fk4w<}T4zhe60Ep9MGQNdOCYFOb`z!!-VaZ(pGaXgQkvb|0 zet?phf{K}f+z0T2*B+txBmGg(&$1|~sE^Rl($ODf08eN>0a^r9RFu?IM~?g)h!m0F zae$in$jP(PmuXmx9BBFdSY@Izp3n(gsqbdHIffRLb@Y#>Kg!N=>NKa2u*kXdqH^*I ziWilXHLhxEY3u0f8Jn1znS<;(IlH*JxqEm91P0v+4hap5xfdH3pOBc8ne`w$C--4q zeo5)mvhs>&mCqX*o0?y?ylQ>j)7#fSF!*NZ?fAsx$EoR0GqXt4(${axE8kbwFxxx3 zd)R&4!QoH7C;+Ozumyhqg|mO+iy7pLlA4-|n)WAO6qLa~8E2+Ga#ot=BWKlqvhG{BktGf{$n zRFsrpS5bk9nuhvkqM@bvBhmgf(fyI=e%=t#LhW9*lhx}d5W*2Mknt9Sb1ALjCD8MDXolGn&cjpech9dwa1;L~r^{I6HWtmEtt@PDcEj`CJ7B7ujafi#X$ zh<)ZUg^xaHF>AO|kbb#!^4Rnlo9t&MrILE}ev$beB;nn)o|5GX!Rf44@`u08tX=3m z1YM^P;SMgUB0>zOQEIbJ;`{hidUnR@ndDbWi%cC;Q=n1h#B&P4yRsHV)M)zzm>_OR z3m1eur8!Vjw_v?GWh9%>J8!E~uT}Oi_J-}3gDE3u+F0{3-lMG?UfMr45cBpHY<4jJuJ zBwfJVR@SO~z7{YP6ddGNEuLkl`n0jF?O3DiNnMc|m;i3HN1YD`Ut+ZGvJ<~+?fF{h zE0*Jayd`xo`+KL1;IpE0mO5`UnQr(QU%dDuF2Kad?i>EXYQ9f1UN1s*Y%e+F$EGB~ z;AyWa3ty&^Q|6kybI>gfG0Mx-w_;*$W`Dkmo)tTE23wOu>gT1 yuZ>r&?SMMYv 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]AEj0hj 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 X?MrVWDmt#4Yk=5aA!&~4=g9v8uJQ(A literal 0 HcmV?d00001 diff --git a/docs/images/Grafana_reading.jpg b/docs/images/Grafana_reading.jpg new file mode 100644 index 0000000000000000000000000000000000000000..89e44798fb8cf1d1a0430fbce7e26b5943dc9ee9 GIT binary patch literal 192440 zcmeFY2V7I%wm*23CPjJ&4N^p;cSRr~A|N7Q0i;Dhnv~FMBnr}-fPkWcfQVA1cS1*s zB1OP}bWnOi34ydZ{_cDC`nzxLeeeDM^O<=wb2lVeXP>jz*=y~#*4p1qnV`%9tXHq- zUjdFB0RTPl51`Be_jLkY909=45I73}z%k(H5q5wIq>g}pK$HtW{Ra&Ir@>zUph}4Z z=)hlg@MHY?=)d2kDSb`#?=;n$Uk_^C)YjJre{b4*J2-gwIKzD@bM&X2eSJOEWMw^k zWNh!j?Hpw6;qJ15ww|)`GIFwjIyBJJ*51{@SIEx6$;CrMc&ia5EaY-eL)c8&P|na( z+rimIFWB4RX7Ke}_Q9_9=kEzaHHFjz)dJl;-5q>wg#z8(JbcswHH80Qt_IS-vSo#Z z{&>XKRYTa^&{#+t?(HC?A|odwCk&SMzUQcR)9p0|EkM0u*K7-cGXe z=g*&)l~a&aP>=?nkoF1k@U;z;_V5w;cMg{weC)klJbhi@9zwr3+S-bBdl=-7V`r6ts;~Pd- z^snjsVc{KRwe|FL`&HQ8!`J(U?j<4fI~GE8%b=0R3NV7^9i6SckEfQg@wHz(|NZw5 z{(t?#jr}qM0boS>7q25S+r|Rs7v@*?j+%YxrJDciWB=y_!#&U}0&fw)kFC9@w=ZZ_ z-UVrq0AJ5v^kb0b^ad*h($9X;PJf|`f6;b-p;=y$8~ZAT4G0 zTfWn8^uN6qd<38~zNVn0EdPuAzc%?g1cEXEfHvGS$lJxq*;hyl)R2RazK6Yxl#qg) zf&u{i()VB9x-;>I9*=Mz`&*vNWdKlF0Dz+of6KG427r1_0AQ>BTb{&sP;3SOK(Tw; zdfWbmANYL)NA2UN2)^YP%~%TnH0cz|ju|Mj1OSl6DHK92g+h7@+U#fmXvI-l0k&gQ zZ)i%XjtB!s*^W@L9iemr5U?!Gkw4NOjDGPtN<~dWOLvT(ff0P5nicd2sHl!oQ_;}; z>WD`kfcF7vHX8O*@>;YUCbo3KUYrV#l5>uUTqXVpCF| zrln^*d!Ct__a^^s!Mpc`6_r)hHMMp14ecGBUEMt&d;5k*M!$}YPkckq%`Yr2E&uqr zvWnf_+1h~f!GEfwN5Q6|0uwbY^{+%rNBc*j`?qxLk3|0~G5$4CKqg0im87Dg0sk3~(H{Hj zz5g;n`3`z}mJ~F=M0Eu0OjK+D6d;TJ%#Ho2$Z#h2;lDor6&<|48)@)-cv{Bd3WH`r zED#$zqsB-T?#DugQh?53HZcsmco62WdRKM=sOqO1o#*sbFBWeE`r~l+d|DD@h7CZXspO1hwcwZ;+ zEsMVQ#Km1Dnt{Tz8wv3l+e%&)uXUydzP0jEeGq?N0$Jy#0NL-5SPDQEekkW$vh{mL z((e}!8~*d#aS8keAx`yo@}8VlrTPAnBYr!t*)5Q+_3%e$63@3l@s2Fmr0nx_MM?LI zYzF0aN6s<4!O)jD8^5=B<2;z6i)XB71qW$*i4bB(v3d_o*+?F{C5J`>i zq5xXb0%QtcL;gsnN6fCc0=PyScSgDj2fqR0;m@W^M# zlIOZ4>P~!cEFp@_%dx;iqOO7yNMJYN&HMXn(xrLG;nD0lvMssB0kX@%F}Es-)|4k6 z!xpqL76~AE^j+0fB}KHwiYnjByH7FiUOF~)!9Eike9+`i#}-~DrE->;OQa#BsHm)M z3g=l@crMeV?9x@^5an9<0OiZS4|0+k=>>B38H7Vql{}CoPbxzoOTQ5{F|v{CGBQ%K zd(IOS;QmxQvv5Sfsbin1FTq|Yutt}*J^X>3P0K!law<33@wI#|$_=KPM2)SA9n zR32#GZca$;D_2+yvU4l{cq$v7{^r7a$S56=%V2hEJp`+3iP>u1LPHih5T`L)QR_Jw zS21b%nOcswwGzY$jSlD|iRy@C;Pyqa-sv>SuHM)mm_eP;De@QC2MR!B?*Ut`Er~5~ za87nZk^<1P#Q3hMzAzjncZ(6++esgh{#3HhLah(loxEoGiC2pA=}vTW{e&KG;UHee z_m&yV!5&XTM%DG-cfiFa(JM7uJ_>EzsvmF2S>9i~w-6t@vr5XR0AXB#?S#3l4g2{m zh)c5Qz8a*1gfxyl?^8ZKp)Fi=H$2RYj#|*<*p9vsR8*Y~Gd|DKC2a?1L8uPF{U!+^ zE@fi1<&SKGl7lwJ)!$~|3Msf~UPcZyM0cfa6nbHVUK`Y82aa%g`x#$YB4?X*t9WOqY3G`Xx0*X!|lZkbt? z#i-a>3^7!2Wb?UtdQG*-|nN8Xj_p~gigg=TUh(Ay|t)1#D26v^>Op|7M#DR)eWc+E=A>ci>$p_D17S-;@2STa4r z1f$yyHWASYd;RHH79X}3WzD?XFThy&_UftncFE@){mEfutXaVAkIO9>QUsYUbkK+Z zC0dXwD1b{D%lE)RZM;W=by`%EbeZS}gEf+cJ$uzYD|!3ee0yruPTii61c?JbIEVT+ zj!VQt2<(CIwrLvd$&6X)P;fvmkl7y4dKIqr^#(8+GI2~*g)F#yO?n|Bk$BX6yXwlT zuUjOWc4%g>uT1L`j9A;0SS^CE{-D4D8!=IE8 z%8$5EjUf$2?jGAZIc#_d&i>HO;KjS1%qNrVT6d`$o_L#c!Ox*c;7WN9nNWi|0(F5u z&N_}&NuHC9QTv?t8Xw+falGwo*?h}L+IO1xeRlyRpF$2vJ$$5kjrXzlI0bUc+!RqL z7nP4hYm@2MF!WF-6yD+q;tcF@@O~uGDbIOa&7n4qr!(AmL|I~t1D7f|{K7IqdgxBD zAlR7Vap0R#c=4nJBpl8b+NVi}_jw=a+JU57uZD317Tij@Q{T`u<}M|@@Z_5|Q}G%D z{XJt*Gld4KzH(})tq?T(mB4I97Yi#wcq~-ih5x4E9F%2xas?fMPnY{J^*zi^o6k$c zqixCf(Nye?B_rd8DfzhUwTMj_k9+31vC2}Lo1TTQz4gTb=C>%Mx;<6|=Zt?&0jT5f z<;9_&ADn3wJ7lA?PT<49fx5TB zjvMU6e$Nkgxp{HLU*=_mdHiLMY4e9Xe4^vS8A#0avdQ80G0U}?@D|xvUXwS;lX~?G zg?XZ>m9M$NF}giAqWBzw7alrq7Vo60RvWGEQ*d9kB732(0i`dhaahSu3Iyk&G?!^$ z1nF!P*CJ9*D%{-t?mdko2R89=B~~hh{P>>^SnLjfN@#*Gxoah1&*JwoviPtA2>Gop#-AGqh0 zmT89L7T8=JM@vv+mQqDeU3lms#Lu1kd>nZd3TX0?J0a!SL{2JjX-Zb@DABgY$0xf4 z?6;^sunWAVR=rN^nQYFo8zlXd_3_Jd$G<*Tm@;ZBJ5ChAxIvghWdbKV_Onhme?>XJ z(!LUjHnhW`KaV-p#kcvV4}H9=(2ln!d~l$0Ew?$Fc0!fv;Atjb$=i^S$IgrKX%4nw zZ#=c=a=7-gG6+Y>lZRW88wlGRq6pRxm+=68;(PU{nj{|uL+Zj4Cm5~-NJ>z%y$sLX zgW=DX#i%pR8%-|EI}wGZ`C-RN;Wneid&g_NzmrqlIG>f?LB3J z3E>)17T;frPn}imgd7PS3gy9{FL0p%Oo+3hHD3|Nht}IwULOb5%w-Rk{O&%?PQR3I z`S8BIq4mKLV$ppy|C~3l!TkGQ^j-bjMRb%DCGL|z-L+O%0b0U?1UATn5G!{vkh}2-atGiRA?$t+`8P*^nruT^mN-E zPko|6G259iVSu5iKJnJ9(+CA{1&2Fb>v0~O3qEgthKVSXF?Xd5GnZHQ#ZMn$4KJ;Y zac8#|qyWxU`im+R2gs(|w*{ZnALvO=^o=uS4<>adg~2$XPTA2sP{vSs7sK4OF)uCk zu>>g}uEbU4Opyk0-wSzu9s(lg&Z(QFnXQ=-xp&AnPR%0;)ITAI?lon-7BM~PhNmJp zO>P{~;WYmL^vA+Nl^7`vU8_PKvKFICH`qX1tb0Jzy(qB33?t36MCtwaH$ z_)kn1#mv^Gn+rQe^3=JlLl{g|?AU)Ecg5z-i&7p2zbfv%kv z&7Y?0i_!O!(MtR;Ca;EHbGTT-nkJI8pUTbaZ3ZOY=JHXT%Z`Coig!aIxur{28{oLa z_zz-jU#n_)8Ul5bbNTAxmDob5@-Oo;U_q_OrvM;g| z``wyn@JNCt!VMc0E_-jJ`hvg-zSs4S=N6>BSM?6VbQfS&XyZA%9Akhcmj2 z2iHcIAmmBa52OO-k6#)7$y7s9^Se04NC7k!9Q~=5=)$dLx{|`OD}Qv9(6?}E&yj*D zKv#00#ql7&HF4MItYru08wPh9Z;ajxmvbxAPVKddXZh48xwkM6T@T0HG{9TV)9-#) zvF7R2WKmO`(ord_&8T>rb5Sa#yr?w1VA&Q)#78saMqSWhY`&KEDzaAMr?m&_S97Q3-)Z2nEc>I4 z^Fv^*K_1d%MZC@CxHg=!+U~WNbu;fJ!&sKZ}sl^_QT;b1r3pU zDSqDt)Y6z+3XM#53)2WUu?wbHqn^RYQ1J$gOcPlevlAF@lw|y6&y@;Z8t5Mqmwon} z+oX4Ufc&=JdESNdQ?8l#RDwe2K-O{0?n%Yw5$0F$xj_zd7yj>Wg6mt-N@TR|9BTXiRp>AgqBZ3!eKgeA)pTxGtBX1B( zT?+Wz%DTu-tM^%QX%M|I=hO;07HHW)mcpO+b8rvw^YU?d=i+bi;p>7HHfaGZ^GU_G;7@iLb+9$?hk$aoSLj$O1kX3Bk?`8s5vFX|G0g4`1AP`PI_W^~L0~_4Nf8$LC?fLQ?|+o**njf0lvVtf>&% z)c|@RZEA3+-I~V9p)GZmIagWEZ!8e=^CbfifJ~I3~-#F5M82QvkurVv0 z&Ry^4b2+zR=)OTq@1Dy`Kb+32e5?IJM)q#2)jxK<`l418UcI?@U(-x~ZRUExHoXo~ zFZ2{C4r+J8Zkm8YenHTOya}vBh$Z!4@E=z9WvK&PxvzO!>RFuPfXW>Fy!y_DKZ%vx zm0iwU4u3#^{?w#y9#*%~WbawPBh39mGQuuY$DKYe{YIKKCOZSMD|SovxQ!cVa2?$U zR_3wJdE>iJ)~Nm#f<|08QTDj}Dg|hYa$hP&Wz5Y`05LL_h{YGQX)0oryYdSXeB-{K zv?Q39m82X_8~A6AxgGdi5oNGYZ9^}dotPb$hm9n4A-{FZWo)=$ISlY8ita>V_j+2( zj<4DrZv?BN)Lfy+C*;5+g4D1MO1|E8MT83vzJ`Vk?~c))MQ!L75&7_p_rJKak!@wZOu<;RJnrLf!&WyHjyB@k^GW>bJ`GvoQ4K_X9 z4Ds!))=m2Bw?|V8LT^tWuDE)nG>$tqG(rY5h@9HwdlY~WjofGsbs1lA`n!ysq!_Rp z-L#_s8-pZODqJWH*o#g=$kSjaT0~NY{w+Qt7U@#*)*voGzL$@wxPV4)kyZDS$i(SKO-?Wj`)+6FcI;Uc-1ak`i57CM*C@zNW0hB@*i&{XR{5wtiNNd zH}gp8_7#r{fQb&55ZB(!x+~!}_R}A z%$BT&|6LCZ7jDg079$Q0J z_O!b~>0BVxpPNr)WvCR%8w*_5lj5lItB zK5)z%kbwy>Od?9kMmj+ssZ1ZM#nP7NyDsC_tX`PIYgcL|JQ4U!cM5=HJR4-dy?dK! zAb?xAB(R9gkcKH7Z$q+<&qCWSupAAnov(>giJHGaaJLEC?V#y<{Jg}sgI}Am?(;}} zQ$^rsOK8IAOyTt{vQlFA5b-%9pLdFvFQ zai-CKMgq6Mr{OxZi^NMft^b%$dem|p&qL5f&?WV#gwl`hm00wx2Zp)QH*MG*8jPG2 zuAu-oquBc5&GoCT+(q0&&kyNVJ%NmOL(GpH|><-2huZS0cq<4z}ag_LUimd?pB>-L`Y>}U!w`!>6>CKV%Yji<*j z&Z-52e$oNA@84X0w2nQ}D-@OFA-r-qTU`B{>fK_aI> zC!`h@*(C4r1fS*lc(h41z}qP@gz;m#L`kNXpwp9_G-3-cQxR~B>|mn(US>A*9npc* zf^_;6g1do*tUo85C-Oj8e6!isxPwRc%gPK3uRB$XFWD+Lq`dHamos{rzJptN&IUrt zBQnk!O~}GXFVs2UA&|JHfO$*TEq0i?b4^*^O0>o2F%@R(7aLL|nv2GAz@P;_G1h9G z8MKq2iKsa7YJH{2U*7W_xzf6(QJW+9wOjTGQ6 zJdpyhBDApfJ;+MwsTL8eSZ8fOfd0aZs+(T2W^5%XulasB17?e2oKMlFRQuwsNQ_z8 zK5jtR`wMiMz*<87t3n&h!63-gB6>ls%=XjZVQOl54$(_*H0#l=R z5c5zp5<(UX9fh2%mQ92(6Zy%~9$Z4Vj{D1kwm7j2 z+m}_s+S;G+0=iJy6S}&CEUF{|jC?kgpsPzJ&g^d>@eM8$af%xna9k!v^|AVSzuD|> z3vD>GboKHpm28!=_cZlmcRao&wC+3+4dGWPKO>(~NKegux<%m~vdR~^^@#$6f);CB z-ftWQ>h3(H7yCESu7_#Q~8+cXc-nH{(7*)Vq}l; zOmRzZK=akcb7!cWJgMqWK8>x3YD9>TUWZB(>D4lbXTRU}9V#l;_vc45CJQ|-zb>A5 zQ6*hG9(fkDPpgpK-#uxe|a98<2fIPaAm>+8vVhQi%U!*9iX<*;FhHCW^bitJQ7{GK+I;2YA?WY7U)<)*Eh1RX$DLj z2GKsq@`@95+fiAFw~w_fLpS2Wn(_Bgbejl$MQ27gsith1Q?lPO-kkQ#@{0GJfO(wj zK3Db<^^epe(>`$6XhW(-xs-9>P2sez(_*R?4+gw+)SC0(r`R$|Ua^5m4mjQ@ij>Y$ z+bcEDB^898cZPELu_OeWHVg%(nqEo7Eow3M4uyr4v1BZ!oia;!_K~hkd1wE3nUH^y zR&kTtsRVHc{|$R#A-&S2jCf;|0#wVayGOiXS?mJzZa;62h+y+%JejA_aKy&o9R>IZ zdKbT<6pTZpJaE1Yg%fZnqV=s&Wkw0NmR^_UIJJ72qYKU=<(gHIPcr}N)%iB4R2BsW znAVI}2|SnDa$CCdI*VIE)caIl#fL>OPR8|dMfJ&@esQ$6TbhbPkjRr@!C=#}-z!d~ zJ91KkR0efM#bn;Hkd0S2R2myH;u@Pc6*=03dD1HydF)H01Q6Ca`!F~*pwkGwkBh{Y z%@VSY1QK98hqo8Hq`r_6#}u|NX_?6iUL{n}TKbza3C12|{MJXIzqd}o03mh&w*kjR z;Ya3W`J9og)o@lT&FZ;EXLqH^Dtdu7CccS0yLa%W0B-7*>+>#}(&R7MJT2#6Xknpd zYGLM8N!0q(Dnmv630oD^2?jN^=3x)kI{#S@NJk#fStG|mlk&@0b2bj#{!ER-Y>}EN zz=~A$T&+d=OSk;6iI0P47w9N%d7{oePd+X5>aAU&M9C>%D4Kvvz|3sW z`w(vZoIaf*d-8j)Qsw=~V~`N5D|ViDod*Q2p2$Ho7d@&vN(&VRm;M$qXaIasy+Z*| za!BkU^zSps?@PMXW$)CQaa=dMF0;BHH!ZW~^wn*!?Y-x8$o1*Z@n19Ve;#vnYFW#h zA}52puPFT4+HPoEC|4!k2m?27!GO+3sk%hLPqmh8<&s=|FD14LE6y~oC36Sr<3++t z-V6`*Rj39Y@WaZOYC5rvXMYwroGR5R~{djbzg9= zM#pne`#s0gC@AvpHTxe_y^CowX|D_3=``umx_VW9+av+4Z_#UG*yu6c%*=nl{lMa> z^JvcLRQRV_*P5-O3WHvePte(1$c{J#n9`;I?rS^OTPjKK$xyu0LfTkt3wKpRP1IG( zgipR~cQTQ(udjGLsw@o|?@c3O=V@)DdYtetP1*0?TIzMI@qc`icoS+jCwRh5=H{hH zVf9L@ahr-%SU8k2{O_CZ|BoVUN;-0T*iSV!htc_(O|)NXv%2SWpY7xMwTryIrsFv4 zBocKAYU?=){~hwpAG*s9IuR|76kx%3omQHwnv`J=#>FJzgk?BcRrmL&xv98g(d7Pe zFaVZTOWIKd?V&t^ObX2=>Ud!zFeIoAH1Ld2}6J4rt`2Xw+2XiRnKM~Py8f<;q~9wj^*>Rqeo|_JW;dm)^GQt=_3c9J5_ZAB9iVq#$()JdOz9({ zhLoFq`aG9y8=Y6%?wsBmI_Uq6m?X~s0G;~pAe#PXmG-6T80J)9eCGci$j*NM85)It zK?l@?q+r)oCpTMI&W4|#pE`^@miY{;K$}91rSDJIg#xw0Tcl0KXbrA0itsU zm`}$}jrj_ca9-YN@)n(}sk*ly8J~Djqsw*}$gOho{RaQKXr?!&eiWu*c~0$ zukQbw_^|&yblJa3gCM>CHYV@?wOT8UG-A=`OyJCri@c!)ftpZ&BX9q^^N90|OU1-l zz0WC9&w;nWr3&YPeXds*A(WB-3F|r<^hg&Dp@%qd!5)$@udW6izMfs=-Uhgs=H7V5 zigpej%V9xFN&U!DU-0#+WJ>ZpoBus+>G6zHOU&F8rj6vQH7w<2%}85l9E4*RCNL8y zsfT6GbIt2`y;keuz%>x(QA_V2SsW(kAH_sP+pPtR`(Wr=Lr>xl@+Shfa8E2tymva) z7J~)VTFOhBD}%0z2uLm5PQUZx=4oUgwUDhhvtGWyYp6=8lDpl=wc4@GlGCw$*f)AI zCsoYzoy(g<*ditCJb;(?oJu&H(akj(w6$I?O8#cou^pZt+a*p)!Ebx3lv{Ur(us&@ zxb7uF84-{#ngZbFu_6}QF>WKCxYivi{KehFeT#o+8@CsAHk2$Fou>>I3_ zn>EYRJzn{S!Lg=>V}L$ zDMNCWE*<)H*~At{=pck~k0l1lP8LNNyi#^`Kf0hZvT=8;I>s$8ps_MhH>ecXFL5@{ z&EU(fIv^SKg#tLhzm0ciNsPb7a1mC6dBTa>?hguKI-d7#&egA5tm-hyHRh!Ao!SAY z)A@dIl3q}4zs(l(HWcn+Pj@^A_=%2Bp{k*+EJqN>F!2g5?{;kPaW+j2Lmo`=W@NUX z^D!m8d>u*&sx#e4f87#8nI_~;|$J4G+qYSi_U1;ifk!8-gI2m{}c+YO>OoFw%KO7`G5!n zET@Z;zopj2TbV1KMnSsq%Bkem)lS9Ih2CRy_s4FP2*mzaygTeJIHxRN_ds5l{8mm< z6W6`m4m-Q#sn_?!yO_mOm-_bAsVPUy+)mK82bcX|UJ*Cs+B;~1oq~oUS-l!^xDO)< zoVaii^omxXYv>;o;BvF-HSkJWm)s1Fx+^``zd#objSg}3;Lwvb`oPcK%IMp(uVZKo zF04IG$jzjsn>S8XnvPr=+nVE1QStf2H>>1TDSL9(?rjwa72H~KmhvS$e`S~MUEVox z+1P2o8z8(7uiLc}T;MvioI~=~MnLbuBilm7RtW@IZAcYl{bM>-;wHd7~(b9(bq;k#bZ zUEo%RiqDM~e&{}3I~HNob>wUcl3EO3L@>9&FCTt{xgeQK#IRCd8sA7L ze=6hlJV@b6;M=?^Cv#~|K$O{aR~+}46gfxAh0eZ4G7_z^HUmE`0=i1r_KaB3E;n_c z8AU&9BFakKmtvL@YS)vPiaR&`3GLMh;%9b*>WPzXFs&gJp*X!(7IJtwFO1?$#T$no7C zAMAqNA;Sy`lN3|cOxw|=mi64v{q6m?w=0^`x%FhOQA>qM9AhBxJ|yU)uQN*?a^t~{ zPQ66RAUYLxVF>fgk9^(^f>CBxe4gP@wdE&2_fl$p^&MRnoO_sPiN6TjySk9nlk{Q+ zM_&_95KO++WP`=$NiU@YBjxUED#s^(Nkc^&|Ezj}9Gh9DTbc$n(TC4e;;}GzsEET~ zLGrIjreRfy2p8BM1z_1xPNDjdxupy_I0kOQTMHay&aO3$A{S3VNxtx97Y>mMyblJ| zgW_(|0;Bsq9p6<9uWT6ipB`pEmupjDAd;r{CBW%!%ibzkl$07O_wyvA5v%by*uUB3 zZBEMW&xVAWJh8&0CWl1&6JO2nFI;YKx>j=_+f@ldfx-Qk>s3@j<*?F=n!?Qq1`7FM zS~zDbS*h5HUb!Uvi>wZ|z@B-J@HuG0$zx+k$D)oPXjIjw3r2)%DsKlj_Px^CJ)(&N zrG5QK9Gx z`qfZHd{JKYQtYaK!!6YSi)SNJ^FiHrjB}ettnP*-KmIo2^&<(1kzJ1>XiNl-bf2Wd ziu$;!ygNkZ4>ZDwWoTDmo{p)#%1GGqeOljG2XTwFbm$EVlQ6Ys-Od!V=dZEW zFNT5`w@yRLt9USEe0)P%Dzv{4eP40Ps=7k?$7YGBB>#YxL%c#Hx~}(g@KA5z#n8ZS zE*5VK>Q-uor`)=?q!|}96d!e&W=)6aXHKv1pJ$y*dt^#C#ZNjziYH6{gfNA&fY_6< zW$bk@&`i%)S3p=r*d_mf3b7OmSe2cX98^Yy@2k$#t`Y_DjqeQS*@DX2 zTtfmkmOlA0P2RZ^3rUN2t8bef>d&Q`yIPGC7`f+nijnjT`qTmK4;Q%*;QRS}w@)m| zr4A1x@VCt#sQZ#>zp9uAekHPxb(lY>;Fb>V-~nY$ZD6qAcBzPLOYv^IT&Q@9_p& z%|j(6n&8oocD{F7%7m#0H8cG#>Kl`{I)4D}Ho&H#4+WrWVM2&tM$GX9%P%t~brtw( zp2$*24S4&P$tm>d7f7G` zAEw<2*Ib$6a~vkF20dg_88$oL*5$PaaGHIEU`nA*Nc^Rq&Yk)CmR_8!=ubYQjie3t zXOpk8VBb_jcLpb4Wj9VP`@keeoEg2q6)hgMHw<0eyHNt}b(~b70ONXKBzL@y+^>?w zjw0nDxSSTAL>Z)-Ro{7xTAkPup!$)JkBc1S{T!Gh`BTNWL3jNDw&=!)wBPY7(yBTy zOcER_D!*1=uw?9i3U9bU|HkY`&1}73EC$LOsM-Z%A?o|hvG7kAzP;~nSP>F5?wTVa zvU*G?Oac7pJkXub!1ER1i*Ao1oxdA(%i-q@CX+UzH>66$9?4M0Gvpa~Cskhrj=pBP z>q&C~mm+74IEl9|T!kxT7T09HH0}+|@mL(PtD`bbI@_vD+I~DcA<0@&75#iu2 z&Lx(^pQr&dhU~xxt_>hS?-U)$7q%=JVbr2oEp~aoM3;OCoTtaHkR4l6@bUz~(4p)q z*$7BCXw0Y`j%9P_lQNXb`vqO8r}bYpeG)m_#n7!VqGu|nM^kaJ?1kUo=2sE~uY>Kt zrI6B4_R&p-81nw*uLu?_j}2;MPg>Gscy9EDz;_i%f7m&zE4_q?B{Q8xJB^7??wn=s zbu$9T$@F^!y+GY|{-i|TcS=YumqV#5?#6g0^NO+4A9M(x)Kx0=&lVyD*3UHSA8ipU z^Co4h2Veu{;9UHJnkpQEX2uaf{Pe#8pCs_Z`wj+HB6W z5xd{b|D%-<qx-P!4+hB4Tg>en1CC`o{Gs zz*D~;em}ERK*ZyNB$99Tfv!!!9gWr%CGd%Z}FMa!l{F8#_pG6D9(}#Wn+>iXZ_A8s2P`5`PPPx;^)I?$nl@?uyYmz2 z5DX(Hxv&@Xo|L}wwb8ET=|z;UJ(TZlEg6hLaUdRG@~n{@h;v^(ltK;vN5A@$Po(Q_#NI3p?7N$!uu0$jA@Ent)-`|vaZSk)$W>e$)aqwX%k_2 zd{kk2_FcNUuCzw0gT8@SkrbUvjTg~; zb##I+<5_wSC3gjIE%*xrbv&dkI3Pxo?fV^z`{k>tD;b#%Z%dV}zjWuP_}jf3YB6I! z&G7!NW=jMn3Pg5uEFd4Ms1*nMO;^u1eo{NcZSt0NrRN=aT>Eq^-KS8;kM;{wqNsSq zwtvJ&&?A#x{hF4rndd33gtrOO6BWIGC)y;%Qy~yY-GG%sF&{yYu5M%tlZ(pq`Oy-$ zCY@5eabVbq8xO2)pUdRO_X^5SJe?Hf6|gWQBr?m7`q=<@Ta0QO^dy1?^P@HMdj4Bi zbW&tu?SrDOcYXQk57fNBys_Vm^yIDC!d>iwf=iJ_F3N_;Ll6o5#0{e%Dtcir+^nh? zQ@761FM9jlr>LYjy`q9ALb&pbsdH;<+VkyW=XyM3$$Uk#h7@3ZV)`_u=2bvZVC;AY zWYTQ7Csb(EUFKmwe5Byk@w=##7WBhwRXrrh+jn-=x$=v3f^F5K|6L{#I8Vu^;p3}Hv zWfTZ$KCRg!J$-%dz8r6RID@D?p`8)njNNVk>VNIOUP2!JoEiA4_S?lMtD@+~pE)1z zUP^vq^!5Vj%+a%wYZL&DYHeY~^yA^3HR)`D_MPax40LrFQ`&ZjhSQfpB5)l92wuC zCCr$MHSgIe&|dLAraqoelqMBusv>xYEIVeH{c`M`aH)aGz3yJBV%|68DvqkC3GvL(4|n$DD3% z9IgLQ>75Z!Y~x}tedNqQ=Yp+()+x_(WwIlh=Mm;Z_Cp+3$Chj1%rL7}3q&-l!SS!t zgK9>K9{V%p-hveiB7!e5nty)H?=`s4G8@d&1xZA5kQH9&;KSdE4VX$xwlQ&kvAC3^ z$&|D-*~8D{o#(@9KI>z(O}vI3CaS_8OTPQ4eh&Tct6}=rNnAN3ZP}xn0@QbZpA1=0 zAO9y34v(_94nyx}Cmzbi`DOE?U2V6Tv<2nw8)%d?jqOW%m1VBW1+CoyaKUz6EzM8HjuHz74VUtx{m@A;CFTsnZ z^{OL&O7A{$j!G~gVX=ls(ubLzkNTuGRU6$zEb4cC{kg@4skY$Z5X=phL?jJ@i{;_2 zLA31d+U4yHk(jV0T!y3lAe- zXUO-sxI)t4-2U&+i)Iz~#HZdo_+1fy$L68ObI`uDNFs%lkrNVMy+-!zX76o)#&@nw z{!Uehf#kE|{LDKZZ1x8Ww~VPIIXcS4m$(e{8^NX9(3`irSJb_B%kJ_Sy+N;+Uue5f z#E>5HPx5W$oBF=@jN?MQ0SZvy`>Qdws$3vD1d#8;UeLI8E>|z`Dhk}{viR}X7kP9w z!^R`+b@M2?Sf}s7&yC z%^78QI`Su*M>aGL#pspKgAVV$pK@~|@yU6u-&4*5T{Q%1m-AOm%u)CyZVAX;yum_1 zCx{j&s$ik*vh=G+I}mITPwrEG;TtKuf2nui$@}L|`U;En(TO>gkp%- zZ|YrxZT}$uT%VmgK0{D&)^4k#41cC)BLVYlHGFPAF5|i(>~^+gmVAMEKR?XsWxuF| zSfiA{A!qbi`*=H)Gzil8{jGU_t`cHh9RV`HW83QSh8O!v1|+Ge?Ii&%TAjyD;9z z?5im;rFzao)=j;@Imc7MXH2>fpaTA+eF!F_AKXzl$R^T&0jb0r-l;<$G%D(09LS#T zGztI%+dEkffqtYF4bK}Wl3a~eX zdS1%haIp8_^t@x8<8ykolMfk2?${aIa5sm=2vzU-1_%xYlG7k8xnIQ zjnp@X^+i$!HhaWk)Km0(Pd6ulC;Pdu;j<3u1#gLRUvC=Kjxk9G38ts-8%Tr)WF&iW zKAWuD?LleT2>cGvf}qu)`{2n(lq-19Xvnitvup(FjzrsE8S^`iG{Ew=dA&clGAoww zI=YF<&7(X>(?Ts#H8)bDw@WvljD}UUBo(frzb3`#)s1bYAFlc37ZsqBx#g9dhd5&m zV`=eU^;-v(w+ns;Z2d>1S%qp(cANrUzzPo!C~E$kG=E{_{e9L!LGP+shqU;1-J8M} zxCCP5zJI|O`aoGUMZm-BMllQ6jEC^hw)Z-mABv|f3?9E?@=*C$+*HK&@}3{Ba_c{V z?^#DY--OXaoy+29sMwcTA`T~4zD%q2DoJyiu~xvOxsauQPwe@#tT!q8%CC(7NyCQ?WXAqO?ysdj@q(*M zH|%f)vK?Gld@J&1*m>%kW~Rg3bm6`;ijq!u$>6Eh>MfH$b>NHUhkX$ATKE2k$xjQ} zEO>ZVW?Hcer$tuf+mf!$3B2_-t(JsIt3nj?rg=6O%Gt6k(T3%brufQA!2EYj&zgp> zbp{V`(seI_axNchR}txTK;QOmiaq$f7yTXjuzg_o@4_i#ZAB|8JJRh{1ICfSYd(<~ zFY@h=;bF&xQ#7`Io6^b(piYBmJLuzJ+Dc6Aylj+olNUHkcBbfP=I4Cx8{4dvJ6itT z!s@lGyLW6CqP4jAaZwSI{URTT6(&5lm_z%z(Aza~&SpPYIJgO&6US^3ceDS3kF}66 zcUqrW-}{A>$5Rn_@G(sW1W7zk=Lf6%sgth^m1o$VZyaxO3&^!VPfqGeg{k;OS|-U| zvGi|u-JY3`iWkO5VP!jQppjtQt^WP@RmLOk%kn;wdaO0H{+r#NiYqoww2iq_n}qXq z5Awv>B)|dQvdV(jCtd&#PlDjHKPIpdKbc}~MRjoBR)_#OT!C&UHf=Ug08Up^{x_yL zoIqc@b=*0|6hg?+VE4V!OO5b99BPb+3)HDCJS z0ZsG_AI=8cGzi65g(wuo!0H^(-s_0lB{B|erS z|4~OS`4L}ouCC8Lk9SU@Yv+nus#z@rt-7Fyu&BoW^vlK<77y7+64o(@!sH+zC=~Y8 zi*K?IV$<}`K*@fCJ|T*ezHl@LxYH3e(jN2XKG_&^dEDn`c3nhEzu3+}YIdgLGTg)K z^z4PZw+$dk5bml^+~XHVl;2C26j!HXsgH6dswSB@OgOTijamwvY;+bh$QVNLa3YxCefwqcgRFFZtNQ{W{)RFLTga1)<&{Fu|1>_Sa+n zYr)rFHW-!+ew)<n$n`ul#+-F zhzN+%q(wxfiHOn(iGYAo6+{G-hzN)@>76K5M0%4VA)p{7kWfM(#WUI8xA(&J-L-ZZ z_nvXaJ?jsKGsE|t?=zoSp8lKnJz~DR!I5(*Kbd42(umnKox|Pcom36Sc%BzzSgJP0 z@%hyjQO)*>N#TjQyIV)LRnCKB^_Yt+H5QUgqz+TTs>$;-)A znK{{W$x*}2rFRv+e{D;WPW3saFHsJ}U7Y@ce*1+#F00t~IsEdb>$sfmnYb=>*Q@j` z&T6zlpf+$%F-##`(@=0Rn0VQ7-}|<=c6V5-=X1+o$s4)`F<0==JO7$rIkYM7Di9 zG}_1+$CmvzqCy-3g1M*+Ad3#tIw?Tr{`SLS5H5tifsMv(bCX|%N2v47kge{=op$r# z@A^92DsKrDPX78W(mz;Dn$Vyb@qwa6bZkM0(Jsr}*W4jcm^|DQK+Rsf^{S|}w4_Wl zBh`8OTFmh-FR7|Wtoqw>;;k)tlHhorKJ4^s1Tgy9x3*VC-iQoL8JJ(cD=Hu#wbzLI z*v|3TQ|f*Ex%ZYal+&xw^%>)U`|NW!-}G^x&Q z7nkd4F3c?Yn18Lrd8(ZARGjJhqqC}I+^qh*HmIa5+c}Yhy7(*ASyc%KqV=0?KVCTI zE0%oXWOGqb`MZ18BZ~Z}Yt%t_4&^!&K@dEncL06_?nxz$)w)kWf;0_?!yFH}OLL+0Q+`l=?{k5gy%tFRlhl?JGclbF| z*`!}oF@HxB!)Fo8JlCJ&ocqXg0tk8d#h*;6k5P^^*{5lEDnT7m zqF?&ROV;0U4xw*@JVpvFs2?$oDz<*p1ueCX7Til~8g*B&5A)-@;lm`6s#FmrHhzc8 z??$N*CeuLh)U>-ymdR>bBag(ZvW|#phBXKa#-d5em@jeYPG2l(kskTTMR){x1|2 z8a%srR)ATa@3UAs z-!t0#M5dB*TeDprjZF=!pKC z(HBHHb4u1^hzc$kslc7})`^gV(94?jXja;(Yhh-koK-Y6tLJ5hr_OScMz3G- z-LEL-_Z+&&y||kmOta3S1mGbNc{LmpJe(AVX2OIPdq56`ul4#KWBkX^mf^HA*Z%90 z=db!r8jqa~I>{Bx^W958lX|3(ejF)7N}R{%gCfR+fC+@KuhsHNl5u0KFqe^N`z8He z!iaHI=a=cn3s;h-FNEE=0mAGzl7-Xkr-Zgo)j9Og?1>SJWbrQLyi0b({8;Iv%ozo) z+819#+r|)?8DeqkW$v6-FH&DVe!850KhCO^eNy9W3*J`1Zt$Z#+CW`~0B{W_*a%v0 zeX%Vt1!7ToIP93qQ40D(vVoj${K<;Ke*U(p{Rq|WDFbh3YyX;fnM(1;$fGZyK9H|C>+LB;11yJf-@a~;pFWar8E z^uM@ykJ+esr;Q-{wms}_h!!p#&ZoET1wFshcxZ0+w(RQlIS&KH_~Q=^2+T3v&zW?M zdy1bIy!p(0wS{4A4d4&XAZTXLFAzq6HF~pcd)sX-TD7RlCM%H42Bg~nj=~Gv;X-;_ zA5p&4b;1M}7zFAxO3NABbv8YmzdUWj#qT8cX0ZL9cJ7g9q`VNuIy-ILM+S!X~S+_zq6n%pZUM086QY{nFuF(5q;c zgnesUNP}$Y&g*@*ZqTO~>O2pS+j&^xK`28pc583rPU$DV>;2g{OIz1X=B^pBxKe0o0z|83cu zzhX0L)xas((fu+)wLb2|_3f!z`Y#Qi3kZy%op4~4`@t8}8OmGR9M8so6aR+;<2D8@vlS$;4A1r^p{uk^1S~h=eng2RF{(o>>7`8X{ zDQVv!929&On$oqQza6TJ z=;>+zKjKJp14Pca`n5@>TTea=)KrieUAERXm`f`%=M>Q^mu|8VQm<5pS|k-vF;-t5VA zouOY~G@YCnz@3qGo@irT)y7{~XrXsH;kv{l?Y-MA`uI?NnPddzte5*Xpv5=VJROiK zj{h8|dqPS7mXu(@;afh+l6A6j9uyS=cJ3 zfYk^Zww9RMSLZ?bN>bCMe3&?k+8=#lh3?N#81Ah9sqtx0*Z40%?em?SHzahsd9 z{2nl~w0u6)u|s%NqIvX4u-F}KV^$+`f{SWHj*plKe0q{MS;lXf%V+IV@0X6RfVf^} zH2cG2yy%E#JB@BH9yXmft_7Le=`$Bc48&g)?rzhJGwKcxx%++3exr_X;m#LGX?he5 zIw?oRaZ-Y*W^p8ykyQ- zjwQwz{P00H*sy})_qYi?nLVoZx`)zpR`+|@Lgtt8n4t;d$TE?{hCKI+$pf|;cIDXO zeua3#g~q3Q1S+GNky#cy-i3zbC~|AJBR}Ix${U@$+&SiwPYpY-+3l{bt$F7w;f_V0 zNY%N$@F8B_lpA(BSbwVOGS(F;FfwaCh!P@B1*KVAx1ch6jZ5Q>UyHwZZ=_8wUhc$| zC~qdbQ0$Wk{U+uPKoadj^|^MP!EBcT1j+J?4Ah4fb^mb0n-DGkglw3i1_?lwgc{<#v zN3vg;aCF60%iG|pmqvil#ng-XSjSIMCYH^YO&{?n$49TS3;?L#q4@ER9Jg1LgPrCB zdLW38KSSD={0y&-P9ghLsLtP!T)*!Y_M^s81?K|lS75vKCT!Vp_|V#p=W7VAMX$&Z zKd##P&#-nSiDN}a_>NxO*T;#hK62O29t8aAJB^5);VY1^sv8L^E8^TGUAMfF+^&m+ z7AqU>Ycx6Gb^gjDNZVBwF}18XD@N~_QfaSewNB4UOI1&a9F|*ZQV)ue3hhz0N9?(; zu-kj-%b{o~F+-B>R6t)AGC_hix}OnAEI zmSpA7)JbtcXN9qYjW@;>$-+!~l=wdG93}!ejw|isphMd9sjax(XQ5 zr~N$eU)%|}OR+|ebbJSbJ|uqhUO!W<^e$D+L50qPJVP(TUh|}!e&Z|Aj1hvOl(WbS zv4P_Sgg|y*FEpq1h@E6{%8PTB4WqnFUq;lDRG%|JSgc$WG=kQX^3flTpj{9GG$T@Y zINH&e)zwa>OY>;{=#LvqGj4f~){(wFH}vB>Wn=c7(LBm_n`KJFwW&@3^#NTb)7%Em zg&8y_4B}Gtnz5%UuEpYHB+t+-yrd@AR1wRu$Ddsj#XLS1^h1Z0$n*5)n)dj>J1y^F z@^RKFox_5-mZLif&;!tyI$2FZ!$n--na@5zB`{&6yTdTyz6C6bP)RucGY|E2MN7Hy>;WLvy3*( zJIDt_RFzEF3OW)k5MPfvL254bN^@d}7WIN~dVzvWsk?k@cC$=`fteq(nfXbNVv=XhKAd9U3H9G}x*1X^MWMSZD_Zv~k8A?-AoD?p87hL!*dfVYP z<7{B%@j#mKJiu`#ds6oLWDOZo&-oVDlYCD%$GHkU?HaagPxHl`kIFhSq9>fZH{VqF zyLD|_$->Cv2!4AIn}bvK`%MGi3`N@FJuX6AkQh@wQ4ldGvZJ%9*7b4^19EEkL?Yqc zjFRy7wTfqfnD$4q>kb|l8>Vh~tn*APa?CQ=NH?;_vAg%j{AALrPW|-V^qc&^g2Qc| z+j|Ysx+o!f8T<+~GW8(EofI+wiGXS{dl0RgQL=+8bY{=&#cTcZD$&}dqGu=KIGeUV zuKPH2?Mkg5J9EKw$^<6bdcp!ElJe4YeNi1=^oz?Ek2-3=`sEDDwMf+hFLd}5?v4L= z74dOf#G#k}&L4-ls)c{Tyt>!@8*dMjhs#tRH;nGMZTjwLu(pK6b{Z8Q?LS>VCe>SGd@XINH{ZT0+B(h2 z<~ZBP!MgYX&uRp}<*Z;GJE<%wi(+9}t$u$%Jt~i@y(a2zktuKSrwhc)gR@__?isPw zKIuu9y&E6=WJBgwN2hs7ZDnenLV4BtO-9*4m26!VvBRs*TI&hDF2{VnV-I$pGqxV? zYyj@qwTnb-q&>0rb@rRQr3Qu2M!2j^!yV>_eX8sW9qg%QL2McRm8drS7Y{ z<@V&aBwZctJdD8OB&uas&Gw7y1Zo6O&(T!Sd~;)m%gXwqQV)bT5abQ{t?g6vQ`r(s z*RjWxZ-3v#^z`_CZr9>np`WrY*0`PF6Q<2+bkDS=E?l;iW?e| zNo#|O<>V)Mfq^5vUSbI)&aZn5@zGR8MpwiKp8H;6kG`Si7=F)r2N%&^{_nnP3pCE4 zccG-_?0Bn43kk1mjnjwRm274AMMzMm`|dLiGIQVrR$e3$4&yljUARtJs<4RJ!Bd*f z>^M)4IQdd$sgMuz_Y}`Z zv6!1V!dE6MRQl;jkM*msUW+r%wRZnnK4g&lqH4G`^LEW*guO71ZI{}iJpMTS<*~VB zL&Emt9?cFz<=9k!BFZu$SeQd`@(nkv>Q#>2gBTiWL6NST+8sB&dClum<=yD_w_U9- z&{JxBUiuCgbNIgPST+h8$5xb7s5TpyNJS{c@gHfvU0rl1s7SA%;xyF=35{uKxb$^s z)}ksb0i8Z-p#1KAybf#f`&P&czO<_CoM)tU4%6qCEm0z%xnno6VX>H{yHmC`Zrb(`Qc)9jjW zm&4!Ie3$N{@Ii%C+sJ1H%Jn(Q&VI?^Id%MCT_tg`1-spnl2Y&EpHWLJ>ZwtHhZhVh zM|~3axXtKRUWCG zFq%bTa_^@+eZ0HC+XReK&u-_Tr9~OJIX6O)Ugcx+PSczgu_vi9LN<|B34Atf7^g$l zUu%=A`-{7vb!;%qxFK7MgH2IwxOJaHZ?fF69+i?U#@Q47u!lzhp zhc_1Few@wu{!By|+>_(&Go|$5!qFJl5=t?tr9m7<9E>P&Qw4Ce)+Eb8x2V~mi(gJl z1|YZ_^%L!w<3K6oUi1oUzI3&dzX3qRzYcKHL@JWk9Tp}4;w#I) zs=ufkiZZm<;H#S!ZsE;$?QUMzm4l(M{cq=YF@>8?Go^Y@rsW3y_Dq4J!(H@&h<ka172v|F(h-ChQofIW<+eD%b9QN!UjV+79tjw<|} zI~KbcQ8==RD9SipeFD4XSqL#Yiv})+K>>kIs+#%rVe}Oo8nqd&u-^<O0+84XC;NiT4L z<5mh8ALflN0zJ`N*){k27Xp9b);A$XwO{B<-^wmqnXU9~<<|bcrt`1q z{A+jq3n$T03owrSXhv1=RYo@_*V~p_Wv#B@4rmV@66_ZBo<`ByjB%1Z2nA9%LBXssf=RuAWE_fHGoYlBE^`mVAA*qqlJ! zH)1^z#kbyzeWwgvUkU+b0TlC6fon?od~glY9T@n|9U25d2dt2{VBSuj8X!zKfnvI5k$!7j<8$;v#|Z zY1`%4E4vCtIw^+-=ljQNh3aA4ltN5xax_s zkC8u_o}G|Y6Ekb(%6!l8+cJEUEd#)&<0yx2BxDTJlt{TdrOcSnZr|$#4>J422y)Ug=k^c5|WDi=00;Gm!XLp>f;95`I5l zjY7hsQ@Pfh>>(jBJCyU;KK5D6*oBY7*%T}1bY8rvON;Yht)myLpOSbwHI#EV-!0+H=8Uktxn zX|pApoayB}dhDGUCy!CV;}sTgM+*H2Nod}W==dHpl6r)cS&*lPCn%jR>K_+`Z8L84);*`XEXrK!zh1Nt{& zIg8}{V$LHEUrgWr{M(gpS5R&yh#YLu;0Nq|6bq%8h_xntWn_3vU<7Rp-+URd`oKd* zs{UAN66vf6S2&;x-_NXmWinL{51*HMMVZ6bg-$^C%&H9}Cq^pd=jSdQqyp~A@p|32 z^(&I^oGS8qc>874TGq$+w60fmgdX(uSms$s@h6%^_@#d6Vv1o!U234ZaDMJh#RE4u zT)jk;Y??pw^BvU|nbwSP#mhcT2C=Hc;3ggZzx|mHWN+?ccY1&tBPOoU)zuW_kM2`r z)B^2HPyf8*zYn?m*D?AxV2G`D#Gf3a(vKC2^7`}of_Xi-o9^sl4oP3WXT&{vn`^sP zXXc@T!^V4YuePfVaGsoXz{vb$+Lwi{cSQrcA{k95d4M$F{!w}V3;~e*oV=OHF@*uR z&o-M0o4-EQTg4%st>cHFNtc5hr*#my!wEq^8u0JlvfUAD`l_aY!Ds!GX`KdqeIOs4 zAstIGbO(7J%f=vNsR*YeD+af`HLl;eY#Qmt(VVq1Kj|;5N{ZlejRLkrgR?;Wo zgb|X@WNPRnnuk(u)T4kWk&CbAyKp&je(WB#JgG2gY0!apIP~(}m3ixQ<|d@Yzc55@ zi~i7mg=H4n4*iD;Az!j zdQJ`i!QfS}K<2f>8I+36Jn;YVg;zho`tXA{@vMW@Qii1}=>LztY^JJ_$Wx@+g>x8D`zE7hn(Np|UrX~MZ7HmuIJmU-N-lki z*(H^5{{2~wqt4b+=Qx>LE+YRJ_gt~Qr60kCb%R4_YVW#U+OnJ+D9}7A+4&mh;$75s z*C~;+gOuK)d?j=0YITrYeDLuWsh5mCaj6~}TNZ`ShDZ*Y*wKB_x1_q={PU>Iklt;B zV_6*%UYtz{*Y&qyuI%s?+KNv9JKo!d#=cVK8OAo(i4d(Q2!rktGi>a+lrx5|^Pg3A zynBAcDN;UI8vlU1TZpC3uOQL&kH=v&FaOU`=?niE_I+^kpM&dj2$z<=MYqHNxn>6( zCF!q!!PZa7X}j6x>gu}xnRP?q^KHym7iia5f~v)WPW}hr#Q#JB7F;Ky=a)&?795us zE(*muoJo=6n}! ziJb7?nSpNNeTI7V#ymgzCldsm;Wj{mbQ_-BYx-~Af`sTHOjh?1@@`P$K0Wxda+Ue5 zKu#L^6cH8}Xw*gySSk%-Nx1;<84jd${k_FVX#!?r@Oh_eExO1*IFTw~}#KlqBo zWz)YaD9p-QQXuF47%)J%Yz)1-RuUN%ZQzCk6%S>h-5}{k`0t9$Klzur#|gK@Qwh3y zjF!nsU=86jbhwj!&!-V}gJXz(HV^);eGWpWfm@D(#lNe|PJg+v8p~h+SCoL>Z_Set zo@Sl@crf-Kt$T;NEnp35x#%?#n)3Fy7E_jv4V81O5Qy6*a5}%)+TQj;;O@MVKj0r) z=qFP|`j+-f_P;*!e*@E4{(ZcxKR;Ti?&Pziv3UFS-ufjf=3K^`$GtE%A5 zT`QWka(ITpzQq>JDB9FWbbWfqfVW4yx2N=c-VL{gqEY%(FOFqF*KD1 zT-QZ!Ub7awNCV1c4N&yffdgCII~*A6z|D;NzUk#n&|z{}ABNDVonR>gr$F>zH>4O_ zj|s!_m*%Wd!uYr;O$N;XSgjAU`Bsp(Z5rsVqkFn%UKBFo*2xpG{iBxFRNC2PvmI z@#T&CeDDLgv04K`Z@xPB>hm|W`6*m;N=iJ+Qj#EfjU{41MM&LZzC68Uvn<8kH|wIB zBX#mzNih{pUnb8065jd{#L;Cnj#;$xc4)j(Po7tjHFfQl2uCxBDA=7oLG!RNoz)+x zM$J_r#$3^!)Gk7ihe7xO>su4GlY&bs$K|h1BGCgclpmkhERP$|eVBB2w}$>j-IK@j)wa$~Z813(K4PcT z%aDe`iAgi&RiE?d)N-yJlj!#a2c9#I7hvALG5qxWx&on~0MYoC?@rcUg8&SmBm%!K8FpQr}Km>^9zLmRl2?yKdD~iWNm)07XQet6gS-$QKPYtqN;w*~{yt`CB z3#RS2IGHkRaQ}OZfRC#1y{st8!|^%eFos%R4ewitQG=|{4txzqmNKL6b$?2FurKa_ zh0Q(h$F|MEXgojtxyn}$ly$7&>^rCK^1RH{9KSo*sLmUKWz=4@lRZ5x&)1=exa^+m zYklS@Bv8Fyc?c}Q{DC+Nep&rNA27dmZ*lbUQIAuvU-V^$a$}#ja;1=H@^mGckSN*%Ig)T7rfo+)22Lx?qes9UI>tKlSZ;t)_+>d?Rff;j{ zdfc^Yf>tiB(0`>n-QC(y%Y5lOdT;7ys@q!bQLZH`#r6{HJ~YQOunN9M7P~=P5cTtT z#z9~8UOYB>6}sK!!P=ggW#LBRXU**N{mOSTud-cxU^cja-)jq@X(#mZBAm_u5i7fX z>S-PVmurJKG(08Hp?>(l1M18`c4k{A-Mb{NX4~8QquI?D$A&jnY3I_^WIdjgm(|sx z`Tl%om#SzLkK;l#c_uM}#ypYc8zX0WN~rCZE<7Euq~W<Z4^7Yo=WQKW(4~?|$nWqS^Wo4~;c8hT99ugH$J(eQck~#yd5Em>Kem-Iy~8Wlk=H z;%!`B*H%}rp+xFsuZ@^O}%)zG&z0NkVY=L0Bg)PJLK zYrc-0z_2*7rG26^Qk`7ZWa&}_YTMe*y;|;Rd8fBl+v=Fs0Y7S zJt=twbNrWWSa6e4g~m%!0>_OXYTc;l{noXBqYjEF$?5^_47Isn!)uXrU2!ARLDf0E z*%EYw_?GrR+20Nh!zgZFxes+(q*uefSp;t@?v(AxF$H%y-&~Jr{&Fk+6YD|Ff<_P4 z_46?=$FKE6|DAE9#^UcWS}7U;*~UUl$1iJUSPZ>N@mm3* zL{zoW@8%nVhX>cFkVKn_6!!~p6ZIV$)+5yFP_KlZL8G##3wIvAyM>k&-1+*A!o9P5 zB|gsmfZW$(@D_xRX;9*OTmxZR+`uJK?U7q7iCOD^Zec*7nje37ycbzrE0oiXl5gRa z5phrSd9~^fZF=^TNth-uj$`)i&eK#NSAS)@7_6mtwldjtPpiWnHNB~z-P=s3PMo5> zI&I29tm1|r5MG$qvkBmwNv%QG7>;WBij6|U14x6aN`lzZ5hSl<1&>Hdzc zYFj-10;~qe=4$A$pyt*sH~qQnDk1#3_~*J9e7@kEN+ijhA#cG(l%r>y-^kfnL-EJ#Ac153O|o(1)~tmr$7SGN{dRHv`NeGL&1BT9H!2VDlj*U+ zlrQENZT5FuOVIItk@@TJy)oRhea<9_<_-5?<&pqDuU+?V_+^Tl9=&I!kKpAiQsyMw zGwO0}&jIdZ$H#O`o-d|p*~2}ZVr_j46R6w2@@3Oz9`qP6o0>Gb7(?zI%$m4vcT4&E zp+z?>f0P95-{Vnw^RJ4iMrKXXN0=MgZrE^sSSKSwEUs}qKFj)MQ*@#W5E9jf3 zHY*3~C8X9w3f^O0CDOoM2I%bj*Xv4~)Z@(hF;%&k9N@flU3-2h8+t33-hYkZLqkEZ zpMS5j{eEBs4Wk^}lrxNxns#85&4GyA(>6Nbj8>9NeNGNR zuOXRGMm0#GKkkqzgPDE4(;Qj4$u*X;gK?U1Lj`O(JU%{Bx!%Xl5w@T2c>GjK0K@!X zAM=%*cpOVlPXEQoDAQ|;Q|cy9uBOYNK~wPZDBS}Xl_y<5M*45z?Uxmy{3a*s z|HTwo?s%ZxJ__uldq%En*}V1t2iDu{_w8DnooIt9E@mB68WMQugRi?#xK0#O&=$%%LyfxIA>6WrhOiXqDwqHRuO$OYSGf!E4V@p%6 zp#(7#%R)(KY+tBdsw}Ilu!MbzgULkfOf_{rbN!X=>mm>>zr9B!G7#ioM=X{=LeYC_ zE@!$}t%cOUvt8A_A6JZxUB29|yjyn3O3(D*(HIo+idW7C^n-C!sw8oVQr%FuXP{u^ zX@qr9fSbK$+0-G?YcZ0hhf9UsZglVy{W5N_C7IafM-xXTpbuzj0h16OU_LS)X97H& zudB7WMI+j{wYaxWj48YVO&7No@BJrjmVX~Q>(Bi-TXR3waFKA5G{u>?SikE7<5Ok- zG(vxsBij_^O+4xPJ_iSPnk;UyGJNGB1`{MUH_dCdAMDVjeI2UHtekZ<=Oy@Tpt7_K zUFu;43m~9(OK1{KGo(onsm%_FwOu=&OfyoP%ayDT(G&)FI%?Q!mm6C;=t-J;HJ{g@ zBuV`20S^X7&fUhI>^VU*^xY@y9z1r3_Qk%A!>^4P4{}nfxI=I#c@T$8!DlsKcgnC) zWv4A(1j_U&W|*vxd|-Y}DT4J9v3M_Gg{=2Nl!EZ!Lh;l zrVJY|5Uq<_Vud}P_3o;1UEy**47p^pn{wE=8q3(8u~8h1`EV`}R522zp#7;kboed& z#sn5I{KjOTdgCxFNyuz|N$qKK^v0sco6+HN#_8gi8t&S)$p=){XyQ+%1|CMS0kO0W z=#(qeoIGtbsV##hms-$b=vPjGFY9T!Ic~O8Hqv17u_ZJp#TLzTwCSbY<)bUfT2_o3 zkhMkXc#rBuZo=z zZGxt8GS;k2p zdTZ1;mtrrg9GTx}q&flM4Ri#D?#L{nLelqE(_@o9U*sV{b zkr6{#A5@h*BtiPe19yIO@8JWz2QE=+xZ&(X^)=j|kz}ETh)G^{C!(if{IUB~rf}mw znc8J*{N7`j_#cK*y^5T)2JXkh@{5o7vxY!Zqn@DXSqSR;(2~YIO>}%x?^$47;iQA~WM#P>6UMve z)&`4WEj=mrVJyJ0*?t>vPGqe!GV2q?jaW1c$Zc8ybwss?w>%`;`wq=ZdD&kOn$jh~M;1IfjYO6XP z!f>!V+y_2|p07551CeNOJ^hcrnT@;&FNQl}nVsSSsnztmmWYk%+iq@b_^Q?)M0c7I z+7ToA!!faEaV6RwJ`{bP9Eai@JnA^gK5nIBOkE`1g2!vFz6Mz*U=!{=&Nxq$J@l%& z^Q0V3*&Zx5pT@9TFxUcEg?Tr_Vf?O=s zq%gP#{=sV4CeZNi;9#8AFimT*Yr3F7GN6fBvF znWi`1Dme}|rXQCU?251Z@DXUnyrwxhW8mh@N#6wx@u{U>NiUjcp-+i715 ztgi(_5?!1XS(+a=r=FSkT84T-SEf2;DNYXEQNvohYzH%*uf>}{AWkGB>=e56+px2> z5@YchWh40?yi4nR@OOUNiZWy{#k$p3MqBZ8R6Y5?3>Qu5^a(J3_;N_JuRy?by~Gqv zm6GKqb0}4`^f`|{pJnd_wLbY6IG-Jx4kY5$GM$edE}%2LA+rv&I9oRD#W4Xemyr4C z34-hEs)6i`nO%%N-iHfQv{XQ23SOIBFqG9iaAa9h9bnoPSfYD{@qKs)iY6(xIofv} zUbGf^1{s*%1pYUPF&OWhakGEmof)bGKFv zIrPyR_~W%z;0kEReZKnw2#*+T^h6a28CnbS(sd9H8I|psM!|_ElqeQ33A{lE$kT~C zL4vc}dC+=kk5c);)=fsbIq)1iT|n_)4W}QC*=HmO59t&JafdnFKcUxdhYmF6)v_@W z@vT0w#l$a*0$s8PB2T*uFx{T)9tPoe|2}cTlS4xVR@9nfc|M&%2|i6RAp#r4i6%iw zd1cIaJ800mdJUL#O;HPN$m=e2T!+=$;-_bKJR>dreSL5 zUXA1pDq~jz)r{iU#1Jr!LJPsWXT83%B z=k>jmzUg~?|HL=%&QYw}gPKX4+Q%&3N`*4|A;p9DVInq8*quldyqkm>v855i>tgj< z1QUs9P%VFIp%#~7{d%{Ktcy1gHbO~Xd@QX%=KW|S0LMH zT$Ch7Qa}SkgmP&dvfXY5c7nLCe=QOHW;Ty=?y$%Wcu)K1{5W08arQ4KuJSBJ>YRJq zTLJlET#tLmiHeT^E~gr1=(n(O?NsjxE!=}59ZSK344^O`W!XdLz~EReKNEmzX^FH`E=zQprY zUgA@XH~vh-y=Y3o)W`%+GvXmyKpD;TLmbvGYEn!LORmy=EUG8M;VOA`;)sdqJI==M zZECfC(H7>T4jsif?s(FGT%2|H|GniMiYV=Wq z-86c{WJvL4j%I^d9}9}ZDt6X)j)db|LRT?Ez*}og+SXZb$5}ygk6ozIOV7;O_gc{3 zYbr;+%HQR}qS-^uq=)y7wk=osUqj2STr?YI)NXzqTo|AQK2LN#O~)wX*yb?&G=MV8 zL-Dylx@^!cV=ZzkFC*{Uva-JFV|8QKyq4p#SJ3k7XHO!Ysh|%T@t@dvN9jZJvBM>% zM#xsh_dxwUxdRyS|LGs(-v^=mW238}7diyRBj%?tte%Szn0+-09uw=DmnKJ`J3egp zS+>jzEq-5Y>>0+nSB5^jbKrc-((@1-#0PW`uz8iCBMsKTM(({(2m`r1ix1^rrDb+ z4)<3rL=%lCr03|-zMT4DuG%PrB!nY zkEKfv$i@EIaQz_-wW8o6A{i3jsQ~?AckzUrLz`pxVfD@9iyfq+Qq0Eb6f{d_Dn?I8 zO!MHz9hB30eMJA3f$5P2ftwe07vyx50oWgc#`(8vxGltS{6bs};+Fvjv=EHbUH340 zvAo|SdTyALbl++77H$`<^b<4R!_W+rT5p_ABu&mhJEVQW@1U_hs{FN)wYiIzsKbKZ0MbvAFIaId|=1-5-PxtCD8orddy zV=%M8`3Mvra2t?`A>_%Ad;Hjy4>Zl{OFx;);mWu5=);Nh%JuYV+5T?qBmtQ2_kS{N z9DcKf-&R$y@VvP9^n>OUcB^~G3E!_)ey90v7%V^Rgif~f zAfBJcg=0y|l)WULlXD;g35Z`jYU`cdbP_bu3wV zWv)T!s%BIi+CTod5H?m+^)rX3ShJ)qfy($$bft zb7DHr2`c@QNou25X`GD4+ab*$t8&&qnPwIZ3Rnu#8NZDoesc__Ho{-74IRWW_YRC4 ztP%Q!jr=9qn@Yaa#tsEpQ#)tIE>zf`E%z=@@ov%_orSR*%kKGmrW=P0fublsk}0|` z&mG*`R;yTob^FY!H>MXg%dA`Lb?NrjwE#0w~}XEm+FUK zjW;()w+d3YQ_F?~J^-gucj9ZzSjxY{>oLX=5^))S;U`nJ6$n-s`{(&~{(9`J6~tPp z7P`XkYpU(bZFEKn_OfojdE4Ej;K9t?-FTZ-uk8PF#y$T>D+$Yt23}3PGBFE5aOZH* z1ZRWed>`7l$dOpEtsoukxKGqFc7pq5kJb5?6hzZ$X;rZof-B6ul@m3PUwD1o*~+yQ z-i~^3Aj5f6cBpLZ@4|jla|G3HfY`3k>lS8dPX1p8=39&Z7Ex};)@bF({nEuPPw{qA zcx*U^J)C}S5V8@_?~MCn^75d6HdsUYb5FOc@CWK4`p(Bf@Mr0rhW#RXeq(=FLS{`oZSY6b+dtdIFMnvIPYA19yzdP6-!)0V3=a=zp?YtZ`O#1f zvGwufTb(p{tux#VL6QX{37TU(IS`#|ZH(vPYH>a)f(R`s3=$O+?Q@+__aFV%O+E5s z_ydK2r^{OFCwTcu_vl}{ay0uC`L(#ldPP24zMy+mJawUijWMJ4RiD1**uigJ@GJT7 z-?SaziN0=8M*}5^4-xON;r?vKWoTDd%T=mj{Sc5hk{%R`Uym4XN@a#iJQ7Z^6;ti0 z*1<>KeQ zdtUGBb?w*lx-S2X{$0YA>KFp^(j9s9H8w=+*@SSI0NSgjSnV%ZO_ zxt(KOr*PsF(%+Sq$2v=o-s^*7;{VD+2dTB_C_BO2njcs?sOu!>J>PSqY|51Qs=E<-3PUU-+1-6qw_8GpJ2YpJTW1@RUWw)?G%-yWl_? z`YWLGq$!8U>iJK&JGksS&-Sur#*`fAwrfwhcEdykNG(H~=&@kSn2O)@r1!C|4<$a@ zz}Wt%mAbKqCT$z3LONZ0;A>eLEiqk}`gNa;y?=aQu-_&iUM`CK9&@JIYAACYbj-XN z&ZV}4byj^B&?Ift%eFa<6Rh!U=krEM57)pFgpZbPxbZlA=O4d~oS0lvwRBS4{vV8p z{HH3@^7JJww&uH2BDou^aEwvWX}?!T_%DM`+W4Q~+<)Qb|2too{h!Yk{-=-%n+G{6 z^(of_>5mU_pgar-xyCQ-oMv83U3pJ@uDm@rIQK$Mv`y9L=4AuI&l|V|#;tSQ_=uD=|!Xv@QCiz8@2HVyh>0fUCe)f## ze*P9$CHhV<8gNeGXtO27JID)KJ22Yo5HA|!q2O+%R}`po|7_0t?TRr&XcMHeh;QHf z85Cx+-<9slSqD);O1;xdX_G6%JcOm4*Nh*Nlxr(CG-@+{)#_zvD01ja!SvTC)s@EU z8g}c4zsV7m!hP7ii>c?m?EU)*o43-*F@CWqJNhc6N$6t;Ss@cOffaNTB_QD%Z2^vt4V;q^wr!hVP}k z8D=7@dov{oc1IvaKs+J{qp4*lx)_kXwtx0;J9B@RYdJ^K%n7tR{E?Z)3KV6nOTkWSuB(_I6lHid+|g78 zt2z!m>jw)3vsql%wG&LzJ z|1>`Qt{K-=v4wVy8)SY;cLf7t!kOmHnY4>J-M%c%obH?E>Rn~i22>AL^oQa+RtyWc zYSR8wufdXEteB50=N3k|^WYqF9WS8U#48pE83#b->KkVJm=q`Dr_L1&{a5D!uS3@& zHPcVR6+!4>#y%m5f7*VI1xA z(nI=JZG>1@4SE6@0UjXj6IfSQ0=bNtdne4zd~s|Zw~hSgyYru#C}V=K9xmC67*XC+ zs-p!Jk^E0$;O@Kk2^gnJmny)m1VY0j*UGdyPk*HR9-?ILF23eLXM!9zf)nmCs&3RU zI3I!_?WMmWd8~E&#D1Fnv1h2eIY9`Pd+MK07xwp;%dV1t=xVbdLoeZ+7`E)j=wTGT z^TcS)4{q?tL)(#}n`yY9Vk0d~HLy*yOhsrNW%oR>$9o<$CZn|;LoE(xuiXKTopUwq z0Sn!4e$$vw-q2TW0pGepC0F$`?knN=re!HBg-3|1%Rvmj7F$Q)_0e^onl!YnZU9{=TaL8@g%FzVpOBqDOz{u{X;9&XaMqm8s@QIB5s;LbS5F*d&0l~g9rm1;;VFMnw zUlw7xG;yH;^+tfiMRVviBxAXONHj>=yfJBqg~Wv;E)t0>UkWV@hdX~ePpWb)M0o&EcdH{J+&P^cc~iTBl$5KZNQMldUBu3Iq{xvtDH1#jH+pS5!!t^j#4lTyUp;Q0n z`fh@|0@uC19NhjIs1^%ag|9bHROq+OcxOiMu7van)DWP6LReN*JWgnbeS{Za1K}~Nd1jP_4fY=``0B7ZbCm4jt>tp#2vH0TL}d+BN7zI+ za3@Yw*fN?WQ;vUlz?T2unkQ%y9y8`ut#52%a}*FXdWbBUj2JVc;5i9(Xb)5<;9CZFTAPK=p4bY9M_%pZ_z}vwt!3<1qmwO76%~vmv!re3G-79>LiNTw_TX z)qRrC;}@4P5TF@$W`+S+;g0QA0IEZfhr`h_C5`}E8sJ>g{wATFajGbf)y4u=P=!~2 zs!6GeFr%B?stp*ITSSD4u&|A@fCMHbLD1}5ds}ZxBjC6Y)(Ma$kMO?4Y3#^VQuFf_ z%pRV_>#(y3tsG5y$Z^n1sFLq2Hp_V*q_B_fYk~hG?~>-}=M-d)`Daf%az@B)lm-6H ztj8Vr;-QG#LwRry<%mV@a6E~L8&;iyiczeG{C{1EAf8`t_o>*i_|LWgf}SeZsq{vk zSc!lh_0thGa@YyNx>2-Wz$?HcY(Zrp;+`AT$3K5{rB@cO(}jws;KsV^6N z^_*&wx`~mC@lXEf^Ym1BfEhunS%+Q+Oye<*qEBYE)pc75x{;$ z_Er{mGacj=P;f%;_2-|4sWYCoE6qb<<96!J8B8nvBJb}N#&G1%FNNT15Gr7;5GZ|8jSD|;jR>zkj1*!eh|CvnLno!>{x@rD9td_DJf{wx1R zRXi3}_k$^QCkU~f?=sV%H}GLjsWvMm@6@q=@PHNm_=!=f0vN`LEb9D9`5HtHoqF-H zA~W=o8K=|CS!n;BONRw{UYbp;l^CZr56K0?1$+p!m+Vw9V0^icRgL5(`WX_RJMGh~ z;kq7=&*6t==N$OA_bLjUEl;?yl6UV&Jt1YwmcEAvXc9VaUl=aWiGH!HX4jj8nwNF` z7|V^>IT*y)0G!%T$IFJ^cVncTyVa4Q-!P4r;C+tQTZ{511Xe^`305wZ(b?i7C8vJW zS$;3V6{E%h?pYx|#0%MLH8?fFe8djRnMHa!@s~XZ33V*A!lA(imePA&-yuO#76(%8*K3sQh(?3fm!8ZADF6PF*V~3inSk6t}zLAf0&7 z%!Kmh+3_+~*E-<`S$|}suY-}S&V*j8>Mq;$^lq|!t}{)P_j)$Xz{*$l)d^NyqVKlg zLvr_Yr&lLD%qPYs-WzOh;g8FD9A3*UDgWR6$NxVumzgO=gW=xOpW=P|Ie~Bis_=a+ zPy0O&0NPQ0$d4gJGcGHA!G4UE<4eX14GcsG8i&Wkhqvsf_Qbu5ZV3#myE>HC6p~er z`~2rO=y?DvFz)alevO(%&Y0bQ0B>ac6b+XZ2a4vo`*u* zCzUGF#c-s)GJ`2+Nf7FQ(lqE)O$h;^QwwTR-3<7|ZeNNUhQ5*k;!$}p51_EuWY#0r z(lf6UCq6k;kHb?=0zauOTR?QTslhWS+Ty`0lVo!MQj&TVXi)8lna75Xf;Cu*rT5W zB>;kkOrY?+SLoe0%{F!w5o1tE?33Gboe9zeHAc#R`{?=b9ZoPxIQnomTG8Bt=AP>1 zibcxmoW$HykSC}RR(YRf*pcnX@3!o1y_Sfdb|dXYQ8y z6SPP-a8WkV8%Ro<9Kmr4?YwYE*=x|~nb3&1T^XH-H#x_xpBgGY<>)4K{XVY13MZh# zPuGTTbFCDWFJY>kDlKlvjFpl_=+`VQuVh=i)!U``BtIs`#0Kfeet@_FIIasZB0zg+ z4#)L$O@DHvOc!zyg-k^3MTp!iumMq6u8=)5O8bbZW3V&1;3YdgSHlIF1wu!)cvsT2 z!3+fMupkqd_8N#Oehp&Fhl49r9(?hOVSLgwphB-C-W-OnGGH$KT6)+csCpN5xeeu& z4WXwrs54JXGhy?-zdV<{e|d*v^UXbh^RTV6TK1fqFy~IsQT9U*g)WF+UKQZm0Pnyy z&I$b)5+j9wgwpHHDZBj;Zz%dxm7B&vF+PlC45q4jyK$O2FMTT<{rnz}YkMiatYJrS z^6AH9Mv~EP<0}D1O!5mZ%i`)_f^;k3?tLyk0V0j5&?RS&{KvD^#eZtQ>!`@ z<3c5VMaE)m5w+~S_bYv+mUHZHQZ?WOB!cT&NLaneC?6Z%sH*uX8s8}86?4-NaX}sXd^$YK_ zv(pY-H=2)UDBAJ^mzIW(!aHA9W(H8L4llk@7+L}NgYMbBTmf?c{^0BGN=^qvpfkyC z_MBVY^3R65nK~+^%|l z2;+_lPr?eOzQN&iN3LEmY;@srP2{&iy6@S{(AdabZ?7Szu~d5$)qqVW986hjGhh91IY+QL94=0I0dfMC zxexQS(4%qt7~RXc){^_)Xth5xM^8c1-H(J(c&%Rjz0aj`3tL6&+@K#1kf9n)av$)e zD*!#305S*5j~x2kYI$_`K4Tlc?ZRSNc_DyRVFUobaD~l^G7oU&Yl}}_A${Q$D4zwe zAFZt*P;jAGM6az#+o3t;Cd7F*ya`)fzAnG|JI^ZKf|5_EQKIy{HZiE{H^Jfl=o+>VGz(3rPIhRX_R0qSuWFRq?75UCLPFt79x5DvZqbatNU$?Cu zM*+I4^$Ww1;t15hDGb+wzsiAHP!qjeK6NAilqdipxgkpfVuIPB36exURwstLCr+^= zW|;>N>*O+=5V8b0#){e8)t|dR17t4%3YNh@H3ob(_f$dP^0O?tmmdu--(%O#Ou3c; z6JsM}>L^t7o#z|;(0C$({Rg}$1BAHh1M=2C5)I?+a20wWpz$5do<$lrvAHw`jR?8E z4=;v9MDCPpReICNCn|ml`4|<=4Nie4paDFAb)ZZG0weCJL8^&MU1&s#WFv(`s+xY^>Yu{E*_EaZ9ria4#6TcP0PG#_X{B}97^3A z8b9_kopf{D##fGB%sDxu&TZ`Ye_PiOxZ0B%+&e~ds;xYJBu?z^TE*-SYc$=Pjn9J4 zXgL<$3Ud{V+js}C*$<3>rL`6XY5N8w9YrD55yUE`Mo{ZCSGp?};{}L)qh0$%*5qn6 z-ac$W$&P)ixvXh_TMLL%Zbu`AtNUhvGa6+K^z9C)IjCe<={wI>e2bemXKj9NPkpy7 zKRp(d(rVItLXZ?<*as|aG^16qcym+vRZXPx*7&^(H=Zyr-YvYdQpDixlp zbh}(Nd%QH@c8PHkQ$qc#fwzHL&z>6(s?J#FO_KE8m)+1jbFjGOy6)=VJ~oXb2(k}2 zUXKqb&LK;<1l^Get7C|ylCf)jAd^m&rtQ2$n_f!;O_67-3=DScvZz1QC{Pzb9E9ky zP%Uz+53FXM;?r1T23MwD54=K-XqnS*q@!wcL}@W=+vgGCo}E|o~T;3 zv!sAmY6gs-Tk@&8ENNi1;UdIj0_$pJBY@f%lP1jv&4Vj7&?o8HB>ZwqdKvTZsF`}Y z+H`-vV$!}_W}qFUIAN1-GT(b;y7+{O5?vNwtKdn}!41LaCp9(P$e&zmgnXJ$QZ5xV zvva*4AI5KgxaM|Wh)GvPyWr7>+{Nf)jW zm;MMrl1462Ua-CZJr(!9RlEAlC}GKu?m^Wja5E&gg+^{rmhd7m8bDzK;qZ|EHEvBYF``n@gU^MyLeuIQJ%YLCtabm} zTq|2%y~k0#C+vOFlA4RB`;A)j8u(rghQE{^c!WXhFUU6&le)#{M|f@Hh2BSPtV)r- zOS;DPHhOhww$^-2!>sVIXlY1a@!4WMvWa8dmkY!0*0E7*4i0zaROK9VRk!ZzIa;7o z6?Zd!Thx*7JZCLBLNu*WXU^|Fma;+VS-wZTpO6o#Uc4kY*{*2(?c@pg^H<1G>&^fH z<|%87vmBs<1r&DV2VSz3?QFU5w$(jDBALIfT$u@W9H7rF3V@1SlhOVF6WQAfPwSD- zbPHK~fh$BmLRB);Qd9x(LfF}2UVq#d7ZAaZuw@zDNOpp1A2z>wLpIrF|2AdWbve-GC^sSR!65v@~y&2x>%rqPxcrOj!d zzh6TOp*|e%tyAlpb4{X3#jkJl`RXO-dh^X)Ngl~g5~3IEh!|S^!}8_qB~*nxX59f_ zGDiqfy>MVwYY8OL+FZv>T&6SQ9DH7sVvWgmf!2dcY3sliLNT%@zFs*ac^giUeqEO5 z?X6t5>;wGGDOvoM6pu-;T!9+6Xkm4So`U%FMeS*fdJ2H7oUFYbSsQx!-PJV{+Wv&e zQ_pZk^R?HG+|V@6;aP1*d*xaWHcS0QxEZD~(Gu4yUk|LceNcUB_9s-fkgWc|tB1%9 ztMyj?gq6xHf*off{fSira2V_Kl@1?EfK1PIKF7HoPQ@)bk9j#up|ZG`euk=i+I8pA zrgV#s%M$ily6LxFhJ%Vzp`_N%S{82?f?={A`MSa${77n8{Hlfy`S`($hgMwQ0f_zA z@pNfmEeE}7QI~r@qIvX23KN`=qAtdF6f?8*p6=YrS3-X!MypLWzq7Qb5^PKkVB=YP ztaeF$5cLJoQ`p(CSef+JoCNF!jaXZ?v@sDJC{c?cI*D7+Bu{n0-la5@u zo+eM4>KTb2mXy}yHK&;RwF6~nYNZI51|y54*CyidmjUG!HkcjGAPXywZZ4=rUK zye~U#Y7!!y?>RxcT-Hd!uh)NnGC@H$^1^$cEB%R!R}*URBa9Rp1|5z)Q*0q?>VZl> zXO2iWkZq6qF=w$|gXVW2C$RV94vg!9RE(2s=5ph~ONXfs76utOi}?8szMaqW;&oob zWVfx}YElRB<$cp=zUJ zcrrkVdKIB34>S*udvQkBP@Sc0Y|^wUCRhgIKY0Z%0_(3g4hIQSwkQee z*yU=HHj4`S&SSb8bXCC~(uGP& z<&D#^a;!3oV=lV@`Oeo36`+!^grx^C{HR{+A86y3Q6Gez%9Ylx*o?qhv~R=`K3PQV1Ki(%$z_ReaYyp66G%@u&se)BlGXUkcz?odL5=4?gz&fT>dA9f`!5x;ovz1ZjBU{HV|p1_P?Zj!+C=LASXglf0*m zZhKyDKeQ_U=_43akhS$|cxh;Utue;hgnsF_42r=%9zVctRST_ zv}f+Xi!g_VnUX{ET$pU-UScoq547UTm=7Y(Xr+D935Y<8juw7G&*=@GwtT+{)G!cE zKE-a7XUT{s>DrTcSNyAD1`r4Z%rGsO67|f_+47EM0>i@LGbg(H2fn|s355IM#TDqY z)wrG%@ot&*>yuTwO!_j-5e@shf0Kq#z^|AHFs5J)B#wy&e0%5Fd~>f5TgjU8p;FyN zQly0n{^#}R9$Z&{_wR~>oH3U>16X+CXrP`@S} zWg(ETS6o8>+f}Y*dY9r_Mfgh%S=d#s9#>-TN~U|YoR)P;@gQ-D zrpwt&Ts{}ix%UCB_L_YW+?VnI&l{k@6rPv-ClK&XBq1qe1 zo2uP#>yllk+lAO#k>^{&imIbFyPK(AblA6-Kj_fwH*d+WpoQCGh`B0g_L5gkyTT<1 zS!y1EStnPESdBJe=a!$PRDwatiqTY|>UeejaMosjH;MYE=Ss%BcpthcB)C0}JZHS^ z{)H&*D@D}q29^ZV+7b<~WG8cbKTibewh>5I=;6SJrJNmmx}Num;WLW`Q`E}4J4<{d z2eTVPdwB1jSb-f55AW`S*C2B6H*v-MRZ6Q^yD3=KE(wq71EzFX9ehu`b#W&Pr4-_J z*2CkAkD_7ny76qQw+<#Myj$PjSkr2xhrb11iQYyDsh;X7G^UqOtQuha2$Boh=oam* zPAWN9%?O0^2FJ?Y8Em~`W4M*zUK)Al;=AQ5q;H1Uqk`@kPkNLtXGpPca}=7>&{7mc z5N8kT9OX=Rm4uXGw_CZ*Alre63_Me85TI1bP0 ztuCoUb_4e>nmd35w52eax=@DC@X7A@Cr?SARt@6LuEMRjimN~E2kH^ck*g;q`RR_& z5R67VFQ`q^rk;+8fY>eSc=4cDa}Y<+ril5Fa16)Gl9B8U_&`jZN<=V}Cd$YNWe$pE z`gj4NjXFQ|0Hftcx#d+nR9i;7KxxA3cCfT_toP1E4Gh#DY-Z0+hlAN3uFZ;*9C6Ie zW46BD9+dXkb)e5sgDu~n?oeK#irg@wwu13Sg)ViEvp)?)oRw%NgcAj-(E}iQ)Ej=7`V_Pe=m4`UmsBqWWFm? zqyXArAqRTQX{_8j{hbFS>gv?H6M#Q)KM}ZHlC$PNMqH?}|EMgF{?<*xkN8L|j;FvC zSwg5-YopG_a3>u=U`qW1*9j$NMN{wY}yat2)NpEpA1y*mM(Tpdl zzGAT3M-d;&Q9zY08M2F3qQp#Q_D?dl(orOtKIE&uS*;Nn_yOXk!ue z;<8z|v2QE|QU#7S^~B1mgo6+QotKp?;7b}&)M{*et~ydC?oY!Q&dyo3I;%+=u`^4F z%ioCs_=`XAXv(W;goB5;bwkZtveJgWSWv$hAfCC4Wsb=J*tmrM*I>Yz-gT>txWcr$ z5eSni$k4_o;vQ-utAE7Q+iF?z+!$MPL-@|z4}nCuGEAci#yf>$U*L$u`p!)kyXniY zqBj9a1@a=g`XQyAbg={d*ysAUejLLou|91(Z2tW-NSvZx!$(1!g+@;f*P!{iQm8dk zJ^Y59Q10vra99o-Mx@50~?(w*gYiIKR{E@GR-Ht z2a`tOEcL0-Jq>KnD2W4h;BJjN%;=*G@T8o@2AwXh5~+q}J%WgvJkpslBL}X#f`&5b z&Kw6AeS(iGEhHS^*Cx0kVT2J}@wi8++?j8-4RbOdbL~7v7;GfiwMuT#7TDXiXfTH6 zhb&XQ*$7g1jp601MuAr@0u|G3T-NYKs2%`)iJE4ZPNphdmVqQ}C?oUk1BH^I5W@%1 zP!VFa>0Q-u!rKYNrxE50z$T7E!TccIW=!PtuYqtE8~FaOY|5=2bf%Mgqy z80WS;n1=*CLaWo`^CZ`_xJ{(NV{BXwB(TVOD}VpJ9@ak|x9B`(hnYV1{@Bo#s&K#2s? zQNIy#f#NuCyM~^M#*J^I6#4UKCS^P4t9^~C;i9B`=_fA+lJIrB$;-E8rdR%;pvAl9PTqt-++iF`9J2w zs8$UFB__IWhKAyrhY}puJg_oZS-DixIS@5jWdG<7`@w!yXAb=^w09 zMVN&xN9%WESMhIX@YwvF=SjR@Q1S)LzRif;l-;|=%{*FxdODg??C>LvB2V<1qCeog zPuW~L#&8TRj<^nw?zj5*Rt#8x7*nnVNW&Ea+bSgpHHL&=Ln(0vCRG&xbZq-he5Q1n zDv;k`DI>k>uAu8n6U=p^T>W56cnxRrn>D+60j0D_=jJTZ_2edJ6B~ZO!-M#W@ z)ZG0_ku8YHA=CEBK2TDO%c_Ic<}m`k5wp%0rw4{3&^I~P)JygwdM~U zKEJ5L`MLVw5pZ4`Xcwrec=L8m?X>=#vr*&$#vy+8Y&2+#7*5U9^jD*gGm_~6Kc;t~ zIv56n-VCKW!S&>WSdx4Ox({`Nr2=r;ZIye*A~*%zHTXi#fT|Vm zbr3knxGa>0`*kM$$T^+L%st!K8UTueWqf3UG(DA(m#U#_UpSNH`xUB{JW13wYzTn+cVRao+qnS z`=ibO9^rqf0C@8UFWgsje^PqUIdnm%b6x7;<s>w_?+qc|*;+gew-e+QH1Nm0z=&W||LUDV3?EN_1qVf6$w zI-u36JPs}TP$DxRiP0QD&qEY)MA0g(>Y}Yvs;ecjo>?|J%5zaG5J$OA0m8|Xh7zEA zA4R^hBe^a2U{`#s@gdUZs_@Ixcv-57^N>GbObkVO>RrYJSeR4z0D2p|kAw(;Z{M0k z;9HZ-(0Vxc>E&upPkqRUHW(H+bte==?=0SD2;z%QuSpf?)w+-U{9U8KlC@(%NTFwE zHS~l<lIdx@ZUOlM89$_(fY<35CcquIeaghoOxhBoL z4|0VEfGPZRM-6BothM-VR}+CbD2Q!S3|iGo z03KEPA-xtNDrR!6cL3F!brK8}P+I9yVOe9=Rn!H5cYpL+%MDuk?wbWJdGp`Bss*Yk zo1dgxBe4%Y!O)^Tf{5{^Wj8qY8-aRXpx*TbJ3+17`!z8lNtb7dIWF#m#OI(vK|=Fq z{%GG%?<~lFxQ_G{twuLjznV?T&I+6L>hhA6;w*S^f7^d5fkqWDP( zbEilf3Gqk!TWo5^uioV|i|yiAuFtv?ggg#Pt7=)w^!VDVH#s#{&bxtC0nsM_a8892 zsS0#+O81ein^lrN866p!H=h?+&wMc1!d~;Zq~S+2dH1JtTcEjW(U3KZod@=jav+`P z$7hdfZ(v5t+#Z^H3^CFz*N2_4*bjJl>Vt z{}vDZYbLFSrLRfoiKxm)tmnv3w?2ZNclGK6CnZ3NzZ!TiOmYd!03*y&ZP8t2C_8U@ z*H5dHU3(1vRpT0$Tb+MqN`toyVhVr*{lL7E{v2}Re30brXi%`varN`}-)10xoAtiU ze#8|p_q8@9aJNkt5UlEQ(cx)r6n7B~c@?4y-Yf)m|CUJL*>WoBc+ zWWbOkA!#lHGMzF~oqKX~I{Ddinl}RYxKj}8lxeWrg!M(~%o1@!PC7(PGAS)V&?ld@ zS}o4;6t3Lu+C1xcv-L+~E0bKsPGcVQQ8L|H9F?CtIyrH3PoB_>vK}@ScvS)ICkSB9 z;9X$n)=`ZT3OQtv_%gz5H0X)3rUz_F19Lo49m6#v8InyLbxvmG*bq~VX4hgj(pwVd zrFUY^K;BjL7$6*S8|)a@2cn*2hme$N6n4QU>tms(u=%eYdAZFT4Hw|s+f|CNzAQYi zK`SgY&e+*5;IYcUTS+iN<2KPlppqo#^hp*??F-jg$$)B`Y3I7PkM$zLuJxRT@&nwi z=RvDV?!dAhS0={*Qe}<_&t8sqAZ)>R0P$@yW%JT(T4>OFWSx2*Sb}+_C?A;Z3`4GH zkd41^-rMqp0T`50=$GZ};1_MDVa!o6%qBC?*nnsS5rU~Ll=i0=h4#f2Ox=Fx`I(+s ztHCbsGnDff&L?n(d47`T$U=pyUh$i?vJ9TQOJhfjyB2%WRm;z@fzI(H&3?r?fK{rH zDUSc~y&vvW%EBXlC7LbO4x>4>iSF-6hqO@~_@O^TLtk zV9aE>1q!QC2bb)b`qJytM^G4F=)U8$w5PBl6W}kyP!mO6l@0ha~bxCxA31QdVO zSOx{fj|flw_fPgaIk|7K7CSN3Q&XRqK*ASC3L#O~cKKfhOBI4Oxm@A@H62sMR2)e~ ze3d6ZL_+ME$vwc!9JMkI?bHF2WL4SA1)kjjgJfM9+(78Z%*|lk1m-@U57J*^Yb&?j z!ydPCJF5r6jEA~IT;ZT(f(UXQN5)Am$ItM7dSK_I$0QjM8bxYu0i&0O)2JQXQ0=^D z>(7Z+S~FFkKL#qqMtR9F+sDOMr9l00O2dfU0&YC&^bZ_xv;EhD7Nf@(+ie#}(O)s| zZI#0gU7#w3$Vjz{^qHAJQ<=t~#RO!1b^#v2RujT3*N#iZUVOT3&fkjZgC$G7^qgIF z|5wbHkN5-ZKfK4a9Q31_1YjP8Wii6#s;(R1dA%PVyoQK78z{g$VnE{D0O6=4KGqOS z=q$3?2lXB;@m8WQU*XFL-?#V>0B=#U0Hi!Y5nmh_4i_fRkaTM&_i-k~wW1y&h!Lhm zH!$%ETrEJkx<3~o7Qy9+p3_qB)MWXEWY@vLRHzWrYmTG^L9xXBMq}HpI^J2O@(RF26ICq-lh1Bb-bmh#LcOv;9{s%y7Tf^W?>07NtMq}xehF! z@z-Mq5-urtk`-T3lJw~T*#=~OzV!VrW+@ghN2}-u`#*;^CnGvnp1;6Z-^J}ow@3D- z)eZd7&5`r*eC=1!6+-gOQ$%gv>sW}a!27b(3s7A++krx02@BD#7Sjp% zu}b-f+U^0tm+hKbPkMVQLsBb>`^C5DlQ++HY^-tL^hP_q#pq%Q&xMyfN}(=<5~T_J z5cZE=ZL$QSo+H+!Df*0FJyYE^AW<2$bNB^SGk3SHKYBVM&L_h6YN>RvQ*f6oZjZ*z z>G|7)!4yIfUvuCWdL&ipSVy@UsSn3HCMnzI(bef8$k32Kay?wwK_}{v)J27TD|9yK z$JRN3L`Ky?f}70-LjlmD1KN1na#h(neFjBkrE8vV{`PvG`?&^}=bDEW^j03}--kNc z1jxROZhmEGUtZJ2+=^sqxfSW2vC8F`#6oA_mh8VdJZPB!KR>t-2CJ-kfs{&)erU&&#hf{TVvG+ zoxMJMR-CnSOeZIlKoRk_AHF8nQb}O^fG6=|&n1)jjh1)b+n=jDoAzel#+1on`55`x zLQAksBZJc{DN2v`rNT(}!|-EnS!j#r^hkvl*(-}nb6>W9Q*h7i97^#R$cg_}i%^}6nE4+8~j;t@*KYStloqoZAHS5#w z+)@v;HAY!uIzaXwEkkXr0Z8Im!g{NLDz%%M{Pv_ITKREfnazga58?lh^| zvMut_Ib8JkW=jTly3P&Iv-@9a{QY;o_kV8#XjJBFOa5RMlH8}oTh}`wDc+u`H0)x& zx9Q5JWv8Bhk|@=acR#nu&GgpQ%ga=mOo}{`K$!<~?olht!JcPtl5RLiWc@Ky=S{Vk zDDF_aWMz7~^x>1pi(!*Pw^|<&^V`3?Uipf1ZM=OJ8A;fTR;F-3LmwhU(<*0_BhqP6 z@eS)1pkgMv{`DUhZd&Us@Hk#g9&~(^eLLsKd^}5Nh`a)9N1DZk+3xI8L5c1nw5eoU z%%OO#`YOKRgqvnf!mfDT6}+-B?5uI1dtY2XAEtnAP>m3VZ$#TsR#!_%PNJQk&>P5^ zp+!(=Vsh8MLmd<3;F`veQ}0Ud?I^tOyx!_o`pq|AJW)-VA#eoRivoozl%FLb#9d1r zo?f(*jPvky&gws=X(qt;^iqseu*E4Jk-bNkwXDJRX^=-uKm(y zajV<-Wv~VaktAe8^V&1ENmO$xJ6_fU3k5|4Z)kOqa)$@0l-|p>0`g=+|EQpUW zTNAE+-~I+deK_@}_nJJbV)E0Y9f5k`)!iHs)nugqI!*W%O08nL-d(B_?L^IOtt$K~ z&IbTw#El?!fjzGN{F7Rq;9830?kMDnX^My^(>6XIIbVQqJgW7gexI!nl9#m(6EO|s zcN1ImGk`=mT0+gUuzO%DY{jtc^Wu1#9p!Pxg!Bg^op5eq0D?mk;E!@rf` z6`3(VQI(@J|9nWFYLsZ4FT1*LQb~>fRSM=^MHv^ww}cwF8mT7s1D4}@bb(K7O{~C3 zgj@D@#NiKVAcc^(=o!lbNADTfBB1;Oby(fiUCR&+;hWgSjwR&^3a0DTG&xGV54^1< zoj?!=eHi1&1y0~JNS{Z7exHtpckDDx=M4O(wmH{GRYd=Dk3u|0LkwhH*0RJ9(qddt zqBvp68{z%hbKH~&4t(d;Dni6T!K*DYY%iSX?E5m{{S58QWN+nVP|tfa134fz*TD9G zr8=K${dV-Zyg{}oXR(}WS-Tb*W=`xwtixPkwQ1TfrOyMr4NEV6WGRPUBI=g>?N|*`R9aa@f_b0wldz7ZlOJ2jS4F@W%mW_t}%g4)jYNA!?LcAX4lRBHREV_ zai@c$*5Y0Qt#MjlJ^&EfO19KZ>`sJ&W;Z?pm5guo@&!J}Ix}Sf7JUh)fWm9hgC6RR z51%Sol3Y>Kl2j0XD;99<4?eIe2Q^r=unhpxR`I|6{c3zEok2OcLbW??Llw8P3q-c_Oi5J4)sq5 z8!Nh$X#UOhTX@e<xs^vf& z6d*y$<~<7v!(x36{%hsQ$PMpn*X|W?E50DjN?>wD;CHQ~TaBY9p!d+@9zlZ62mJ22 zj?qeJ)MWqAZ_)_vMx&HpBW9a_Is6QbA-dxOkTWZH0zqwTF_Hg*H z%CB*oa!nItC`B5&o?phrFGMcv&S!uu;h%BWpCK!Fe44$hBLzo#a<}C9?Ie9dM_BCx zr2}bR?#TYxV&f0;RnTADV%yBkey*Tfxv=y^gEIOxu*w!4pHWSlkuBXfTYsie#eTvX z9sYhPA{M&hfd zw$;1Vfiy*K!w|qMyW8Y&h9NMjpvI#Z*Wb?O-_ugWL{63=W=9a+4ZWx-eug6$3#n7z z)l5Rv7;g8lTYDf5dMXsQ*VavEtRMGk)Fmz1{MK)s&=t6$ZPTo^loy@!7$shVm)?>N z`A^>v68Ga$|21p6REu7N{<0ngSz!GRLt}6*DBDMf9F*hzys(kvbD1ZWt{S;tM>F%{ zQJ=qy(8MGsiTu#JM)yfBDc5}?qMXvx=qbj!5Of&edGq}IPA3PzNFFW2nHhQwt$FKTB%mz9@Wjkr932@UU^44 zO1G5oGSsmjlwTPF++9{b6RJNGtckxF9$&haoy))qdaA3$#GYxo?N%OX4xjzWXzZ?@ zQz`PG5rEj!$5yLTp9;nrTGd$gZ-abEh4;ViqrY8ubLzKix;p7NufYicRlL7wRWV$9 zUnHONeqcjM3~i%TZOV=WJ;AGyZt0JtJ~yAXYpc8hN)EY^Y9z-R8=lL}=>sk%N@<@^ z{l}HR*_Yh;k8;_lCCcMpZv{a^=NI8>ZMU~HP3%bw2`V0Zy%zDM?VZ(g-y^NLRbV>& zQilpL@llO+qWmU?#o0pD+^J=2BR;n&z+fZjHAsQgCr+dA3tK51mF^fe^oD^r{k*sx z;b17(H~BocOVc3hy^(a4!4}uk$L5vi^Q0v-{_X~_Oc8c;14^Slvg}GaaZH!JP%NMA z32<7ypinO65kxqIaa*;81lmcHbp9qi1joiLdMpt6t{O?Bp)n}6SWJRnqGFdgJgvW(n|GiUIS}|vJ!AD<>phJNUyQRQQ_T& zQ(iH`f4d0XiGt&VBF8|L7tF*b*&a^_%=k&#b+$COUc*0R=nJO1xr1RYKQ0B!`NYxf zz$g|J=d)8L(hS}l?nI-qMGwZpMnt;&fj8TB!B<2&%)6}e@~XoVYsU@`nn1OgoLhS#;{G3Y{i_hD5q5JS4f);tC)1;b zI5LP?fk4gz*9&d^&LfCptN|%XG|;Z~;~|f4_5l2+K4@NF&7S$;L@)jIZhq}$7rbHA zU7*+G4uEWdkO51-2gdK{@H4-H_{dso)5_@n-#?!WBB&!`h^Yh+n_QkfC87(U7fU}A zFhLlSy#nAbD=%^#^_tehXaDyI|4W5Gd7-JPB>GF~iGuX(3JK*~`*kn#pVHlteFnR5 zdz3f_a735lY@_#l@BE*s!_ScPn2sQ=&bUCh$|urr3dI-~dFsdm+z&-t5K=4b=&nT+ z$=#UcZGGTTuAR~MmNQYZ?8P^vhWGs6{^8@Pe`S_4Jqm zjhKQ0;9&;IP2$#ZGzC9z6=FxM>7gi*9yBH{F1%|62)UCB=OG)#K zk4CPqv%t`x5yByE&x7{D8=xjZkv@Q~4b~bWLm&axUSIFlZ5`WDXD{L18ZoCdK^;P{ z?OJ1n$C($cIil$KtLgjj*>8^CTu7uf_tZ{NyKtgY=shs?CeS>9G*=!ZJu^5{ZuQ@v9Mme@N{isik0oUukB=qXqcNA`or6=NT zHl@B@Q&VtaBxAz~9f_DDpfVJ}k;QG`NYT$tPdz@8b+ode$F}c2>ya;(#4XM;4?g6m zcjm$#e5I6x&ExIAjEctKKab?j38%=@jckgU#q9M|OOtzLuJfQ6C713T?>CU`n&v!S z>Ho?^th@97WADAgqUg4CaS#*~5GCi9jFKdYk{SabA|fatu~jk%h-7GJf`F1*KtMo1 z$vGzhX~~i#N@zkugXD&8Vnc`TmfxJ2@te7G&iQ7}{oVUKzw<{uR$*1|U3=GFYwfk( z^{yp;b>e{EHb%G*>4*S9pIk|uF1_&G#n~BN!uIV6U{3L96oaZIbDM$u>SpNxzmJ%` zrs1M*`5z;6A9!9+>lCtox$<@Sm7usGE#mT!uhJRu*Y8f_;r2%*K zL9XBL@tnCp2H$Et7;Ty8LZ#!q;E6ol+S!tyKcjZ_8oz+mbgWY^kw4F3BalB-b94fF z=p^)Wexg4F+J3e=0OGKB@zpe8gMuAbxH4kd$8`wWAEIzfjh7Ekl#;)W*Bzp2+1oe7 zYZ+OPq!6WyFjE`qK!JuIVB2+slxu7GAE)PO;D~8@MltTNbJwA?WrWvgd3^GCdiq+p zG|`Q%`A&(&?B6p#M+9Y14ZhfN*!njL!+-_XbK3yw+(HSx2Hp{(`x)6I$THRtpH>e= zpvE^9ocX}VYekRDO+{1>@5-2-z5`fDVR3=hMaZz9OE z9ve|P0DR_+_B_lJdT!ZE~#_D zB~xPLJ(N|_Bbr5dx1WLN!KsHU2Wfa;${(UQk!0%7YAuC+`}Kg7N1^+Lov>4Z@EuWh zz)%%E;sYXyggbC?G}MTZT-B|P#k|iRF|!c)#z`~3s^JUym-pmy_)qV-(V~P;LUn<; zpeE=j6*_;6<<29D)ru6eKK;$YAk{ENQ{3;=%kTbm2JGJc1;0VK3RG3`Sv0^_dyMZf z*!E~0<`HSH_Fr*YXWQys6j9th63%_I7|u|4MiMZP@ku zbFz(`F~AqOSH7cad=LwmO1Q4H1)F*M)Kf9m?S$%p*o$_cmm@#1+u#57C7S>DFX5|e z$*FMX^tSb1{sG|I)%SM;#dIDcHl%A9&zsy*wQU@6S%?mlnl}!fD2ATFNg_g96nykL z+236`Q2PA7I&}CWQ~A66se}szE}4ssaytItuQD<&(IbFQOmOgz>8`^-_Q?l4N*7zT zH!RP<)e~`OOW-m120p#?#yE4slB)r0*Fiwg%&rWKcxp?aRK2fXym=f6EIP+*IMNl( zL$!4st!qHreP|WFd`p9`w}|5S;gwt?24_Hc?8WoEEov<-L6H;4ze8z8JTi_55+J#Q zIILPKYJH#AaZoRr{K@j`1sKumCa`*ov7*4TV!)&3QS7sey(6^)O1Rz8XY8~qd#pV^ zsCHvMdR$)lJfZohQ5Vyhwo~VlL6X9Z{qNJW{oyMF>;TW z4ZLpz6yM$&B>0V%Ze{*PA#m?IkZ^#gnItH7aet;Kk=WX`hXH9&mTD39IeP`=p``%S zE{28DEFpgP5b{Os07`l4@lj?CJa`X4m>Cyr82LdF`@IL(0j<1P1>`&ILxRang} zfJYJEvdw3dSmrPR&q#aRpauR=)RDKQD>b+y&XkrdUtdjxUjlNGvh=2!jX$hb{zg$$ ziLHOxu%eRn<5rlS-GErxD?h3Q)s6LjI#&?ikp zgQ($W^67kf$7{KhW=OSw!&~n6m;QC!Gk5uW?v!vL0X?t=UIs|c^({oTF^FoHe1}|s zl@5wbcvh2USXcW=?TvXuIE3hiY>qM-mDxpl2Ig+7*w}7OKg?ZC6@xIhkQ`Jjt~W)6Fdat zeMkb3Z4m|HqM0IcWBYUxUY9~8<{s}6Gz$yNMOSzVerAdQ8AetlMsz=!-IBe1oXaKJ zctlrighQBkw_r1%r~CwfTomhTK?EWSp1{I5y(hLO_Rk!krs^NmjI^lX)tt5KOm&N< zO=mK1OPSx4CSS!^3L8mmZAnO>TWX%hw`~YqUgx}boyg!|#DjgSoELMcJ%cI2W7z6{ z`?})Ofl@#5L<^{PIQ>~(dF}nv$s=ad(;iRH!p#~?CC?B&LH>=q}zR?Uf{(WjTG{@Mj z58|6;rL(*4#2rPJ+j+Y^@n+r6W=UcOg@+pBud^ug2+@MH~i7y_t zRvr9DR=@m7XCzi$9C()8?*(Qf)8iM>&6cvG60XghKn5*PGLd5?`TnQ+`XnTKGC%cs zjg~c5ojVq z@_SbBs80LU&>Ps;QaKkPCh0_vO)1J1MXR!_gHWm^7$ejw0K46d1a&aT+?-i84XgXe zRDa{3N+Oc6QXFEAk6Q2qU;*W4p(YbXNHineMv|AGam2PwOro^G@$sNR{mu-rJWAZl z;YvbHBF*-hUEIAoshNc9|$ESk)SR0I21 zwGWWXA&p8bEg42-G1f;1(=tF66)(_V?UadeX!=DBmr+P?qR+LF_iPviJYO1C0)W}B zkyUU|*oFs;&f+K#fs@TZ-F*i8BF+7?CRt6(1s`c${Ka|HE5=+Ie=w`#l}5GbfpH7b zL#4`ujf%Au#Buvzd1q}Bmt%IKMs@9H34~Gq^HD>dBFXg9HJjr)7JUs*Ub_bJK=OeX zj7LS)rtr2v&G-BOz8}+DC0seKb{ExJMVa zDHIbbezBGM1+7{Z;+D#j{B%GCpa(mqU+LB&qM$O_1I#CZK%qVUrHSK6H|JVVoW)rs z%GmJczYJ&>ir_u(i!T*gB(9?(A;3kTCy=JI$`@n|!4f)?)lT5HA{NtBj*tqZ+8wL1 z4PUnF$E7b=4BkFWh?8cI>QqHyqE} zh;C5;$V^Ema4)p1%6vu-K2rGdiD7qUOhF6IdYyEVx#)m%dAarEPmJxm2MrZ3+?zA) z^ViEz%WjXCR(wBWSV)G`#5Q2)78^FmAfKw0FF>h!6?eN#Wlcm~%U#b|SAnl!!}2^L z?}8a50#aw&lruS>AG}Sx8Q==v_6g)Jeuo2!2GyGzchw%BL@&j5o8$5^Hz;;g^cQ|K z)Br3ynUQQ}IvvOSx;n0;7odn!a$2s-QIIPmkTeydZ7gbl9hBxEJwO&+Sp!H;HCX5T zC@o;^+pIHq#_mSZSc%;gdt}&uIXo%zjI?HW=7Ymw6-7IEh5ejdU5XIMd-KYn&gEnh zir*Wk0|S^d zbXoK*gI7-i495V8#6fvO^F-9PZokmD_oEPnhr?{>W%qs2NKt zWEl1Tn$+*V_0(@-MF9vDSs;=wf#s2~coiaF8LE#JlOd*l?Dd;Xb84UsIU|6zfpnH;eE@b2C-%N z3!af918T7lT|nSj=q~r zkOQQF-IcP9*IYM`YhM5+ZDnMnzL{X1jQ$;QYZj_l4VDL-2gcDV;!ZgBgMp!%s7-2I z*T;p8jp*Mf{5#GeXL>U6tgQpkp8xt+fs|90Sb{k)wKvpvRHPS{8=Amv0HN}@xQ_hs zwE#tLk|!9xf_eUU-;4Yxch^{NM=LY*`}EP%>|NdbBk3=IiLk9oQJw{ei-0SK9SE*z zi;FD{2ae?V^?fu(UN%vJd+rLJTJ~*x1AyMMp9wTcIX97jqPdCxAERXQIY+*5$&AOIT&lRto}`9aDk zBxpl#jO`s!*B$Z+f6skAku5lT`yu?Pc>B7^a_X{OL&MXZ+np)zmg0SdNRF5O;_lMY z5PNas@@71cG*~0A7Df8FH;rN`|7ykfvg+uo{;$^dHd7n7z3<9af z8*tMo@*1O{gSNAAMv+_e8T?t_yiX}xQXI|kGPbtYgfg_jrn}h29<3u*1UC$Wc)haV z84uqP50w0Q0qkIYu7Uto+^+8D2{l1{pz1|>Op%XM8_vubDA606YLVMSxg`=ay3PRI zfP4U-EaC2`BC_IR3fe3|bWV+7Wgq!1zBXEh93ZQkGEz=^Dn;+p(%gFwjBC%Y^S*4`KkSlLyQJr{YZkHLk-HY zdp9Jez=h(wg~k;;3?hUC&-MsrC93`IQ3UdG!-Ih;gVaNN$>fGUAmpOprZD~Q>6=65 zH-I7*Pk=ip|Bi!3`xba|5$UD<7a@EL!1DqC>xU=kcph&*^C_G4HD9|*;33x!!l zie($cn^@b#ihWO?($}G2$o$3SU#H;D9U%90)LEK;OrW0mRB#=iyo$CW_*ohDR~D2aB400fe9LH_&MPi^tA=Q8&abmP zMYx7RLr)t3m{-uk9XR?re-02xj2-y7Z9{y-{1FsPwKkqKK9oCZG1(uByLBP6p_J*O4#!)zq?5ohgM3YGhB}KVeMxa+w%=y%dB=Lu>&Y5`hAMh2eB5QXMe9p8+!P z1tS3m*fz`-%LrUPIwG?9Vm_X`16h+Ao|yC1rn56)}Tn>~S_Y2Z-TM!rgU_U6^=^nwpSO2!|a zW|evQw3OBQ?h}q;4U@mS2VRW;y9bc|+aiXoi$ppwlXHzZWG?XP_Gd9RB#;-DE>r4!bbto$C9E; zkqWS1|C0U7t-V=6s^Snl0>|FT$2Q!|T)qx=9D%CxRIZJ~=`9T#`!RwTN?(coK&ymk zDX$9+jY1#6j?gYn6h(nwq{mYX*%J(Tw^ZQ;nF_0nthwmXzCfc>PCOf z33P~-CX2xT!z#^+f&AewwJ_joJ8zALf!gZEVCeM7{r!^_=Q;!kcOwg|FGy)4gDAA= zdMMa_f4gXlvN{p{sM_&A_u2fXDFp0MGVmekF_;lAS!j_jPI+EcI8`BY>nY*x;}35b zKG8V6QNN%_9b)LV{0BMk5%$$(klX~28h<>~TNwSc+~$)^wBcs`Ut1^z*}tx_EeSOl zqSgrUv_H11{r-7-uILRnck7DIA3Xw_*T5p`B3Jt;)UCMKsIwOP3ku%~O20Nwxgm>B z9Qebi+5a-YRRu+2e{H}i_NE!5VdwV{CoG9F6=T$z|d|%vdI;+?7=5(y= zmvbClVZmYzfW-QB#RD?Hini;(EP+E)v1;b8HS(Wkb+`o>U+iIMt!o65FZ;lP+amt7 z0^Os9*9Hrv^}haO^LbZMm*@9RQx`1`*cZNin3z*`H!G)9*!|bR`m+K_^QS;+pF8`# z1!V6BpYm|_x-B#&X%#N46J9s_WBbTGxHs2A9;@Cfaytx`8NVBawk-9bYf9^Gh z)PBAuBCIx(dX)=kG4otEi(gFEP4>j+6^&ohf-TQf!QVYz6i?3yU9Nf9d+E-Iv53Bb zQT(UxPK}+YgV~iHn&TtzkC%`+@aDMjFOo*y39-WsL@mp9V5^!{MUm1oj*9FuM+Oq= zuu3L=;uzJ#za+(rMC2g$yC5XW;@4%!U&^)h{USyy^WiAD3Y~X2`gy%T5kl0mM0AO?Nxq5#zFk zO{Pi{NrQl%29$E_FzGd5&kxQ3*^mn`JVskXW>*&chllLR9mBAdEf@hvfAY%73R?bK zzd+gl6{rv*4>=-al7AYTyx9b1Kx=1y`iaNVF51u&E<338W z4hZH}2@wy&PZ2H>HSm&biN&SMY3Nx-v&x1siT%v8cMr#bR7jLvL*KhakITJ=5I?b# z$<*Pj=H>pByOOMj^>Bb)J{`oT#y34Bi8%->K(*B7`S?E^tsyL`&P5eEuA7c?@9lhv zZW-s!mKC$PbZ<+%oeU-q0y}18jUNM0Iu)vj_Fr&wck(^x=OH=!sA9 zy!qFQ27GgT%0$Mt_H+<<%`LP0PP_(PU?qQ@u=5{Hm@a?26QNtsq1fvbjZ@rA!#TA< zsP?4csUJseMxa^+*Yl=Kk&v6-0n0OOqn*pGRM#T>q;A|XxTn<8W_uJm;y*wKiiJwc* zwg2g1Q3uon#os)PM?ly<5DWW(d*;E%R9zXU;>qu|N0WdwtpN#cO({A_U>a`tw0t&x(S% zzuvt3AjI(#AKIoCExV7vGbLkcE%%h;HrquC%>=Gj1|wM-VG$s!~D^o$diVP3V} z2U3|;ai4=uO^!D%2iiMP5<|#^N7>Q56TW&QicYu3KP3BL=*z z2k05p2YS*kzJl#mtQ+~itFDnssOCqfuxWY86p)f1@Cr%5$$T>uTQ$|x;J=6M=jqo zzuBLHUH{d&?&hy2JZG+hOn-PafS86YN&q%%fGpG@iR=4#aG{o6vCfjoz45A7Wj5cg z-0FOe$+%J|Dv$98@XPQsvnG%5neE3(X;*UYAhkRlBqXmf)Vyjhkh%#)Nck?7ieJ7O zDL!nxK+~BwQKll%!v6hRzP+HsX6M^E=nW&-w0$Zd+_gqRs@1UHUop(~ zG1d8y+q|pQRNutP14n?2;&LRF5#AMziee+PBH%Z%3Z0+J>g9*uWsIApPe1G;SPS1+ z)-8foJZu?iSM~#M=HqU5AgaR<7}15>+(x7M6I**Ul~v&mTWEjfM`bzbZT$MQ+Um1S z7eX_xWhWj`Ejx-A)?gK5%84>=i%z_J$Ifgc*I5p6(_hCcZ~KY&vOld?J$>r4_yTxy z7blKJz@e=3O=hR}nqa&eY^hh$iY%vllOz>p`e+62=Uml%RyWW=;qy_1CS2bVfrbS` zSX7i3buv$y+1DfA53eVu>eh^VRqL=~I^V|dgv`9`f5|Eoq)0h-roRR+j)UJH18G-a zld4rmZY9*nOx_!jFkpN5;-f5U$|I_wH|neQ)l~hfWh1WPKZ~2}l`2{^40*Ctj$5Bw zJ7jPYi`>$j7m}`j7VUphXtWfd%+qRVAP6T%>|e}fk9Qz2jTpJs-N;=ErF37;3hB@E zp^TT&c*mp5ibAx(BlUeUP_42)PKFk?J2LWYr@lS$l(1$y8~1Fk_aXBe+Ajm%s2bzV zeKcaKx)Z4v3bk@SIWS)OajkLvh_XA8EuS_;@cDYq?I4U>wB1K}lP#KHz_S+gb7}tB z;~!lE=il^fSwb86EY3K_RSLkD(5~&SKbV@DL48YFwaBimj>*d~qRP_Zs&4W)bNa(s zm&mD!=4)sWon=`H+Mg~)>BmCk!qdjrAKmF!g|;TfvZqc5&+M)nU(99yMnL8qPpw7 z8zVZ)`G8`T($04Icj{ZX>qdTLtS{se%x@t5U#+~8xX7)|eaYq(L*$X`0S3P|uNS3u z5*rvfCtr(CThvw7|Gwqgtml-g_V!+ymn6BzK`frmJN0&o$P2HxQGp${JQK_5EVG(> zfJq>J`EPHS0DFqCy8yw^0S=yp?#+EHO0yxotQJK}e3;gmZ2F>$5Svkle35HV*XJq0jE@TF+=A{RbUgHOFdI#R4&B8@cRlG3HEv7pf>RW^#-YnLb^f0Hwp#xAHNP;`g?x6}r>Ws>*1M%-5$fe|%M(oHlva zca#RLOu5|T?Xq&UTLGuRdhZ$IID8tk2-=(uz)ql5;jIvk`Y6{HN#f0@E@$Th?lhwj ziLBWD=BV(77}hQNiCplD5s}G5m!qKa9zU_%ixx8{{!a6WY6BFW$*jV>usubEE^nK) zJnWr->Xi6cZrrQeS#nk4RVLiTFnoTPwYj^vFv&K%6B-I1LPQ||VK9xRgMo;e_y8R5 zCiFTkX`}6uWPI;2CsE3y=W)i)GTP>qM8>TOxacNaBFvXc0C8@$_<_SC#wviN{~lH^ zJdlF;91kns2tPEzS*>R4yzN%zRi9cv<&ZnqvttX+JnVe5!c)(>ZwKu79LgiOP@8rI zL?v8ihs>f^W;>Tu!UBqJb`@pUGNhoxS=wJMxjvnvNgZ;{Dkk18$>Vud5k>?dQ1DUr z1Mpe=ULE`N$2Dn^8;~fX?ud4(`}ghlhlZaVk3d-XZ`aUn(mMjcT!V)jQDviK0O+_& zI;I#LMl6AV9jS!?S92_BdwIvo?CRp#ppX$6!*WHyyB0^3#L>Vdpf+gK zt9o`tBzrf5cZZU~R(9U(da>1lS+Pj?a6G3MY#G?O5*zZq=) z7KCVV&1334CiXVZu>>yR=+pqDF8Rq+=6Aj*f;y2MU#!>(VTSVHiwp2RYase(9;BO{ zmw64=r*%F#Tilb#Sd}UoiWA{>vjV+?HU~#S!Vy^g?a6#y{2@R~+2WZJZ9)MN75maEaUo=jz9ybUb=5UOUx-Q(Sx`6E!AM|}}UpUUjo#*+MSed#x?25d>!N?>d3K0vc*J?#Y zWu7Eo_Bq>)R-G-&M{l3O^ZEPQ0E*r=yV!m_=4|n^C9ODx?yW2b>k}7mFnlw-UV^}j zYGGWlI`b==YYWn}K7D8ssy#-h9n5TlbIAwDW*~#4%Iw_q8qMz+<5ylCZF6^58BIr5 zQqg6$Mqczc_75fr5ZOo#Fe?V>1M_hrYZ1Oo_w1tiu!_?Y=?G6+Pp1M*{9Qy+hiz}HG zPp4Hk_R`x6nLaT4dB5YZ%l1N#vz)2!=Z>xTC%D5M@uSF5PgNaFMAXCKE#aER;Cd~2 zDXTc{?D3X&0Y%5n|wx`AY z+8rwo<91XN86|2I;<*m5V+Bpj+u2`gMF@xJRKdmAzBJy#$5RF7-6^k)F#9P|bv&cpczilEm0Xk;Zsi2s9#v9`(iI{Gb9x(Zitzb?z? zW`O_Zqh4qx_P$)ky{5sx0>qwt=!F3p=83i&I^5Q zcJVz8{Wm(9z7qgfveWK(WXeNllOO=M^A12bsQ=jm^banl05$^K!tkE;#EZ@#G8Y&F z#-`XV5^lO4B+dBl_&y>iZsC?T*S@)DIL!(JvP;NUw;Geu+J(YIuS~1hZFB~54qK|4 zXJ)*}9KR&qG^L}llvth+icrSQ9^JQjrc@$Y0AF<%UM>&kB z0n()p+mUsl`D;kUgVL=^Sn-rYGJ8FUv_3URsl?}eyn{moflhzGDsJwj0^nPUwfZ@r^0CfhPwh5m4|lpIL%@Zx z5Ai)YOkwc8FaeFAF7ND`2GM26%0oE{brrsvrZkuS_jXq?sR+j=O44bc(RLV33;U|9 z&-gaLyz{zT3aCMlDgabnxGCJ*?o^C_He+$*6G!X7B@?1e_r8Fh1^$5a9%fx0evW7s z`US*DW?LnLhY$>Nag)OvL7S?{sQefRz z4+tQf2poh5;6MNwQ&`^;r$lf=-At-Q3k#@63PG&RqvGMvfU zq}ijwMjSZewP0AdMom5TN^pq}7rDK2rJL`XuXTn6jsECTlbLW`qij~kYaXxi6E$|2 zrw`(GpFACHIgR($$4a7J1#&=DN7V#;)<+k%+j~m)EOdn$VwD+gjNB}=%yE*pu4?=e zJrC!%mZDt;Q?yqY1ij~BQg*vh&EFe;wVN*-Zr?vIWGO_<{%k}rfF#g;<|A45;zxsB{r2f^KTcrYP{!&1w$WM_Nx&_((eLu2TB@)QiBHO&)^Uy(yr=x~R(gR%xI z9qCc*$}Ez8W_oH?S0$;Qj)`8N*XUx>jckg`$lE+iyQU-YdIpU=J1o zUIbH`-pqruw7!_|N?K>)S1r~ee81jy6rxVcL0zb-J-CDk&?Vf4KErKeRB;se!|v3W zx0Vl|(&^l$ZsWGUF6#K>v{1Z`%r(&=3Ywtu@P)x`1zH($?^nI`puk$@YUhtLpYmt4 zeLp6E`^T#!?7Pdl>D~5D`W%mWIt-M4E^-*>l;M~7)=t0a)59}w^#Nn(sQnYZa{;h; z|AT|}zkN;h=LxAdMh^8dIA&KKrRbk4KD8cnwpZ(F*^Nl*;YnYlE0F|5fT0M$eWI0~ z_cNLWJM04jO|0F+>Myb@c56^a1UUH!Mizi8>jHr&05`M^Y!}et@T{O8T2EFSfH)M0 z1gKr22A@|N;2(4Y;!r@~s>2whLD?JI{%sV9e}M@)|LUT!(@ei$v{nDR?W3jUjz5dv!{;&OU+q=(Gu=$5Zvw!W*;_8QM z`u`k)e-6Pvzk+`*gnx)Eusm#pp8L9{)Y~5${7})D+WY?10RWDyF7$W97ydhn__~G; zi>{pWU8;%Y$B6#O%uP8zK%~O}ghJ$pGaiP66$3yS9U_E$3I1S)vEsQEyJHU?R(B;MzgM5SI#T57`Gx#)P<-u~KKTofRv&~tJYr4(JJFFz19K38d-^Z*z0Qg6-O-qNts&*wA9!=)t5OZ)fk~wa6>#TQY;aj4U&zGmNrXO)wUs zEIw}DMB*u~K4M>zw^p9XBx*z3d7zCsX!ta%cl3Lk7vgKKQ`HBe_;lRh!Fz1P=J4Vp z>E_ekib#}owU`#o~|(k?O-zXioKA!C7uL%14LLvI(kXKk-dzV1HIQ5z`{%kjY|$Gq2}k z9#iA+adbUzKIzD2AlZQyy|r`aQ%sg#yBIkaK7{eU zW9k2B`v?B>tTz9XC6^>7nqK!MddW*aHL|7#W3Y19*6DeEpe%>qeQL;5Bb-R+0rmnQ zY&JnrAF%a(!P}u^)>?pK*)p31;L-%i@~}2zAe!|83|z%fJOw`Hb@1-CCE-tIMhq1 z43?_1g$GxQUhgaE`QhMqcC-;mGIT5Cyxnn~<><-%1jS49mzG;BvLd}H%11Ntf`c6( zN}?nQ(agW-`r5BEJS-b&>U6?s;NG&bj-jl>A#LPNZ*Qpoxgvl^gGK})Q;^U3qUHPN0PltE$oj(=uQ^$`MMLQA=24d~4H^F7dIHz1&u>Qx zoB5=~u`_%jORbg)ntTA~K|;WFnQa#CZQ#>^7s%s*iuE|v!|)cl^+S43?(Z!vRU>5* z=4R%;8X1Pwv6yVn$4%_E>>pV7_qQ=N*z9|x!WO!XlXG$egcGw213lFy3H{=)y(K$*=dTOHDY!_g6+m;`c+rJRPJC4Ou-vr_{z_8H zUOL-|nW_Ot*}`~MmaBlxeg4O}!dnY|f*RRMADPL=tHdVG% zz@(1Z!#)cc5gltKqQS6Fj}UH-c;*t-vB z+P4 zSO5k3=iH?KpWpxAF(PkO-jv5wu}JwXXgb0+HvrO?1yRxttgUcZogG|V{u{;0%gjSS zNdvm`my3K23Ul%|z=xN?1Vf1en)2VzFQv0kx)Xq;WwMVppxZM6-Tuo(k;na$gTFKb z(0Tr|$^SnNtd4}7`n1T6h%%0+SpY!o-?J%?T@R%3*B9V$RBc2%Duk@yn*dZfXtJ~N zbDk8+J1xZBCPU*O{^smixzwZhmNZfnSsHIO&xm<~JzUg^F|ZpZDwIv3ETcRb#X_!~ z+KIe9b7Ltu?)}rED~%1H64UOV;e2UE9|S=fQj0%th26&J>;9OLjue>qjiPF0TFAAw z61MWWTD-9PZU2|(Le?W?f<5#Cw)+bR*^Xv!g`HFx%*H!eG*?zB((~z4zu*m?q-+TL zB1(02Ag~q>M}Ld(U)0BOtK-wKQpzy3IT-$qtBRBej^`LL$KXIj2QU&F8E2Io@{)wMRQ9P`x&MO)bYGwW6U*)t%9PQolXYhRI4z& zsOT4PD2k;P{u;zi2Ct1ewXonHEO4WkbhEE3PxIbemt~rp{Sn2a#VjM7e)c+*inZ~i zpWdboR+@a~JT`kFvkNk{*bZ<<(JDZg@XH%tOlRN94Hm4S>~(0yo-~Gu!en3`8D?26 zv)xxYgvj>fZg6czEkVc!V4K37SWRlVh&_y~aYCHMN8D_V`xte9R2tYF?cQg5z4M_Y z@-$EE%ZXJopqWlelG0nap;CAmPXeEh(Qd0Tgn{_PyL{b}@$;K?w)$-qHDhGj!>7Ww zGIHvLOCcY7<~7s4UNyU~rh_;9je>d{pN7l-(!z$*YA4x_1JLZwK($7!@aMOcHBQV^ z)7*tpOK;go$gUET6Krj`1fbFl!23e2j!PfxghY@}V>3JGoV7G?UByNAvW}yxhpGOP z>!ud(58<43jXQIXa&Pl!$X@B{(&8AD@dbM8hRqM!Br-b?q@bekFWIeg3ZHPJK zMac;eGi@h#s)+iqIO|xW`@O$WTnY~R_Gk~lM4e0+l6OUNe*w4>p~BcjW41Y#?+U5_ zaO-=sU4bLQF;l-PwO@hpXl z-9ufMKCLmAk`H4~^`w*=FiX}ZiP}$#FIaqGx_t`q7%~4IQcDf1%-{6JA<%cpGQ;RG z6+`Pra0FDTo_jxc+>lEi@koYH?34BBg^ehatn>N@P>0_)Xr0lF-4N=GilPHwlFH5J z!OJP{G;b4%@_GE@83HC2U@zyWaWr4R%tSr7Swn&a_86(W*5_KqF}}R^*kGhmxyQil zOtvehXdL7WR17Dalllm|-~KX{&5A>GTbu{Cby{J+{G}QI7-+kQ{ptB*Z0Q8@p4tp~ zqha>DSB^kd?{(AD?vW;^50iO)*Y1~&F|v)%fUq zZBOcJV38Zd+6ge|!k!);hlUyQ(C>5)8Fw8{=mq#I>}C4d*@2C&<(xGAslo}y^JO0i z%0A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≪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 B$xi?P literal 0 HcmV?d00001 diff --git a/docs/images/Grafana_statistics.jpg b/docs/images/Grafana_statistics.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fec03c723f59f06e9d6fea9e4f7563ec3fce17c3 GIT binary patch literal 202272 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

*sMgm4!$ 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" http://localhost:8081/fledge/ping + +Alternatively a certificate based authentication can be used with the user presenting a certificate instead of the JSON payload shown above to the ``/fledge/login`` endpoint. + +.. code-block:: console + + curl -T user.cert -X POST http://localhost:8081/fledge/login --insecure + +The payload returned is the same as for username and password based authentication. + +.. note:: + + The examples above have been shown using HTTP as the transport, however if authentication is in use then it would normally be expected to use HTTPS to encrypt the communication. + +Logout +------ + +``PUT /fledge/logout`` - Terminate the current login session and invalidate the authentication token + +Ends to login session for the current user and invalidates the token given in the header. + +``PUT /fledge/{user_id}/logout`` - Terminate the login session for user's all active sessions. + +The administrator may terminate the login session of another user. + +.. code-block:: console + + curl -H "authorization: " -X PUT http://localhost:8081/fledge/{user_id}/logout + +Users +===== + +Fledge supports two levels of user, administration users and normal users. A set of API calls exists to allow users to be created, queried, modified and destroyed. + +Add User +-------- + +``POST /fledge/admin/user`` - add a new user to Fledge’s user database + +.. note:: + + Only admin users are able to create other users. + + +**Request Payload** + +A JSON document which describes the user to add. + +.. list-table:: + :widths: 20 20 50 30 + :header-rows: 1 + + * - Key Name + - Type + - Description + - Example + * - username + - string + - The username of the new user to add. It is a required field. + - david + * - password + - string + - The password to assign to the new user. It is a required field. + - Inv1nc!ble + * - access_method + - string + - Access of a user. It is an optional field. + - Possible values are cert, any, cert. + * - real_name + - string + - The real name of the user. This is used for display purposes only. It is an optional field. + - David Brent + * - role_id + - integer + - The role id of the new user. It is an optional field. + - 1 for Admin user and 2 for normal user. If not given it will be treated as normal user. + * - description + - string + - Description of the user. It is an optional field. + - 1 for Admin and 2 for normal user. If not given it will be treated as normal user. + + +**Response Payload** + +The response payload is a JSON document containing the full details of the newly created user. + +**Errors** + +The following error responses may be returned + +.. list-table:: + :widths: 20 50 + :header-rows: 1 + + * - HTTP Code + - Reason + * - 400 + - Incomplete or badly formed request payload + * - 403 + - A user without admin permissions tried to add a new user + * - 409 + - The username is already in use + + +**Example** + +.. code-block:: console + + curl -H "authorization: " -X POST -d '{"username": "david", "password": "Inv1nc!ble", "role_id": 1, "real_name": "David Brent"}' http://localhost:8081/fledge/admin/user + + +Get All Users +------------- + +``GET /fledge/user`` - Retrieve data on all users + +**Response Payload** + +A JSON document which all users in a JSON array. + +.. list-table:: + :widths: 20 20 50 30 + :header-rows: 1 + + * - JSON Key + - Type + - Description + - Example + * - .users[].userName + - string + - The username of the user + - david + * - .users[].roleId + - integer + - The permissions level of the user + - 1 + * - .users[].realName + - string + - The real name of the user. This is used for display purposes only. + - David Brent + * - .users[].description + - string + - The description of the user. + - This is an admin user. + +.. note:: + + This payload does not include the password of the user. + +**Example** + +.. code-block:: console + + curl -H "authorization: " -X GET http://localhost:8081/fledge/user + + +Returns the response payload + +.. code-block:: json + + { + "users" : [ + { + "userId" : 1, + "userName" : "admin", + "roleId" : 1, + "accessMethod" : "any", + "realName" : "Admin user", + "description" : "admin user" + }, + { + "userId" : 2, + "userName" : "david", + "realName" : "David Brent", + "accessMethod" : "any", + "roleId" : 1, + "description" : "OT Department Head" + }, + { + "userId" : 3, + "userName" : "paul", + "realName" : "Paul Smith" + "roleId" : 2, + "accessMethod" : "any", + "description" : "OT Supervisor" + } + ] + } + +Update User +----------- + +``PUT /fledge/user`` - Allows a user to update their own user information + +**Request Payload** + +A JSON document which describes the updates to the user record. + +.. list-table:: + :widths: 20 20 50 30 + :header-rows: 1 + + * - Key Name + - string + - description + - Example + * - real_name + - string + - The real name of the user. This is used for display purposes only. + - David Brent + + +.. note:: + + A user can only update their own real name, other information must be updated by an admin user. + +**Response Payload** + +The response payload is a JSON document containing a message as to the success of the operation. + +**Errors** + +The following error responses may be returned + +.. list-table:: + :widths: 20 50 + :header-rows: 1 + + * - HTTP Code + - Reason + * - 400 + - Incomplete or badly formed request payload + +**Example** + +.. code-block:: console + + curl -H "authorization: " -X PUT /fledge/user -d '{"real_name": "Dave Brent"}' + +Change Password +--------------- + +``PUT /fledge/user/{userid}/password`` - change the password for the current user + +**Request Payload** + +A JSON document that contains the old and new passwords. + +.. list-table:: + :widths: 20 20 50 30 + :header-rows: 1 + + * - Key Name + - string + - description + - Example + * - current_password + - string + - The current password of the user + - Inv1nc!ble + * - new_password + - string + - The new password of the user + - F0gl!mp1 + +**Response Payload** + +A message as to the success of the operation + +**Example** + +.. code-block:: console + + curl -X PUT -d '{"current_password": "Inv1nc!ble", "new_password": "F0gl!mp1"}' http://localhost:8081/fledge/user/{user_id}/password + +Admin Update User +----------------- + +``PUT /fledge/admin/user`` - An admin user can update any user's information + +**Request Payload** + +A JSON document which describes the updates to the user record. + +.. list-table:: + :widths: 20 20 50 30 + :header-rows: 1 + + * - Name + - Type + - Description + - Example + * - description + - string + - The description of a user + - david + * - access_method + - string + - The permissions that new user should be given + - Possible values are cert, any, cert. + * - real_name + - string + - The real name of the user. This is used for display purposes only. + - David Brent + +**Response Payload** + +The response payload is a JSON document containing the user information. + +**Errors** + +The following error responses may be returned + +.. list-table:: + :widths: 20 50 + :header-rows: 1 + + * - HTTP Code + - Reason + * - 400 + - Incomplete or badly formed request payload + * - 403 + - A user without admin permissions tried to add a new user + * - 409 + - The username is already in use + +**Example** + +.. code-block:: console + + curl -H "authorization: " -X PUT -d '{"description": "OT Department Head", "real_name": "David Brent", "access_method": "pwd"}' http://localhost:8081/fledge/admin/{user_id} + +Delete User +----------- + +``DELETE /fledge/admin/user/{userID}/delete`` - delete a user + +.. note:: + + - It is not possible to remove the user that is currently logged in to the system. + - Only Admin can delete the user. + - Super Admin cannot be deleted. + +**Example** + +.. code-block:: console + + curl -H "authorization: " -X DELETE http://localhost:8081/fledge/admin/{user_id}/delete diff --git a/docs/rest_api_guide/02_RESTadmin.rst b/docs/rest_api_guide/03_RESTadmin.rst similarity index 92% rename from docs/rest_api_guide/02_RESTadmin.rst rename to docs/rest_api_guide/03_RESTadmin.rst index 890d19a3ee..0f04327f1b 100644 --- a/docs/rest_api_guide/02_RESTadmin.rst +++ b/docs/rest_api_guide/03_RESTadmin.rst @@ -36,6 +36,73 @@ audit The *audit* methods implement the audit trail, they are used to create and retrieve audit logs. +The set of possible audit sources are + ++--------+-------------------------------+ +| Source | Description | ++========+===============================+ +| PURGE | Data Purging Process | ++--------+-------------------------------+ +| LOGGN | Logging Process | ++--------+-------------------------------+ +| STRMN | Streaming Process | ++--------+-------------------------------+ +| SYPRG | System Purge | ++--------+-------------------------------+ +| START | System Startup | ++--------+-------------------------------+ +| FSTOP | System Shutdown | ++--------+-------------------------------+ +| CONCH | Configuration Change | ++--------+-------------------------------+ +| CONAD | Configuration Addition | ++--------+-------------------------------+ +| SCHCH | Schedule Change | ++--------+-------------------------------+ +| SCHAD | Schedule Addition | ++--------+-------------------------------+ +| SRVRG | Service Registered | ++--------+-------------------------------+ +| SRVUN | Service Unregistered | ++--------+-------------------------------+ +| SRVFL | Service Fail | ++--------+-------------------------------+ +| NHCOM | North Process Complete | ++--------+-------------------------------+ +| NHDWN | North Destination Unavailable | ++--------+-------------------------------+ +| NHAVL | North Destination Available | ++--------+-------------------------------+ +| UPEXC | Update Complete | ++--------+-------------------------------+ +| BKEXC | Backup Complete | ++--------+-------------------------------+ +| NTFDL | Notification Deleted | ++--------+-------------------------------+ +| NTFAD | Notification Added | ++--------+-------------------------------+ +| NTFSN | Notification Sent | ++--------+-------------------------------+ +| NTFCL | Notification Cleared | ++--------+-------------------------------+ +| NTFST | Notification Server Startup | ++--------+-------------------------------+ +| NTFSD | Notification Server Shutdown | ++--------+-------------------------------+ +| PKGIN | Package installation | ++--------+-------------------------------+ +| PKGUP | Package updated | ++--------+-------------------------------+ +| PKGRM | Package purged | ++--------+-------------------------------+ +| DSPST | Dispatcher Startup | ++--------+-------------------------------+ +| DSPSD | Dispatcher Shutdown | ++--------+-------------------------------+ +| ESSRT | External Service Startup | ++--------+-------------------------------+ +| ESSTP | External Service Shutdown | ++--------+-------------------------------+ GET Audit Entries ~~~~~~~~~~~~~~~~~ @@ -1043,6 +1110,31 @@ The response payload is a JSON object with the details of the cancelled task. Other Administrative API calls ============================== +shutdown +-------- + +The *shutdown* option will causes all fledge services to be shutdown cleanly. Any data held in memory buffers within the services will be sent to the storage layer and the Fledge plugins will persist any state required when they restart. + +.. code-block:: console + + $ curl -X PUT /fledge/shutdown + +.. note:: + + If an in memory storage layer is configured this will **not** be stored to any permanent storage and the contents of the memory storage layer will be lost. + +restart +------- + +The *restart* option will causes all fledge services to be shutdown cleanly and then restarted. Any data held in memory buffers within the services will be sent to the storage layer and the Fledge plugins will persist any state required when they restart. + +.. code-block:: console + + $ curl -X PUT /fledge/restart + +.. note:: + + If an in memory storage layer is configured this will **not** be stored to any permanent storage and the contents of the memory storage layer will be lost. ping ---- @@ -1134,134 +1226,3 @@ The response payload is some basic health information in a JSON object. } $ - -statistics ----------- - -The *statistics* interface allows the retrieval of live statistics and statistical history for the Fledge device. - - -GET statistics -~~~~~~~~~~~~~~ - -``GET /fledge/statistics`` - return a general set of statistics - - -**Response Payload** - -The response payload is a JSON document with statistical information (all numerical), these statistics are absolute counts since Fledge started. - -.. list-table:: - :widths: 20 50 - :header-rows: 1 - - * - Key - - Description - * - BUFFERED - - Readings currently in the Fledge buffer - * - DISCARDED - - Readings discarded by the South Service before being placed in the buffer. This may be due to an error in the readings themselves. - * - PURGED - - Readings removed from the buffer by the purge process - * - READINGS - - Readings received by Fledge - * - UNSENT - - Readings filtered out in the send process - * - UNSNPURGED - - Readings that were purged from the buffer before being sent - - -**Example** - -.. code-block:: console - - $ curl -s http://localhost:8081/fledge/statistics - [ { - "key": "BUFFERED", - "description": "Readings currently in the Fledge buffer", - "value": 0 - }, - ... - { - "key": "UNSNPURGED", - "description": "Readings that were purged from the buffer before being sent", - "value": 0 - }, - ... ] - $ - - -GET statistics/history -~~~~~~~~~~~~~~~~~~~~~~ - -``GET /fledge/statistics/history`` - return a historical set of statistics. This interface is normally used to check if a set of sensors or devices are sending data to Fledge, by comparing the recent statistics and the number of readings received for an asset. - - -**Request Parameters** - -- **limit** - limit the result set to the *N* most recent entries. - - -**Response Payload** - -A JSON document containing an array of statistical information, these statistics are delta counts since the previous entry in the array. The time interval between values is a constant defined that runs the gathering process which populates the history statistics in the storage layer. - -.. list-table:: - :widths: 20 50 - :header-rows: 1 - - * - Key - - Description - * - interval - - The interval in seconds between successive statistics values - * - statistics[].BUFFERED - - Readings currently in the Fledge buffer - * - statistics[].DISCARDED - - Readings discarded by the South Service before being placed in the buffer. This may be due to an error in the readings themselves. - * - statistics[].PURGED - - Readings removed from the buffer by the purge process - * - statistics[].READINGS - - Readings received by Fledge - * - statistics[].*NORTH_TASK_NAME* - - The number of readings sent to the PI system via the OMF plugin with north instance name - * - statistics[].UNSENT - - Readings filtered out in the send process - * - statistics[].UNSNPURGED - - Readings that were purged from the buffer before being sent - * - statistics[].*ASSET-CODE* - - The number of readings received by Fledge since startup with name *asset-code* - - -**Example** - -.. code-block:: console - - $ curl -s http://localhost:8081/fledge/statistics/history?limit=2 - { - "interval": 15, - "statistics": [ - { - "history_ts": "2020-06-01 11:21:04.357", - "READINGS": 0, - "BUFFERED": 0, - "UNSENT": 0, - "PURGED": 0, - "UNSNPURGED": 0, - "DISCARDED": 0, - "Readings Sent": 0 - }, - { - "history_ts": "2020-06-01 11:20:48.740", - "READINGS": 0, - "BUFFERED": 0, - "UNSENT": 0, - "PURGED": 0, - "UNSNPURGED": 0, - "DISCARDED": 0, - "Readings Sent": 0 - } - ] - } - $ - - diff --git a/docs/rest_api_guide/03_RESTassetTracker.rst b/docs/rest_api_guide/03_RESTassetTracker.rst new file mode 100644 index 0000000000..6649593169 --- /dev/null +++ b/docs/rest_api_guide/03_RESTassetTracker.rst @@ -0,0 +1,129 @@ +.. + +Asset Tacker +------------ + +The *asset tracker* API allows the operations that an asset undergoes whilst traversing the data pipeline within Fledge to be tracked as displayed. + +``GET /fledge/track`` - return tracking data for one or more asset + +**Parameters** + + - ``asset`` - define the asset to be tracked. If omitted tracking data for all assets is returned + + - ``event`` - the event to track. If omitted all events will be returned + + - ``service`` - limit the tracking data to a particular service + +**Response Payload** + +An array of tracked events, each of which contains the following + +.. list-table:: + :widths: 20 20 50 50 + :header-rows: 1 + + * - Name + - Type + - Description + - Example + * - asset + - string + - The name of the asset for which this track event relates + - sinusoid + * - event + - string + - The event that was tracked, this will be one of Ingest, Filter or Egress + - Ingest + * - service + - string + - The name of the service this event was tracked in + - testSignal4 + * - fledge + - string + - The name of the fledge instance this event was tracked in + - fledge002 + * - plugin + - string + - The name of the plugin this event was tracked in + - sinusoid + * - timestamp + - string + - The timestamp when this event was first tracked + - 2022-07-06 10:20:13.059 + * - deprecatedTimestamp + - string + - The timestamp when this event was deprecated + - 2022-07-06 10:20:13.059 + +.. note:: + + Asset tracking deprecation allows for old information regarding the plugin that ingested an asset to be hidden when that asset is no longer ingested by the plugin. When this is done the deprecatedTimestamp value is set to be a non-empty timestamp. + +**Example** + +Return the asset tracking data for the asset called *sinusoid* + +.. code-block:: console + + curl http://localhost:8081/fledge/track?asset=sinusoid + +Returns + +.. code-block:: console + + { + "track": [ + { + "asset": "sinusoid", + "event": "Filter", + "service": "test1", + "fledge": "Fledge", + "plugin": "test2", + "timestamp": "2022-07-06 10:20:13.059" + }, + { + "asset": "sinusoid", + "event": "Ingest", + "service": "test1", + "fledge": "Fledge", + "plugin": "sinusoid", + "timestamp": "2022-07-11 16:12:25.749" + }, + { + "asset": "sinusoid", + "event": "Filter", + "service": "test1", + "fledge": "Fledge", + "plugin": "python35", + "timestamp": "2022-07-13 12:33:10.082" + }, + { + "asset": "sinusoid", + "event": "Egress", + "service": "OMF", + "fledge": "Fledge", + "plugin": "OMF", + "timestamp": "2022-07-15 14:07:14.950" + } + ] + } + +Deprecation +~~~~~~~~~~~ + +There are some circumstances in which old data regarding asset tracking needs to be removed. In particular when a plugin ingests multiple assets or asset names have changed, it is convenient for the user to remove the association with the old asset names. + +``PUT /fledge/track/service/service_name/asset/asset_name/event/event_name`` - mark the asset tracking event as deprecated + +**Parameters** + + - ``service_name`` - the name of the service for which we want to deprecate the asset tracking event + + - ``asset_name`` - the name of the asset that we should deprecate + + - ``event_name`` - the name of the event to deprecate + +.. note:: + + There is no API to remove the deprecation of an asset tracking event, this is done automatically when assets are tracked in future events. diff --git a/docs/rest_api_guide/03_RESTservices.rst b/docs/rest_api_guide/03_RESTservices.rst new file mode 100644 index 0000000000..57888f5e34 --- /dev/null +++ b/docs/rest_api_guide/03_RESTservices.rst @@ -0,0 +1,398 @@ +.. + +Working With Services +===================== + +There are a number of API entries points related to working with services within Fledge. + +Service Status +-------------- + +In order to discover the services registered within a Fledge instance and what state they are currently in the API call */fledge/service* can be used. This is a GET call and will return the set of services along with various information regarding the service. A registered service is one that is either currently running or is configured but disabled. + +.. code-block:: console + + $ curl http://localhost:8081/fledge/service | jq + { + "services": [ + { + "name": "Fledge Storage", + "type": "Storage", + "address": "localhost", + "management_port": 39773, + "service_port": 46391, + "protocol": "http", + "status": "running" + }, + { + "name": "Fledge Core", + "type": "Core", + "address": "0.0.0.0", + "management_port": 41547, + "service_port": 8081, + "protocol": "http", + "status": "running" + }, + { + "name": "Notification", + "type": "Notification", + "address": "localhost", + "management_port": 40605, + "service_port": 40779, + "protocol": "http", + "status": "shutdown" + }, + { + "name": "dispatcher", + "type": "Dispatcher", + "address": "localhost", + "management_port": 46353, + "service_port": 35605, + "protocol": "http", + "status": "shutdown" + }, + { + "name": "lathe1004", + "type": "Southbound", + "address": "localhost", + "management_port": 45113, + "service_port": 34403, + "protocol": "http", + "status": "running" + }, + { + "name": "OPCUA", + "type": "Northbound", + "address": "localhost", + "management_port": 42783, + "service_port": null, + "protocol": "http", + "status": "shutdown" + }, + { + "name": "sine2", + "type": "Southbound", + "address": "localhost", + "management_port": 38679, + "service_port": 33433, + "protocol": "http", + "status": "running" + } + ] + } + +The data returned for each service includes + ++-----------------+-----------------------------------------------------------------------------+ +| Key | Description | ++=================+=============================================================================+ +| name | The name of the service | ++-----------------+-----------------------------------------------------------------------------+ +| type | The service type. This may be one of Northbound, Southbound, Core, Storage, | +| | Notification or Dispatcher. In addition other storage types may also be | +| | installed to extend the functionality of Fledge. | ++-----------------+-----------------------------------------------------------------------------+ +| address | The Address the service can be contacted via. Normally localhost or 0.0.0.0 | +| | if the service is running on the same machine as the Core service of the | +| | Fledge instance. | ++-----------------+-----------------------------------------------------------------------------+ +| management_port | The management port the service is using to communicate with the core. | ++-----------------+-----------------------------------------------------------------------------+ +| service_port | The port the service is using to expose the service API of the service. | ++-----------------+-----------------------------------------------------------------------------+ +| protocol | The protocol the service is using for its control API. | ++-----------------+-----------------------------------------------------------------------------+ +| status | The status of the service. This may be running, shutdown, unresponsive or | +| | failed. | ++-----------------+-----------------------------------------------------------------------------+ + +Parameters +~~~~~~~~~~ + +You may limit the services returned by this call to a particular type by using the *type=* parameter to the URL. + +.. code-block:: console + + $ curl -sX GET http://localhost:8081/fledge/service?type=Southbound | jq + { + "services": [ + { + "name": "lathe1004", + "type": "Southbound", + "address": "localhost", + "management_port": 45113, + "service_port": 34403, + "protocol": "http", + "status": "running" + }, + { + "name": "sine2", + "type": "Southbound", + "address": "localhost", + "management_port": 38679, + "service_port": 33433, + "protocol": "http", + "status": "running" + } + ] + } + +South and North Services +~~~~~~~~~~~~~~~~~~~~~~~~ + +Specific API calls exist for the two must commonly used service types, the south and north services. These give additional information and are primarily used to give the status of all south or north services in the system. + +.. note:: + + In the case of the north API entry point the information returned is for both services and tasks + +South Services +~~~~~~~~~~~~~~ + +The */fledge/south* call will list all of the south service with the information above and will also list + + - the assets that are ingested by the service, + + - a count for each asset of how many readings have been ingested, this is only applicable if the plugin ingests multiple assets + + - the name and version of the south plugin used + + - and the current enabled state of the south service. + +.. code-block:: console + + $ curl -s http://localhost:8081/fledge/south |jq + { + "services": [ + { + "name": "lathe1004", + "address": "localhost", + "management_port": 45113, + "service_port": 34403, + "protocol": "http", + "status": "running", + "assets": [ + { + "count": 520774, + "asset": "lathe1004" + }, + { + "count": 520774, + "asset": "lathe1004Current" + }, + { + "count": 520239, + "asset": "lathe1004IR" + }, + { + "count": 260379, + "asset": "lathe1004Vibration" + } + ], + "plugin": { + "name": "lathesim", + "version": "1.9.2" + }, + "schedule_enabled": true + }, + { + "name": "sine2", + "address": "localhost", + "management_port": 38679, + "service_port": 33433, + "protocol": "http", + "status": "running", + "assets": [ + { + "count": 734, + "asset": "sine2" + }, + { + "count": 373008, + "asset": "sine250" + } + ], + "plugin": { + "name": "sinusoid", + "version": "1.9.2" + }, + "schedule_enabled": true + }, + { + "name": "test1", + "address": "", + "management_port": "", + "service_port": "", + "protocol": "", + "status": "", + "assets": [ + { + "count": 76892, + "asset": "sinusoid" + }, + { + "count": 125681, + "asset": "sinusoid2" + } + ], + "plugin": { + "name": "sinusoid", + "version": "1.9.2" + }, + "schedule_enabled": false + }, + { + "name": "testacl", + "address": "", + "management_port": "", + "service_port": "", + "protocol": "", + "status": "", + "assets": [ + { + "count": 76892, + "asset": "sinusoid" + } + ], + "plugin": { + "name": "testing", + "version": "1.9.2" + }, + "schedule_enabled": false + }, + { + "name": "dsds", + "address": "", + "management_port": "", + "service_port": "", + "protocol": "", + "status": "", + "assets": [], + "plugin": { + "name": "Expression", + "version": "1.9.2" + }, + "schedule_enabled": false + } + ] + } + $ + +Service Types +------------- + +Fledge supports a number of different service types, some of which are included with the base Fledge installation and others that must be installed separately if required. + +.. note:: + + The API entry points in this section require that the Fledge installation has been configured with access to a Fledge package repository. + +Installed Service Types +~~~~~~~~~~~~~~~~~~~~~~~ + +In order to find out what service types are installed in the system the */fledge/service/installed* call can be used. + +.. code-block:: console + + $ curl http://localhost:8081/fledge/service/installed + {"services": ["storage", "north", "dispatcher", "notification", "south"]} + +.. note:: + + All Fledge instances have the storage, south and north services installed by default when the Fledge core is installed. + +Available Service Types +~~~~~~~~~~~~~~~~~~~~~~~ + +To find out what services are available to be installed from the package repository configured for your Fledge instance use the API */fledge/service/available*. + +.. code-block:: console + + $ curl -q http://localhost:8081/fledge/service/available |jq + { + "services": [ + "fledge-service-notification" + ], + "link": "logs/220831-13-26-25-list.log" + } + +The *link* in the returned JSON is a link to a log file that shows the interaction with the package repository. + +Install a Service Type +~~~~~~~~~~~~~~~~~~~~~~ + +To install a new service type the POST method can be used on the */fledge/service* API call with the parameter *action=install*. + +.. code-block:: console + + $ curl -X POST http://localhost:8081/fledge/service?action=install -d'{"format":"repository", "name": "fledge-service-notification"}' + +This will install the named service from the package repository. + +.. note:: + + In order to install a package the package repository must be configured and accessible. + +Creating A Service +------------------ + +A new service can be created using the POST method on the */fledge/service* API call. The payload passed to this request will determine at least the service type and the name of the new service, however it may also contain further configuration which is dependent on the type of the service. + +The minimum payload content that must be in every create call for a service is the name of the new service, the type of the service and the enabled state of the service. This can be used for example to create a notification service or a control dispatcher service that need no further configuration. + +.. code-block:: console + + $ curl -X POST http://localhost:8081/fledge/service -d'{ "name" : "Notifier", "type" : "notification", "enabled" : "true" }' + +Or for a control dispatcher + +.. code-block:: console + + $ curl -X POST http://localhost:8081/fledge/service -d'{ "name" : "Control", "type" : "dispatcher", "enabled" : "true" }' + +A north or south service need some extra configuration in the payload. These service type must always have a plugin and can optionally be passed configuration for that plugin. If no plugin configuration is given then the plugins default configuration values will be used. + +To create a south service using the default values of the *sinusoid* plugin. + +.. code-block:: console + + $ curl -X POST http://localhost:8081/fledge/service -d'{ "name" : "Sine", "type" : "south", "enabled" : "true", "plugin" : "sinusoid" }' + +In the next example we create a north plugin that will send data to another Fledge instance using the *HTTPC* plugin. We set the value of the configuration item *URL* in the plugin to be the URL of the concentrator Fledge instance. + +.. code-block:: console + + $ curl -sX POST http://localhost:8081/fledge/service -d '{"name": "HTTP", "plugin": "httpc", "type": "north", "enabled": true, "config": {"URL": {"value": "http://concentrator.local:6683/buildingA"}}}' + +Stopping and Starting Services +------------------------------ + +Services within Fledge are started and stop via the scheduler, normally a service will be started via a schedule that defines the service to run at startup of Fledge. This ensures that the service runs when Fledge is started and will continue to run until Fledge is stopped. To implicitly stop a service the schedule must be disabled. + +Disabling a schedule associated for a service will also stop the service. The service will not then be restarted, even if Fledge is restarted, until the schedule is again enabled. + +To disable a schedule you can call the */fledge/schedule/{schedule_id}/disable* API call, however this requires you to know the ID of the schedule associated with the service. It is possible to find this for a given service, as the schedule name is the same as the service name, however it is simpler to use the API call */fledge/schedule/disable* as this can be passed the name of the schedule rather than the schedule ID. Since the schedule name and the service name are the same, we effectively pass the name of the service we wish to disable. + +To disable the service call *Sine* we would use the following *curl* command. + +.. code-block:: console + + $ curl -X PUT http://localhost:8081/fledge/schedule/disable -d '{"schedule_name": "Sine"}' + +To enable the service again we can use the */fledge/schedule/enable* API call, this takes an identical payload to the disable API call. + +.. code-block:: console + + $ curl -X PUT http://localhost:8081/fledge/schedule/enable -d '{"schedule_name": "Sine"}' + +Deleting a Service +------------------ + +Services may be deleted from the system using the */fledge/service* API call with the DELETE method. When a service is deleted it will be stopped and the service, configuration for the service and the associated schedule will be removed. Any data that has been read by the service will however remain in the readings database. + +To delete the service named *Sine* + +.. code-block:: console + + $ curl -X DELETE http://localhost:8081/fledge/service/Sine + diff --git a/docs/rest_api_guide/03_RESTstatistics.rst b/docs/rest_api_guide/03_RESTstatistics.rst new file mode 100644 index 0000000000..c8117a92bb --- /dev/null +++ b/docs/rest_api_guide/03_RESTstatistics.rst @@ -0,0 +1,177 @@ + +Statistics +---------- + +The *statistics* interface allows the retrieval of live statistics, statistical history and statistical rates for the Fledge device. + +Fledge records a number of statistics values, some with fixed names and other that reflect the name of a service or an asset. The statistics counters with fixed names are given below. + +.. list-table:: + :widths: 20 50 + :header-rows: 1 + + * - Key + - Description + * - BUFFERED + - Readings currently in the Fledge buffer + * - DISCARDED + - Readings discarded by the South Service before being placed in the buffer. This may be due to an error in the readings themselves. + * - PURGED + - Readings removed from the buffer by the purge process + * - READINGS + - Readings received by Fledge + * - UNSENT + - Readings filtered out in the send process + * - UNSNPURGED + - Readings that were purged from the buffer before being sent + +In addition to these fixed names there will be; + + - One statistic per north service or task that is named the same as the service or task name. This will count the number of readings sent out on that service. + + - One statistic per asset that is named the same as the asset. This will be the number of readings that have been ingested for that asset. + + - One statistics per south service, that is named with the service name and *-Ingest* appended. This is the count of readings read in for that service. + +GET statistics +~~~~~~~~~~~~~~ + +``GET /fledge/statistics`` - return a general set of statistics + + +**Response Payload** + +The response payload is a JSON document with statistical information (all numerical), these statistics are absolute counts since Fledge started. + + +**Example** + +.. code-block:: console + + $ curl -s http://localhost:8081/fledge/statistics + [ { + "key": "BUFFERED", + "description": "Readings currently in the Fledge buffer", + "value": 0 + }, + ... + { + "key": "UNSNPURGED", + "description": "Readings that were purged from the buffer before being sent", + "value": 0 + }, + ... ] + $ + + +GET statistics/history +~~~~~~~~~~~~~~~~~~~~~~ + +``GET /fledge/statistics/history`` - return a historical set of statistics. This interface is normally used to check if a set of sensors or devices are sending data to Fledge, by comparing the recent statistics and the number of readings received for an asset. + + +**Request Parameters** + +- **limit** - limit the result set to the *N* most recent entries. + + +**Response Payload** + +A JSON document containing an array of statistical information, these statistics are delta counts since the previous entry in the array. The time interval between values is a constant defined that runs the gathering process which populates the history statistics in the storage layer. + +.. list-table:: + :widths: 20 50 + :header-rows: 1 + + * - Key + - Description + * - interval + - The interval in seconds between successive statistics values + * - statistics[].BUFFERED + - Readings currently in the Fledge buffer + * - statistics[].DISCARDED + - Readings discarded by the South Service before being placed in the buffer. This may be due to an error in the readings themselves. + * - statistics[].PURGED + - Readings removed from the buffer by the purge process + * - statistics[].READINGS + - Readings received by Fledge + * - statistics[].*NORTH_TASK_NAME* + - The number of readings sent to the upstream system by the plugin with the north instance name + * - statistics[].UNSENT + - Readings filtered out in the send process + * - statistics[].UNSNPURGED + - Readings that were purged from the buffer before being sent + * - statistics[].*ASSET-CODE* + - The number of readings received by Fledge since startup with name *asset-code* + + +**Example** + +.. code-block:: console + + $ curl -s http://localhost:8081/fledge/statistics/history?limit=2 + { + "interval": 15, + "statistics": [ + { + "history_ts": "2020-06-01 11:21:04.357", + "READINGS": 0, + "BUFFERED": 0, + "UNSENT": 0, + "PURGED": 0, + "UNSNPURGED": 0, + "DISCARDED": 0, + "Readings Sent": 0 + }, + { + "history_ts": "2020-06-01 11:20:48.740", + "READINGS": 0, + "BUFFERED": 0, + "UNSENT": 0, + "PURGED": 0, + "UNSNPURGED": 0, + "DISCARDED": 0, + "Readings Sent": 0 + } + ] + } + $ + + +GET statistics/rate +~~~~~~~~~~~~~~~~~~~ + +``GET /fledge/statistics/rate`` - return a set of rates for a set of statistics. This interface returns the rate of a statistic value in counts per minute over a specified set of averages. It is passed two parameters, a comma separated list of intervals in minutes and a comma separated list of statistics. + +**Request Parameters** + + - **statistics** - a comma separated list of statistics values to return + + - **periods** - a comma separated list of time periods in minutes. The corresponding rate that will be returned for a given value X is the counts per minute over the previous X minutes. + +**Example** + +.. code-block:: console + + $ curl -sX GET http://localhost:8081/fledge/statistics/rate?statistics=READINGS,Readings%20Sent\&periods=1,5,15,30,60 + { + "rates": { + "READINGS": { + "1": 12.938816958618938, + "5": 12.938816958618938, + "15": 12.938816958618938, + "30": 12.938816958618938, + "60": 12.938816958618938 + }, + "Readings Sent": { + "1": 0, + "5": 0, + "15": 0, + "30": 0, + "60": 0 + } + } + } + $ + + diff --git a/docs/rest_api_guide/03_RESTupdate.rst b/docs/rest_api_guide/03_RESTupdate.rst new file mode 100644 index 0000000000..cc6fd2e6e2 --- /dev/null +++ b/docs/rest_api_guide/03_RESTupdate.rst @@ -0,0 +1,42 @@ +.. + + +Repository Configuration +------------------------ + +``POST /fledge/repository`` - Configure the package repository to use for the Fledge packages. + +**Payload** + +The payload is a JSON document that can have one or two keys defined in +the JSON object, *url* and *version*. The *url* item is mandatory and +gives the URL of the package repository. This is normally set to the +fledge-iot archives for the fledge packages. + +.. code-block:: console + + { + "url":"http://archives.fledge-iot.org", + "version":"latest" + } + + +Update Packages +--------------- + +``PUT /fledge/update`` - Update all of the packages within the Fledge instance + +This call can be used if you have installed some or all of your Fledge +instance using packages via the package installation process or using +the package installer to add extra plugins. It will update all the Fledge +packages that you have installed to the latest version. + +**Example** + +.. code-block:: console + + $ curl -X PUT http://localhost:8081/fledge/update + +The call will return immediately and the package update will occur as a background task. + + diff --git a/docs/rest_api_guide/03_RESTuser.rst b/docs/rest_api_guide/04_RESTuser.rst similarity index 100% rename from docs/rest_api_guide/03_RESTuser.rst rename to docs/rest_api_guide/04_RESTuser.rst diff --git a/docs/rest_api_guide/05_RESTdeveloper.rst b/docs/rest_api_guide/05_RESTdeveloper.rst new file mode 100644 index 0000000000..fb21401847 --- /dev/null +++ b/docs/rest_api_guide/05_RESTdeveloper.rst @@ -0,0 +1,164 @@ +Developer API Calls +=================== + +A number of calls exist in the API that are targeted at those developing +pipelines and plugins for Fledge. These are not actions that are expected +to be of everyday use, but are to aid in this development process. + +Purge Readings +-------------- + +Under ordinary circumstances a user should never need to manually purge +data from the Fledge storage buffer, however during the development +process it can be useful to be able to manually purge data. + +``DELETE /fledge/asset`` - Purge data for all assets from the buffer + +**Response Payload** + +The response payload is a JSON document that returns the number of readings that have been deleted. + +**Example** + +.. code-block:: console + + $ curl -X DELETE http://localhost:8081/fledge/asset + +The return from this is the number of readings that have been purged. + +.. code-block:: JSON + + { "purged" : 3239 } + +.. note:: + + Great care should be exercised in using this call as **all** data that is currently buffered in the Fledge storage layer will be lost and there is no mechanism to undo this operation. + +``DELETE /fledge/asset/{asset name}`` - Purge data for the named asset from the buffer + +**Response Payload** + +The response payload is a JSON document that returns the number of readings that have been deleted. + +**Example** + +.. code-block:: console + + $ curl -X DELETE http://localhost:8081/fledge/asset/sinusoid + +The return from this is the number of readings that have been purged. + +.. code-block:: JSON + + { "purged" : 435 } + +.. note:: + + Great care should be exercised in using this call as **all** data for the **named** asset that is currently buffered in the Fledge storage layer will be lost and there is no mechanism to undo this operation. + +View Plugin Persisted Data +-------------------------- + +Fledge plugins may persist data between executions of the the plugin. This data takes the form of a JSON document. In normally circumstance the user should not need to view or manage this data as it is the responsibility of the plugin to manage this data. However, during the development of a plugin it is useful for a plugin developer to be able to view this data and manage the data. + +``GET /fledge/service/{service_name}/persist`` - get the names of the plugins that persist data within a service. + +.. code-block:: console + + curl http:/localhost:8081/fledge/service/OMF/persist + +This would return the list of plugins as a JSON document as shown below + +.. code-block:: JSON + + { + "persistent": [ + "OMF" + ] + } + +If no plugins within this service persist data the *persistent* array would be empty. + +``GET /fledge/service/{service_name}/plugin/{plugin_name}/data`` - view the plugin data persisted by an instance of a plugin + +**Parameters** + + - *service_name* - the name of the service in which the plugin is running + + - *plugin_name* - the name of the plugin within the service. For a north or south plugin this is the same as the service name. For a filter this will be the name given to the filter instance when it was added to the pipeline. + +**Response Payload** + +The response payload is the persisted data from the plugin. + +**Example** + +.. code-block:: console + + $ curl http://localhost:8081/fledge/service/OMF/plugin/OMF/data + +Where *OMF* is the name of a north service with an OMF filter connected to a PI Server. In this case the persisted data is the type information we cache locally that describes the types that have been created within the OMF layer of the PI Server. + +.. code-block:: console + + { + "data": { + "sentDataTypes": [ + { + "sine25": { + "type-id": 1, + "dataTypesShort": "0x101", + "hintChecksum": "0x0", + "namingScheme": 0, + "afhHash": "15489826335467873671", + "afHierarchy": "fledge/data_piwebapi/mark", + "afHierarchyOrig": "fledge/data_piwebapi/mark", + "dataTypes": { + "sinusoid": { + "type": "number", + "format": "float64" + } + } + } + }, + { + "sinusoid": { + "type-id": 1, + "dataTypesShort": "0x101", + "hintChecksum": "0x0", + "namingScheme": 0, + "afhHash": "15489826335467873671", + "afHierarchy": "fledge/data_piwebapi/mark", + "afHierarchyOrig": "fledge/data_piwebapi/mark", + "dataTypes": { + "sinusoid": { + "type": "number", + "format": "float64" + } + } + } + } + ] + } + } + +.. note:: + + Persisted data is written when the plugin is shutdown. Therefore in order to obtain accurate results this call should only be made when the service is shutdown. Calling this API when a service is running will result in data from the previous time the service was shutdown. + +``POST /fledge/service/{service_name}/plugin/{plugin_name}/data`` - write the persisted data for a plugin. Also send the data with payload ``{"data": ""}`` + +Write or overwrite data persisted by the plugin. The request payload is the data which the plugin should receive and must be in the correct format for the plugin. + +The payload for the POST command is defined by the plugin itself and hence no general example can be given here. It is intended that this is used in conjunction with an earlier GET request or a GET request on another instance, to restore a previous state. + +.. note:: + + Persisted data is written when the plugin is shutdown. Therefore in order to obtain predictable results this call should only be made when the service is shutdown. Calling this API when a service is running will result in data that is written by the call being overwritten by the plugin when it shuts down. + + +``DELETE /fledge/service/{service_name}/plugin/{plugin_name}/data`` - delete the persisted data for the plugin + +.. note:: + + Persisted data is written when the plugin is shutdown. Therefore in order to obtain predictable results this call should only be made when the service is shutdown. Calling this API when a service is running will result the data being written from the plugin when it is shutdown and render this delete operation obsolete. diff --git a/docs/rest_api_guide/06_GrafanaExamples.rst b/docs/rest_api_guide/06_GrafanaExamples.rst new file mode 100644 index 0000000000..4eee69af59 --- /dev/null +++ b/docs/rest_api_guide/06_GrafanaExamples.rst @@ -0,0 +1,159 @@ +.. +.. Images +.. |GrafanaAsset| image:: ../images/Grafana_asset.jpg +.. |GrafanaPing| image:: ../images/Grafana_ping.jpg +.. |GrafanaReading| image:: ../images/Grafana_reading.jpg +.. |GrafanaStatistics| image:: ../images/Grafana_statistics.jpg +.. |GrafanaTimestamp| image:: ../images/Grafana_Timestamp.jpg + +.. Links +.. |grafana| raw:: html + + Grafana + +Grafana Examples +================ + +The REST API of Fledge provides a way to integrate other applications with Fledge, these applications can control Fledge or that may be used to monitor the operation of Fledge itself or to visualize the data held within a Fledge instance. One such tool is |grafana|. Here we will show some simple examples of how the Fledge REST API can be used with Grafana and the Infinity data source plugin. This is intended to be a simple example, more complex systems can be built using these tools. + +Show Fledge Status +------------------ + +Using the *GET /fledge/ping* endpoint we can retrieve information about the number of readings read, sent, purged etc. + +.. code-block:: console + + $ curl http://localhost:8081/fledge/ping + +Which would return a JSON payload that looks similar to that shown below + +.. code-block:: JSON + + { + "uptime": 13203, + "dataRead": 2045868, + "dataSent": 6700, + "dataPurged": 1293723, + "authenticationOptional": true, + "serviceName": "Fledge", + "hostName": "foglamp-18", + "ipAddresses": [ + "192.168.0.172" + ], + "health": "green", + "safeMode": false, + "version": "1.9.2" + } + +We can use this URL as the query for a Grafana dashboard panel to retrieve the basic statistics. We then select the items we want to display as columns and set the type of these, in this case we have chosen the basic counters which are numeric value. + ++---------------+ +| |GrafanaPing| | ++---------------+ + +Display Statistics +------------------ + +This example sow how to take a set of values over time and display them graphically within Grafana. The major difference here is the treatment of the timestamp. In this example we are using the statistics history API to retrieve statistics data over time. + +Using the curl command to look at the API call + +.. code-block:: console + + curl http://localhost:8081/fledge/statistics/history|jq + +We get a JSON response as follows + +.. code-block:: console + + { + "interval": 15, + "statistics": [ + { + "history_ts": "2022-08-25 11:31:29.565", + "READINGS": 68, + "BUFFERED": 0, + "UNSENT": 0, + "PURGED": 0, + "UNSNPURGED": 0, + "DISCARDED": 0, + "coap-Ingest": 0, + "COAP": 0, + "Sine-Ingest": 0, + "SINUSOID": 0, + "exp-Ingest": 0, + "EXPRESSION": 0, + "Readings Sent": 0, + "OP": 0, + "test1-Ingest": 0, + "sine2-Ingest": 15, + "SINE210": 0, + "SINE25": 0, + "SINE2": 0, + "SINE250": 15, + "OMF": 0, + "PRESINE2.SINUSOID": 0, + "SINUSOID2": 0, + "lathe1004-Ingest": 53, + "LATHE1004": 15, + "LATHE1004CURRENT": 15, + "LATHE1004IR": 15, + "LATHE1004VIBRATION": 8, + "testacl-Ingest": 0, + "dsds-Ingest": 0, + "OMF2": 0, + "test-Ingest": 0 + }, + ... + } + +We are interested in the array of data under the *statistics* object in the JSON, therefore we choose a value of *statistics* for the *Rows / Root* value. This means that each array element under *statistics* will be considered as a row in the query result. + ++---------------------+ +| |GrafanaStatistics| | ++---------------------+ + +We then select the columns as before to extract the values we are interested in displaying. These are all set to be of type *Number*. + +In order to have the data graphed over time we must also select a timestamp column, in this case *history_ts* will be used. We can not set this as a timestamp type column as the Fledge timestamp format is not directly supported by Grafana. We must set up a transformation to take the string value from *history_ts* and convert it to a timestamp that can be understood by Grafana. + ++--------------------+ +| |GrafanaTimestamp| | ++--------------------+ + +In this transform we give it the Fledge timestamp format and set the desired result type to be a Timestamp. This now allows Grafana to understand the timestamps and display the Fledge data. + +One final point to mention, the Fledge timestamps are returned in UTC whereas Grafana assumes the data is in the local timezone. To resolve this merely set the preferences in Grafana to expect UTC data or add a time adjustment based on the number of hours from UTC at your location. + +Graph Reading Data +------------------ + +This example is very similar to that of the statistics history example above, the major difference is that we are extracting the readings data from the buffer using the */fledge/asset/{assetName}* URL. + ++------------------+ +| |GrafanaReading| | ++------------------+ + +We must select the data to display in the same way, we use the *limit=* to allow the query to return sufficient data. Ideally we would have a time bound query here, but that is outside the scope of this simple example. + +.. code-block:: console + + $ curl http://localhost:8081/fledge/asset/sine250?limit=2 |jq + [ + { + "reading": { + "sinusoid": -0.951056516 + }, + "timestamp": "2022-08-25 13:47:45.624800" + }, + { + "reading": { + "sinusoid": -0.978147601 + }, + "timestamp": "2022-08-25 13:47:44.624586" + } + ] + +We add the columns we require, there is no need to select the *Rows / Root* in this example as the array is already at the root of the JSON document returned. + +We must also do the same transformation for the timestamp format we did above. diff --git a/docs/rest_api_guide/index.rst b/docs/rest_api_guide/index.rst index 2ed9366948..b814166f57 100644 --- a/docs/rest_api_guide/index.rst +++ b/docs/rest_api_guide/index.rst @@ -7,5 +7,12 @@ REST API Developers Guide .. toctree:: 01_REST - 02_RESTadmin - 03_RESTuser + 02_RESTauthentication + 03_RESTadmin + 03_RESTstatistics + 03_RESTassetTracker + 03_RESTupdate + 03_RESTservices + 04_RESTuser + 05_RESTdeveloper + 06_GrafanaExamples diff --git a/python/fledge/services/core/api/statistics.py b/python/fledge/services/core/api/statistics.py index 7f3fee9210..142cf90026 100644 --- a/python/fledge/services/core/api/statistics.py +++ b/python/fledge/services/core/api/statistics.py @@ -189,7 +189,7 @@ async def get_statistics_rate(request: web.Request) -> web.Response: raise web.HTTPBadRequest(reason="The maximum allowed value for a period is 10080 minutes") stats = params['statistics'] - stat_split_list = list(filter(None, [x.upper() for x in stats.split(',')])) + stat_split_list = list(filter(None, [x for x in stats.split(',')])) storage_client = connect.get_storage_async() # To find the interval in secs from stats collector schedule scheduler_payload = PayloadBuilder().SELECT("schedule_interval").WHERE( diff --git a/tests/unit/python/fledge/services/core/api/test_statistics_api.py b/tests/unit/python/fledge/services/core/api/test_statistics_api.py index 42f6ea194a..6b4bd6f338 100644 --- a/tests/unit/python/fledge/services/core/api/test_statistics_api.py +++ b/tests/unit/python/fledge/services/core/api/test_statistics_api.py @@ -493,7 +493,7 @@ async def test_bad_get_statistics_rate(self, client, params, msg): assert msg == resp.reason async def test_get_statistics_rate(self, client, params='?periods=1,5&statistics=readings'): - output = {'rates': {'READINGS': {'1': 120.52585669781932, '5': 120.52585669781932}}} + output = {'rates': {'readings': {'1': 120.52585669781932, '5': 120.52585669781932}}} p1 = {'where': {'value': 'stats collector', 'condition': '=', 'column': 'process_name'}, 'return': ['schedule_interval']} p2 = {"return": ["key"], "aggregate": [{"operation": "sum", "column": "value"}, From a4bab5582ff85dab6c68ceacf7c8d3b04fd6e8cf Mon Sep 17 00:00:00 2001 From: pronoob Date: Mon, 12 Sep 2022 19:32:45 +0530 Subject: [PATCH 08/48] Pair system test fix (#820) Fix for pair test sending data via PIWeb API. --- tests/system/python/pair/test_pyton_north_service_pair.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/python/pair/test_pyton_north_service_pair.py b/tests/system/python/pair/test_pyton_north_service_pair.py index a5be218cb4..fbd4ab3d90 100644 --- a/tests/system/python/pair/test_pyton_north_service_pair.py +++ b/tests/system/python/pair/test_pyton_north_service_pair.py @@ -21,7 +21,7 @@ # Local machine local_south_plugin = "sinusoid" -local_south_asset_name = "sinusoid" +local_south_asset_name = "python-north-service-pair" local_south_service_name = "Sine #1" local_north_plugin = "http-north" local_north_service_name = "HN #1" @@ -55,7 +55,7 @@ def reset_fledge_local(wait_time): @pytest.fixture def setup_local(reset_fledge_local, add_south, add_north, fledge_url, remote_ip): - local_south_config = {"assetName": {"value": remote_south_asset_name}} + local_south_config = {"assetName": {"value": local_south_asset_name}} add_south(local_south_plugin, None, fledge_url, config=local_south_config, service_name="{}".format(local_south_service_name), installation_type='package') From 52ec3055248e8e13fbb4764c021e92b2c359cc69 Mon Sep 17 00:00:00 2001 From: pronoob Date: Wed, 14 Sep 2022 19:10:25 +0530 Subject: [PATCH 09/48] Delete OTT tokens for user if something is updated for it. FOGL-6892. (#817) Delete OTT tokens for user if something is updated for it. FOGL-6892. --- python/fledge/services/core/api/auth.py | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/python/fledge/services/core/api/auth.py b/python/fledge/services/core/api/auth.py index 86bd3a3aa3..0ddf7907c2 100644 --- a/python/fledge/services/core/api/auth.py +++ b/python/fledge/services/core/api/auth.py @@ -75,6 +75,27 @@ def __init__(self): pass +def __remove_ott_for_user(user_id): + """Helper function that removes given user_id from OTT_MAP if the user exists in the map.""" + try: + _user_id = int(user_id) + except ValueError as ex: + _logger.info("User id given is not an integer.") + return + for k, v in OTT.OTT_MAP.items(): + if v[0] == _user_id: + OTT.OTT_MAP.pop(k) + break + + +def __remove_ott_for_token(given_token): + """Helper function that removes given token from OTT_MAP if that token in the map.""" + for k, v in OTT.OTT_MAP.items(): + if v[1] == given_token: + OTT.OTT_MAP.pop(k) + break + + async def login(request): """ Validate user with its username and password @@ -238,6 +259,7 @@ async def logout_me(request): _logger.warning("Logout requested with bad user token") raise web.HTTPNotFound() + __remove_ott_for_token(request.token) _logger.info("User has been logged out successfully") return web.json_response({"logout": True}) @@ -262,6 +284,9 @@ async def logout(request): _logger.warning("Logout requested with bad user") raise web.HTTPNotFound() + # Remove OTT token for this user if there. + __remove_ott_for_user(user_id) + _logger.info("User with id:<{}> has been logged out successfully".format(int(user_id))) else: # requester is not an admin but trying to take action for another user @@ -535,6 +560,11 @@ async def update_user(request): user = await User.Objects.update(user_id, user_data) if user: user_info = await User.Objects.get(uid=user_id) + + if 'access_method' in data: + # Remove OTT token for this user only if access method is updated. + __remove_ott_for_user(user_id) + except ValueError as err: msg = str(err) raise web.HTTPBadRequest(reason=str(err), body=json.dumps({"message": msg})) @@ -592,6 +622,10 @@ async def update_password(request): try: await User.Objects.update(int(user_id), {'password': new_password}) + + # Remove OTT token for this user if there. + __remove_ott_for_user(user_id) + except ValueError as ex: _logger.warning(str(ex)) raise web.HTTPBadRequest(reason=str(ex)) @@ -645,6 +679,8 @@ async def enable_user(request): raise User.DoesNotExist payload = PayloadBuilder().SET(enabled=user_data['enabled']).WHERE(['id', '=', user_id]).payload() result = await storage_client.update_tbl("users", payload) + # Remove ott token for this enabled/disabled user. + __remove_ott_for_user(user_id) if result['response'] == 'updated': _text = 'enabled' if user_data['enabled'] == 't' else 'disabled' payload = PayloadBuilder().SELECT("id", "uname", "role_id", "enabled").WHERE( @@ -717,6 +753,10 @@ async def reset(request): try: await User.Objects.update(user_id, user_data) + + # Remove OTT token for this user if there. + __remove_ott_for_user(user_id) + except ValueError as ex: _logger.warning(str(ex)) raise web.HTTPBadRequest(reason=str(ex)) @@ -771,6 +811,9 @@ async def delete_user(request): if not result['rows_affected']: raise User.DoesNotExist + # Remove OTT token for this user if there. + __remove_ott_for_user(user_id) + except ValueError as ex: _logger.warning(str(ex)) raise web.HTTPBadRequest(reason=str(ex)) From 4a58ebbbd80e422241c72f2747e509c2688fcd9a Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Thu, 15 Sep 2022 12:28:16 +0530 Subject: [PATCH 10/48] Documentation branch changes in plugin and service documentation Signed-off-by: ashish-jabble --- docs/scripts/plugin_and_service_documentation | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/scripts/plugin_and_service_documentation b/docs/scripts/plugin_and_service_documentation index c0de4afae1..2699dd4989 100644 --- a/docs/scripts/plugin_and_service_documentation +++ b/docs/scripts/plugin_and_service_documentation @@ -3,7 +3,7 @@ # The best default branch to use develop rather than master. As new repository do not have a branch called master any more and having main branch only. if [[ "${DOCBRANCH}" == "" ]]; then # NOTE: During release time we need to replace develop and nightly build with actual released version - export DOCBRANCH=2.0.0RC + export DOCBRANCH=develop export ARCHIVE_BUILD=nightly else # only for dev purpose From 6646f529ded05028dbc8ef304da046df9bf9f878 Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Thu, 15 Sep 2022 12:48:58 +0530 Subject: [PATCH 11/48] schema as per develop Signed-off-by: ashish-jabble --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 7cbf336050..bca1eea4a4 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ fledge_version=2.0.0 -fledge_schema=56 \ No newline at end of file +fledge_schema=57 \ No newline at end of file From bfebbffd27952b19f1ed371daee96d834aaa62c1 Mon Sep 17 00:00:00 2001 From: pronoob Date: Fri, 16 Sep 2022 20:11:20 +0530 Subject: [PATCH 12/48] FOGL-6887 API to get Storage & data directory disk health (#825) FOGL-6887 API to get Storage & data directory disk health. --- .../microservice_management_client.py | 13 +- python/fledge/services/core/api/health.py | 134 ++++++++++++++++++ python/fledge/services/core/routes.py | 4 + 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 python/fledge/services/core/api/health.py diff --git a/python/fledge/common/microservice_management_client/microservice_management_client.py b/python/fledge/common/microservice_management_client/microservice_management_client.py index af395aa485..70196433fb 100644 --- a/python/fledge/common/microservice_management_client/microservice_management_client.py +++ b/python/fledge/common/microservice_management_client/microservice_management_client.py @@ -303,6 +303,18 @@ def update_configuration_item(self, category_name, config_item, category_data): response = json.loads(res) return response + async def ping_service(self): + + import aiohttp + async with aiohttp.ClientSession() as session: + async with session.get('http://{}:{}/fledge/service/ping'.format(self.hostname, + self.port)) as resp: + json_response = await resp.json() + self._management_client_conn.close() + self.port = None + self.hostname = None + return json_response + async def update_service_for_acl_change_security(self, acl, reason): assert reason in ["attachACL", "detachACL", "reloadACL", "updateACL"] url = "/fledge/security" @@ -315,7 +327,6 @@ async def update_service_for_acl_change_security(self, acl, reason): async with session.put('http://{}:{}/fledge/security'.format(self.hostname, self.port), data=json.dumps(payload)) as resp: - _logger.info(resp.status) json_response = await resp.json() _logger.debug("The response is {}".format(json_response)) self._management_client_conn.close() diff --git a/python/fledge/services/core/api/health.py b/python/fledge/services/core/api/health.py new file mode 100644 index 0000000000..1ba69e98e2 --- /dev/null +++ b/python/fledge/services/core/api/health.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- + +# FLEDGE_BEGIN +# See: http://fledge-iot.readthedocs.io/ +# FLEDGE_END + +import logging +import asyncio +import json + +from aiohttp import web +from fledge.common import logger +from fledge.common.common import _FLEDGE_DATA, _FLEDGE_ROOT + + +__author__ = "Deepanshu Yadav" +__copyright__ = "Copyright (c) 2022, Dianomic Systems Inc." +__license__ = "Apache 2.0" +__version__ = "${VERSION}" + +_help = """ + ---------------------------------------------------------- + | GET | /fledge/health/storage | + ---------------------------------------------------------- +""" +_LOGGER = logger.setup(__name__, level=logging.INFO) + + +async def get_storage_health(request: web.Request) -> web.Response: + """ + Return the health of Storage service & data directory. + Args: + request: None + + Returns: + Return the health of Storage service & data directory. + Sample Response : + + { + "uptime": 33, + "name": "Fledge Storage", + "statistics": { + "commonInsert": 30, + "commonSimpleQuery": 3, + "commonQuery": 91, + "commonUpdate": 2, + "commonDelete": 1, + "readingAppend": 0, + "readingFetch": 0, + "readingQuery": 1, + "readingPurge": 0 + }, + "disk": { + "used": 95287524, + "usage": 82, + "available": 20918108, + "status": "green" + } + } + + :Example: + curl -X GET http://localhost:8081/fledge/health/storage + """ + # Find the address and management host for the Storage service. + from fledge.services.core.service_registry.service_registry import ServiceRegistry + from fledge.services.core.service_registry.exceptions import DoesNotExist + try: + services = ServiceRegistry.get(name="Fledge Storage") + service = services[0] + except DoesNotExist: + msg = "Cannot ping the storage service. It does not exist in service registry." + _LOGGER.error(msg) + raise web.HTTPNotFound(reason=msg, body=json.dumps({"message": msg})) + try: + from fledge.common.service_record import ServiceRecord + if service._status != ServiceRecord.Status.Running: + msg = "The Storage service is not in Running state." + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + + from fledge.common.microservice_management_client.microservice_management_client import \ + MicroserviceManagementClient + + mgt_client = MicroserviceManagementClient(service._address, + service._management_port) + response = await mgt_client.ping_service() + + except Exception as ex: + msg = str(ex) + _LOGGER.error("Could not ping Storage due to {}".format(msg)) + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + + try: + + response['disk'] = {} + data_dir_path = _FLEDGE_DATA if _FLEDGE_DATA else _FLEDGE_ROOT + '/data' + disk_check_process = await asyncio.create_subprocess_shell('df -k ' + data_dir_path, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE) + + stdout, stderr = await disk_check_process.communicate() + if disk_check_process.returncode != 0: + stderr = stderr.decode("utf-8") + msg = "Failed to get disk stats! {}".format(str(stderr)) + _LOGGER.error(msg) + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + + # Following output is parsed. + """ + Filesystem 1K-blocks Used Available Use% Mounted on + /dev/sda5 122473072 95449760 20755872 83% / + + """ + disk_stats = stdout.decode("utf-8") + required_stats = disk_stats.split('\n')[1].split() + used = int(required_stats[2]) + available = int(required_stats[3]) + usage = int(required_stats[4].replace("%", '')) + status = 'green' + if usage > 95: + status = 'red' + elif 90 < usage <= 95: + status = 'yellow' + + except Exception as ex: + msg = "Failed to get disk stats! {}".format(str(ex)) + _LOGGER.error(msg) + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + else: + # fill all the fields after values are retrieved + response['disk']['used'] = used + response['disk']['usage'] = usage + response['disk']['available'] = available + response['disk']['status'] = status + return web.json_response(response) diff --git a/python/fledge/services/core/routes.py b/python/fledge/services/core/routes.py index 183edb268e..0ae665f7ea 100644 --- a/python/fledge/services/core/routes.py +++ b/python/fledge/services/core/routes.py @@ -35,6 +35,8 @@ from fledge.services.core.api.control_service import script_management from fledge.services.core.api.control_service import acl_management from fledge.services.core.api import python_packages +from fledge.services.core.api import health + __author__ = "Ashish Jabble, Praveen Garg, Massimiliano Pinto, Amarendra K Sinha" __copyright__ = "Copyright (c) 2017-2018 OSIsoft, LLC" @@ -258,6 +260,8 @@ def setup(app): app.router.add_route('GET', '/fledge/python/packages', python_packages.get_packages) app.router.add_route('POST', '/fledge/python/package', python_packages.install_package) + app.router.add_route('GET', '/fledge/health/storage', health.get_storage_health) + # Proxy Admin API setup with regex proxy.admin_api_setup(app) From a5eb4d6568ef34cf48d38d94aecfbf2c65394efb Mon Sep 17 00:00:00 2001 From: pronoob Date: Fri, 16 Sep 2022 22:55:30 +0530 Subject: [PATCH 13/48] Fetch list of upgradable packages for fledge repository FOGL-6888. (#824) Fetch list of upgradable packages for fledge repository FOGL-6888. --- python/fledge/services/core/api/update.py | 77 ++++++++++++++++++++++- python/fledge/services/core/routes.py | 2 + 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/python/fledge/services/core/api/update.py b/python/fledge/services/core/api/update.py index c3e4020c39..0fde626928 100644 --- a/python/fledge/services/core/api/update.py +++ b/python/fledge/services/core/api/update.py @@ -11,6 +11,9 @@ from aiohttp import web import datetime import os +import asyncio +import re +import platform from fledge.services.core import server from fledge.common import logger @@ -26,7 +29,7 @@ _help = """ ----------------------------------------- - | PUT | /fledge/update | + | PUT, GET | /fledge/update | ----------------------------------------- """ @@ -107,3 +110,75 @@ async def update_package(request): raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) else: return web.json_response({"status": "Running", "message": status_message}) + + +async def get_updates(request: web.Request) -> web.Response: + """ + Gives list of packages for which updates are available. + + Returns JSON Response + Sample Response + { + "updates": [ + "fledge-south-sinusoid","fledge" + ] + } + Example + curl -sX GET http://localhost:8081/fledge/update |jq + """ + _platform = platform.platform() + update_cmd = "sudo apt update" + upgradable_pkgs_check_cmd = "apt list --upgradable | grep \^fledge" + if "centos" in _platform or "redhat" in _platform: + update_cmd = "sudo yum check-update" + upgradable_pkgs_check_cmd = "yum list updates | grep \^fledge" + + update_process = await asyncio.create_subprocess_shell(update_cmd, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE) + _, stderr = await update_process.communicate() + if update_process.returncode != 0: + msg = "Could not run {} due to {}".format(update_cmd, stderr.decode('utf-8')) + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + + upgradable_pkgs_check_process = await asyncio.create_subprocess_shell(upgradable_pkgs_check_cmd, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE) + + stdout, stderr = await upgradable_pkgs_check_process.communicate() + if upgradable_pkgs_check_process.returncode != 0: + _logger.info("Nothing to upgrade at the moment. {}".format(stderr.decode("utf-8"))) + upgradable_packages = [] + return web.json_response({'updates': upgradable_packages}) + try: + process_output = stdout.decode("utf-8") + _logger.info(process_output) + # split on new-line + word_list = re.split(r"\n+", process_output) + + # remove '' from the list + word_list = [w for w in word_list if w != ''] + packages = [] + + # For APT the output of apt list is as follows: + """ + $ apt list --upgradable + Listing... Done + fledge-gui/unknown 1.9.2-440-gf849eed5 all [upgradable from: 1.9.2] + fledge-south-sinusoid/unknown 1.9.2-1-g38a138f amd64 [upgradable from: 1.9.2] + """ + # Now match the character / . The string before / is the actual package name we want. + for word in word_list: + # TODO find regex for yum as well. + word_match = re.findall(r".*[/]", word) + if len(word_match) > 0: + packages.append(word_match[0].replace('/', '').strip()) + + # Make a set to avoid duplicates. + upgradable_packages = list(set(packages)) + except Exception as ex: + msg = "Failed to fetch upgradable packages list for the configured repository! {}".format(str(ex)) + _logger.error(msg) + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + else: + return web.json_response({'updates': upgradable_packages}) diff --git a/python/fledge/services/core/routes.py b/python/fledge/services/core/routes.py index 0ae665f7ea..5b8efb1720 100644 --- a/python/fledge/services/core/routes.py +++ b/python/fledge/services/core/routes.py @@ -38,6 +38,7 @@ from fledge.services.core.api import health + __author__ = "Ashish Jabble, Praveen Garg, Massimiliano Pinto, Amarendra K Sinha" __copyright__ = "Copyright (c) 2017-2018 OSIsoft, LLC" __license__ = "Apache 2.0" @@ -168,6 +169,7 @@ def setup(app): # Package Update on demand app.router.add_route('PUT', '/fledge/update', update.update_package) + app.router.add_route('GET', '/fledge/update', update.get_updates) # certs store app.router.add_route('GET', '/fledge/certificate', certificate_store.get_certs) From cc752dad24e8b2e44b0062e92811a13b3a557abc Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Mon, 19 Sep 2022 11:06:30 +0530 Subject: [PATCH 14/48] data column added in asset_tracker table for PostgreSQL engine i.e init.sql Signed-off-by: ashish-jabble --- scripts/plugins/storage/postgres/init.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/plugins/storage/postgres/init.sql b/scripts/plugins/storage/postgres/init.sql index 638a91a3fe..6bdd7cc2f4 100644 --- a/scripts/plugins/storage/postgres/init.sql +++ b/scripts/plugins/storage/postgres/init.sql @@ -773,7 +773,8 @@ CREATE TABLE fledge.asset_tracker ( fledge character varying(50) NOT NULL, -- FL service name plugin character varying(50) NOT NULL, -- Plugin name deprecated_ts timestamp(6) with time zone , -- When an asset record is removed then time will be set else empty and that mean entry has not been deprecated - ts timestamp(6) with time zone NOT NULL DEFAULT now() + ts timestamp(6) with time zone NOT NULL DEFAULT now(), + data jsonb DEFAULT '{}'::jsonb ); CREATE INDEX asset_tracker_ix1 ON fledge.asset_tracker USING btree (asset); From 8ff588531612b6273c49eb0985b1ac9b9805311f Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Tue, 20 Sep 2022 10:58:52 +0530 Subject: [PATCH 15/48] missing data column added in asset_tracker table for sqlitelb engine Signed-off-by: ashish-jabble --- scripts/plugins/storage/sqlitelb/init.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/plugins/storage/sqlitelb/init.sql b/scripts/plugins/storage/sqlitelb/init.sql index e259a8a6c8..496c5de958 100644 --- a/scripts/plugins/storage/sqlitelb/init.sql +++ b/scripts/plugins/storage/sqlitelb/init.sql @@ -566,7 +566,8 @@ CREATE TABLE fledge.asset_tracker ( fledge character varying(50) NOT NULL, -- FL service name plugin character varying(50) NOT NULL, -- Plugin name deprecated_ts DATETIME , -- When an asset record is removed then time will be set else empty and that mean entry has not been deprecated - ts DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime')) + ts DATETIME DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW', 'localtime')), + data JSON DEFAULT '{}' ); CREATE INDEX asset_tracker_ix1 ON asset_tracker (asset); From b17868e6dc7a8681c7c270f34e45bb9e5a7c37a8 Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Tue, 20 Sep 2022 13:40:34 +0100 Subject: [PATCH 16/48] FOGL-6935 Fix incorrect JSON for NorthServoce::operation (#832) Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/services/north/north.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/C/services/north/north.cpp b/C/services/north/north.cpp index 1dbd42129c..25541af599 100755 --- a/C/services/north/north.cpp +++ b/C/services/north/north.cpp @@ -948,7 +948,7 @@ int NorthService::operation(const string& name, int paramCount, char *names[], string payload = "{ \"destination\" : \"broadcast\","; payload += "\"operation\" : { \""; payload += name; - payload += "\" : { \""; + payload += "\" : { "; for (int i = 0; i < paramCount; i++) { payload += "\""; @@ -959,7 +959,7 @@ int NorthService::operation(const string& name, int paramCount, char *names[], if (i < paramCount -1) payload += ","; } - payload += "\" } }"; + payload += " } } }"; sendToDispatcher("/dispatch/operation", payload); return -1; } From 781d5a030dcfb1cf3da52bb420a0ff52f182f867 Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Wed, 21 Sep 2022 09:21:29 +0100 Subject: [PATCH 17/48] FOGL-6925 Add periodic SQLite vacuum (#826) * FOGL-6925 Add periodic SQLite vacuum Signed-off-by: Mark Riddoch * FOGL-6925 Fix descriptions Signed-off-by: Mark Riddoch * FOGL-6925 Add empty vacuum command for in memory database Signed-off-by: Mark Riddoch * FOGL-6925 Add vacuum to SQLiteMemory plugin Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- .../storage/sqlite/common/connection.cpp | 25 ++++++++++++ .../sqlite/common/connection_manager.cpp | 39 +++++++++++++++++- .../sqlite/common/include/connection.h | 1 + .../common/include/connection_manager.h | 8 ++++ C/plugins/storage/sqlite/plugin.cpp | 13 ++++++ .../storage/sqlitelb/common/connection.cpp | 25 ++++++++++++ .../sqlitelb/common/connection_manager.cpp | 40 ++++++++++++++++++- .../sqlitelb/common/include/connection.h | 1 + .../common/include/connection_manager.h | 8 ++++ C/plugins/storage/sqlitelb/plugin.cpp | 14 ++++++- C/plugins/storage/sqlitememory/connection.cpp | 9 +++++ .../storage/sqlitememory/include/connection.h | 1 + docs/storage.rst | 2 + 13 files changed, 182 insertions(+), 4 deletions(-) diff --git a/C/plugins/storage/sqlite/common/connection.cpp b/C/plugins/storage/sqlite/common/connection.cpp index fc2173897f..a55dab911d 100644 --- a/C/plugins/storage/sqlite/common/connection.cpp +++ b/C/plugins/storage/sqlite/common/connection.cpp @@ -3720,4 +3720,29 @@ bool Connection::createSchema(const std::string &schema) { return m_schemaManager->create(dbHandle, schema); } + +/** + * Execute a SQLite VACUUM command on the database + */ +bool Connection::vacuum() +{ + char* zErrMsg = NULL; + // Exec the statement + int rc = SQLexec(dbHandle, "VACUUM;", NULL, NULL, &zErrMsg); + + // Check result + if (rc != SQLITE_OK) + { + const char* errMsg = "Failed to vacuum database "; + Logger::getLogger()->error("%s: error %s", + errMsg, zErrMsg); + sqlite3_free(zErrMsg); + return false; + } + else + { + Logger::getLogger()->info("Database vacuum complete"); + } + return true; +} #endif diff --git a/C/plugins/storage/sqlite/common/connection_manager.cpp b/C/plugins/storage/sqlite/common/connection_manager.cpp index 684fe795c5..ee417de40f 100644 --- a/C/plugins/storage/sqlite/common/connection_manager.cpp +++ b/C/plugins/storage/sqlite/common/connection_manager.cpp @@ -16,10 +16,19 @@ ConnectionManager *ConnectionManager::instance = 0; +/** + * Background thread entry point + */ +static void managerBackground(void *arg) +{ + ConnectionManager *mgr = (ConnectionManager *)arg; + mgr->background(); +} + /** * Default constructor for the connection manager. */ -ConnectionManager::ConnectionManager() +ConnectionManager::ConnectionManager() : m_shutdown(false), m_vacuumInterval(6 * 60 * 60) { lastError.message = NULL; lastError.entryPoint = NULL; @@ -27,6 +36,8 @@ ConnectionManager::ConnectionManager() m_trace = true; else m_trace = false; + m_background = new std::thread(managerBackground, this); + } /** @@ -35,7 +46,10 @@ ConnectionManager::ConnectionManager() */ void ConnectionManager::shutdown() { + m_shutdown = true; shrinkPool(idle.size()); + if (m_background) + m_background->join(); } /** @@ -409,3 +423,26 @@ int ConnectionManager::SQLExec(sqlite3 *dbHandle, const char *sqlCmd, char **err return rc; } + +/** + * Background thread used to execute periodic tasks and oversee the database activity. + * + * We will runt he SQLite vacuum command periodically to allow space to be reclaimed + */ +void ConnectionManager::background() +{ + time_t nextVacuum = time(0) + m_vacuumInterval; + + while (!m_shutdown) + { + sleep(15); + time_t tim = time(0); + if (m_vacuumInterval && tim > nextVacuum) + { + Connection *con = allocate(); + con->vacuum(); + release(con); + nextVacuum = time(0) + m_vacuumInterval; + } + } +} diff --git a/C/plugins/storage/sqlite/common/include/connection.h b/C/plugins/storage/sqlite/common/include/connection.h index 81a014e026..62cef54a34 100644 --- a/C/plugins/storage/sqlite/common/include/connection.h +++ b/C/plugins/storage/sqlite/common/include/connection.h @@ -159,6 +159,7 @@ class Connection { void shutdownAppendReadings(); unsigned int purgeReadingsAsset(const std::string& asset); + bool vacuum(); private: diff --git a/C/plugins/storage/sqlite/common/include/connection_manager.h b/C/plugins/storage/sqlite/common/include/connection_manager.h index 51941f1210..2d33cc81fe 100644 --- a/C/plugins/storage/sqlite/common/include/connection_manager.h +++ b/C/plugins/storage/sqlite/common/include/connection_manager.h @@ -15,6 +15,7 @@ #include #include #include +#include class Connection; @@ -37,6 +38,10 @@ class ConnectionManager { { return &lastError; } + void background(); + void setVacuumInterval(long hours) { + m_vacuumInterval = 60 * 60 * hours; + }; protected: ConnectionManager(); @@ -53,6 +58,9 @@ class ConnectionManager { std::mutex errorLock; PLUGIN_ERROR lastError; bool m_trace; + bool m_shutdown; + std::thread *m_background; + long m_vacuumInterval; }; #endif diff --git a/C/plugins/storage/sqlite/plugin.cpp b/C/plugins/storage/sqlite/plugin.cpp index f3d8d0bf4c..c4c2b32cde 100644 --- a/C/plugins/storage/sqlite/plugin.cpp +++ b/C/plugins/storage/sqlite/plugin.cpp @@ -79,6 +79,14 @@ const char *default_config = QUOTE({ "default" : "", "displayName" : "Purge Exclusions", "order" : "6" + }, + "vacuumInterval" : { + "description" : "The interval between execution of a SQLite vacuum command", + "type" : "integer", + "minimum" : "1", + "default" : "6", + "displayName" : "Vacuum Interval", + "order" : "7" } }); @@ -158,6 +166,11 @@ PLUGIN_HANDLE plugin_init(ConfigCategory *category) purge->exclude(StringTrim(exclusions.substr(s, pos))); } + if (category->itemExists("vacuumInterval")) + { + manager->setVacuumInterval(strtol(category->getValue("vacuumInterval").c_str(), NULL, 10)); + } + return manager; } diff --git a/C/plugins/storage/sqlitelb/common/connection.cpp b/C/plugins/storage/sqlitelb/common/connection.cpp index 1546dbdf94..a3ccc19286 100644 --- a/C/plugins/storage/sqlitelb/common/connection.cpp +++ b/C/plugins/storage/sqlitelb/common/connection.cpp @@ -3337,4 +3337,29 @@ bool Connection::createSchema(const std::string &schema) { return m_schemaManager->create(dbHandle, schema); } + +/** + * Execute a SQLite VACUUM command on the database + */ +bool Connection::vacuum() +{ + char* zErrMsg = NULL; + // Exec the statement + int rc = SQLexec(dbHandle, "VACUUM;", NULL, NULL, &zErrMsg); + + // Check result + if (rc != SQLITE_OK) + { + const char* errMsg = "Failed to vacuum database "; + Logger::getLogger()->error("%s: error %s", + errMsg, zErrMsg); + sqlite3_free(zErrMsg); + return false; + } + else + { + Logger::getLogger()->info("Database vacuum complete"); + } + return true; +} #endif diff --git a/C/plugins/storage/sqlitelb/common/connection_manager.cpp b/C/plugins/storage/sqlitelb/common/connection_manager.cpp index adafd6adc2..4da5090368 100644 --- a/C/plugins/storage/sqlitelb/common/connection_manager.cpp +++ b/C/plugins/storage/sqlitelb/common/connection_manager.cpp @@ -9,14 +9,23 @@ */ #include #include - +#include ConnectionManager *ConnectionManager::instance = 0; +/** + * Background thread entry point + */ +static void managerBackground(void *arg) +{ + ConnectionManager *mgr = (ConnectionManager *)arg; + mgr->background(); +} + /** * Default constructor for the connection manager. */ -ConnectionManager::ConnectionManager() +ConnectionManager::ConnectionManager() : m_shutdown(false), m_vacuumInterval(6 * 60 * 60) { lastError.message = NULL; lastError.entryPoint = NULL; @@ -24,6 +33,7 @@ ConnectionManager::ConnectionManager() m_trace = true; else m_trace = false; + m_background = new std::thread(managerBackground, this); } /** @@ -32,7 +42,10 @@ ConnectionManager::ConnectionManager() */ void ConnectionManager::shutdown() { + m_shutdown = true; shrinkPool(idle.size()); + if (m_background) + m_background->join(); } /** @@ -160,3 +173,26 @@ void ConnectionManager::setError(const char *source, const char *description, bo lastError.message = strdup(description); errorLock.unlock(); } + +/** + * Background thread used to execute periodic tasks and oversee the database activity. + * + * We will runt he SQLite vacuum command periodically to allow space to be reclaimed + */ +void ConnectionManager::background() +{ + time_t nextVacuum = time(0) + m_vacuumInterval; + + while (!m_shutdown) + { + sleep(15); + time_t tim = time(0); + if (m_vacuumInterval && tim > nextVacuum) + { + Connection *con = allocate(); + con->vacuum(); + release(con); + nextVacuum = time(0) + m_vacuumInterval; + } + } +} diff --git a/C/plugins/storage/sqlitelb/common/include/connection.h b/C/plugins/storage/sqlitelb/common/include/connection.h index e8acb2e6fb..448790797b 100644 --- a/C/plugins/storage/sqlitelb/common/include/connection.h +++ b/C/plugins/storage/sqlitelb/common/include/connection.h @@ -118,6 +118,7 @@ class Connection { bool aggregateQuery(const rapidjson::Value& payload, std::string& resultSet); bool getNow(std::string& Now); unsigned int purgeReadingsAsset(const std::string& asset); + bool vacuum(); private: #ifndef MEMORY_READING_PLUGIN diff --git a/C/plugins/storage/sqlitelb/common/include/connection_manager.h b/C/plugins/storage/sqlitelb/common/include/connection_manager.h index 62ce84439f..eda1fb06db 100644 --- a/C/plugins/storage/sqlitelb/common/include/connection_manager.h +++ b/C/plugins/storage/sqlitelb/common/include/connection_manager.h @@ -13,6 +13,7 @@ #include #include #include +#include class Connection; @@ -32,6 +33,10 @@ class ConnectionManager { { return &lastError; } + void background(); + void setVacuumInterval(long hours) { + m_vacuumInterval = 60 * 60 * hours; + }; protected: ConnectionManager(); @@ -46,6 +51,9 @@ class ConnectionManager { std::mutex errorLock; PLUGIN_ERROR lastError; bool m_trace; + bool m_shutdown; + std::thread *m_background; + long m_vacuumInterval; }; #endif diff --git a/C/plugins/storage/sqlitelb/plugin.cpp b/C/plugins/storage/sqlitelb/plugin.cpp index 177db8bb69..10a4a1a973 100644 --- a/C/plugins/storage/sqlitelb/plugin.cpp +++ b/C/plugins/storage/sqlitelb/plugin.cpp @@ -41,7 +41,15 @@ const char *default_config = QUOTE({ "default" : "5", "displayName" : "Pool Size", "order" : "1" - } + }, + "vacuumInterval" : { + "description" : "The interval between execution of a SQLite vacuum command", + "type" : "integer", + "minimum" : "1", + "default" : "6", + "displayName" : "Vacuum Interval", + "order" : "2" + } }); /** @@ -79,6 +87,10 @@ int poolSize = 5; poolSize = strtol(category->getValue("poolSize").c_str(), NULL, 10); } manager->growPool(poolSize); + if (category->itemExists("vacuumInterval")) + { + manager->setVacuumInterval(strtol(category->getValue("vacuumInterval").c_str(), NULL, 10)); + } return manager; } diff --git a/C/plugins/storage/sqlitememory/connection.cpp b/C/plugins/storage/sqlitememory/connection.cpp index a6b8d8428b..608fa75fbd 100644 --- a/C/plugins/storage/sqlitememory/connection.cpp +++ b/C/plugins/storage/sqlitememory/connection.cpp @@ -102,3 +102,12 @@ Connection::Connection() } } + +/** + * Add a vacuum funtion, this is not needed for SQLite In Memory, but is here + * to satisfy the interface requirement. + */ +bool Connection::vacuum() +{ + return true; +} diff --git a/C/plugins/storage/sqlitememory/include/connection.h b/C/plugins/storage/sqlitememory/include/connection.h index c4c2551739..974c4d7821 100644 --- a/C/plugins/storage/sqlitememory/include/connection.h +++ b/C/plugins/storage/sqlitememory/include/connection.h @@ -30,6 +30,7 @@ class Connection { void setTrace(bool flag) { m_logSQL = flag; }; static bool formatDate(char *formatted_date, size_t formatted_date_size, const char *date); unsigned int purgeReadingsAsset(const std::string& asset); + bool vacuum() { return true; }; private: int SQLexec(sqlite3 *db, const char *sql, int (*callback)(void*,int,char**,char**), diff --git a/docs/storage.rst b/docs/storage.rst index b5110653c4..a12fc66310 100644 --- a/docs/storage.rst +++ b/docs/storage.rst @@ -111,6 +111,8 @@ The SQLite plugin has a more complex set of configuration options that can be us - **Database allocation size**: The number of databases to create when the above threshold is crossed. Database creation is a slow process and hence the tuning of these parameters can impact performance when an instance receives a large number of new asset names for which it has previously not allocated readings tables. + - **Vacuum Interval**: The interval in hours between running a database vacuum command to reclaim space. Setting this too high will impact performance, setting it too low will mean that more storage may be required for longer periods. + Installing A PostgreSQL server ============================== From f666b79346e04076a86ed33790f70943956ef350 Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Wed, 21 Sep 2022 11:32:00 +0100 Subject: [PATCH 18/48] FOGL-6938 Fix crash with incorrect argument count for get_plugin_info (#833) Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch Co-authored-by: Aman <40791522+AmandeepArora@users.noreply.github.com> --- C/plugins/utils/get_plugin_info.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/C/plugins/utils/get_plugin_info.cpp b/C/plugins/utils/get_plugin_info.cpp index 82c7ea4cdb..cae8eb4bbb 100644 --- a/C/plugins/utils/get_plugin_info.cpp +++ b/C/plugins/utils/get_plugin_info.cpp @@ -24,15 +24,20 @@ typedef PLUGIN_INFORMATION *(*func_t)(); * * @param argv[1] relative/absolute path to north/south C plugin shared library * - * @param argv[2] symbol to extract value from (typically 'plugin_info') + * @param argv[2] symbol to extract value from (defaults 'plugin_info') */ int main(int argc, char *argv[]) { void *hndl; + char *routine = (char *)"plugin_info"; - if (argc<2) + if (argc == 3) { - fprintf(stderr, "Insufficient number of args...\n\nUsage: %s \n", argv[0]); + routine = argv[2]; + } + else if (argc < 2) + { + fprintf(stderr, "Insufficient number of args...\n\nUsage: %s [ ]\n", argv[0]); exit(1); } @@ -47,11 +52,11 @@ int main(int argc, char *argv[]) if ((hndl = dlopen(argv[1], RTLD_GLOBAL|RTLD_LAZY)) != NULL) { - func_t infoEntry = (func_t)dlsym(hndl, argv[2]); + func_t infoEntry = (func_t)dlsym(hndl, routine); if (infoEntry == NULL) { // Unable to find plugin_info entry point - fprintf(stderr, "Plugin library %s does not support %s function : %s\n", argv[1], argv[2], dlerror()); + fprintf(stderr, "Plugin library %s does not support %s function : %s\n", argv[1], routine, dlerror()); dlclose(hndl); closelog(); exit(3); From b2d54a369df202cd3044ea5572cf7cf5441c435b Mon Sep 17 00:00:00 2001 From: pronoob Date: Thu, 22 Sep 2022 15:47:53 +0530 Subject: [PATCH 19/48] Fogl 6877 API level changes for getting health of logging. (#828) FOGL-6877 API level changes for getting health of logging. --- python/fledge/services/core/api/health.py | 137 +++++++++++++++++----- python/fledge/services/core/routes.py | 2 + 2 files changed, 111 insertions(+), 28 deletions(-) diff --git a/python/fledge/services/core/api/health.py b/python/fledge/services/core/api/health.py index 1ba69e98e2..08f0267217 100644 --- a/python/fledge/services/core/api/health.py +++ b/python/fledge/services/core/api/health.py @@ -21,11 +21,114 @@ _help = """ ---------------------------------------------------------- | GET | /fledge/health/storage | + | GET | /fledge/health/logging | ---------------------------------------------------------- """ _LOGGER = logger.setup(__name__, level=logging.INFO) +async def get_disk_usage(given_dir): + """ + Helper function that calculates used, available, usage(in %) for a given directory in file system. + Returns a tuple of used(in KB's integer), available(in KB's integer), usage(in %) + """ + disk_check_process = await asyncio.create_subprocess_shell('df -k ' + given_dir, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE) + + stdout, stderr = await disk_check_process.communicate() + if disk_check_process.returncode != 0: + stderr = stderr.decode("utf-8") + msg = "Failed to get disk stats! {}".format(str(stderr)) + _LOGGER.error(msg) + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + + # Following output is parsed. + """ + Filesystem 1K-blocks Used Available Use% Mounted on + /dev/sda5 122473072 95449760 20755872 83% / + + """ + disk_stats = stdout.decode("utf-8") + required_stats = disk_stats.split('\n')[1].split() + used = int(required_stats[2]) + available = int(required_stats[3]) + usage = int(required_stats[4].replace("%", '')) + + return used, available, usage + + +async def get_logging_health(request: web.Request) -> web.Response: + """ + Return the health of logging. + Args: + request: None + + Returns: + Return the health of logging. + Sample Response : + + { + "disk": { + "usage": 63, + "used": 42936800, + "available": 25229400 + }, + "levels": [ + { + "name" : "Sine", + "level" : "info" + }, + { + "name" : "OMF", + "level" : "debug" + } + ] + } + + :Example: + curl -X GET http://localhost:8081/fledge/health/logging + """ + response = {} + try: + from fledge.common.storage_client.payload_builder import PayloadBuilder + from fledge.services.core import connect + + payload = PayloadBuilder().SELECT("key", "value").payload() + _storage_client = connect.get_storage_async() + excluded_log_levels = ["error", "warning"] + results = await _storage_client.query_tbl_with_payload('configuration', payload) + log_levels = [] + for row in results["rows"]: + for item_name, item_info in row["value"].items(): + if item_name == "logLevel" and item_info['value'] not in excluded_log_levels: + service_name = row["key"].replace("Advanced", "").strip() + log_level = item_info['value'] + log_levels.append({"name": service_name, "level": log_level}) + + response["levels"] = log_levels + + except Exception as ex: + msg = "Could not fetch service information.{}".format(str(ex)) + _LOGGER.error(msg) + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + + try: + response['disk'] = {} + used, available, usage = await get_disk_usage('/var/log') + # fill all the fields after values are retrieved + response['disk']['used'] = used + response['disk']['usage'] = usage + response['disk']['available'] = available + + except Exception as ex: + msg = "Failed to get disk stats for /var/log !{}".format(str(ex)) + _LOGGER.error(msg) + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + else: + return web.json_response(response) + + async def get_storage_health(request: web.Request) -> web.Response: """ Return the health of Storage service & data directory. @@ -90,45 +193,23 @@ async def get_storage_health(request: web.Request) -> web.Response: raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) try: - response['disk'] = {} data_dir_path = _FLEDGE_DATA if _FLEDGE_DATA else _FLEDGE_ROOT + '/data' - disk_check_process = await asyncio.create_subprocess_shell('df -k ' + data_dir_path, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE) - - stdout, stderr = await disk_check_process.communicate() - if disk_check_process.returncode != 0: - stderr = stderr.decode("utf-8") - msg = "Failed to get disk stats! {}".format(str(stderr)) - _LOGGER.error(msg) - raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) - - # Following output is parsed. - """ - Filesystem 1K-blocks Used Available Use% Mounted on - /dev/sda5 122473072 95449760 20755872 83% / - - """ - disk_stats = stdout.decode("utf-8") - required_stats = disk_stats.split('\n')[1].split() - used = int(required_stats[2]) - available = int(required_stats[3]) - usage = int(required_stats[4].replace("%", '')) + used, available, usage = await get_disk_usage(data_dir_path) status = 'green' if usage > 95: status = 'red' elif 90 < usage <= 95: status = 'yellow' - except Exception as ex: - msg = "Failed to get disk stats! {}".format(str(ex)) - _LOGGER.error(msg) - raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) - else: # fill all the fields after values are retrieved response['disk']['used'] = used response['disk']['usage'] = usage response['disk']['available'] = available response['disk']['status'] = status + except Exception as ex: + msg = "Failed to get disk stats! {}".format(str(ex)) + _LOGGER.error(msg) + raise web.HTTPInternalServerError(reason=msg, body=json.dumps({"message": msg})) + else: return web.json_response(response) diff --git a/python/fledge/services/core/routes.py b/python/fledge/services/core/routes.py index 5b8efb1720..a135e3a525 100644 --- a/python/fledge/services/core/routes.py +++ b/python/fledge/services/core/routes.py @@ -262,7 +262,9 @@ def setup(app): app.router.add_route('GET', '/fledge/python/packages', python_packages.get_packages) app.router.add_route('POST', '/fledge/python/package', python_packages.install_package) + # Health related calls app.router.add_route('GET', '/fledge/health/storage', health.get_storage_health) + app.router.add_route('GET', '/fledge/health/logging', health.get_logging_health) # Proxy Admin API setup with regex proxy.admin_api_setup(app) From 524989b80e251c6c8df652c3189a4bb0031f9753 Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Tue, 27 Sep 2022 10:25:45 +0100 Subject: [PATCH 20/48] FOGL-6799 Add Dryrun option to Python tasks (#821) * FOGL-6799 Add Dryrun option to Python tasks Signed-off-by: Mark Riddoch * Correct else if Signed-off-by: Mark Riddoch * Add missing self Signed-off-by: Mark Riddoch * Fix missing brackets Signed-off-by: Mark Riddoch * Intial draft version of configuration boot startup with some TODO comments Signed-off-by: ashish-jabble * Address review comments Signed-off-by: Mark Riddoch * Add backup and restore Signed-off-by: Mark Riddoch * Add automation script support Signed-off-by: Mark Riddoch * Add file missed from previous checkin Signed-off-by: Mark Riddoch * dryrun variable fixes in FledgeProcess class Signed-off-by: ashish-jabble * added comments for the dryrun & removed unused comments and logger statements Signed-off-by: ashish-jabble * dryrun exit in run def of python sending process; otherwise logs are cominng for every task Start, Stop, Completed Signed-off-by: ashish-jabble * Fixes SyntaxError in main automation script task Signed-off-by: ashish-jabble * dryrun handling in backup & restore for PostgreSQL Signed-off-by: ashish-jabble * dryrun handling in backup & restore for Sqlite Signed-off-by: ashish-jabble * system tests updated as now on startup the purge related configuration is available & along with audit logs Signed-off-by: ashish-jabble Signed-off-by: Mark Riddoch Signed-off-by: ashish-jabble Co-authored-by: ashish-jabble --- python/fledge/common/process.py | 19 ++++++- .../backup_restore/backup_postgres.py | 40 +++++++------- .../backup_restore/restore_postgres.py | 52 ++++++++----------- .../sqlite/backup_restore/backup_sqlite.py | 48 +++++++---------- .../sqlite/backup_restore/restore_sqlite.py | 52 ++++++++----------- python/fledge/services/core/server.py | 18 ++++++- .../tasks/automation_script/__main__.py | 7 +++ python/fledge/tasks/north/sending_process.py | 6 ++- python/fledge/tasks/purge/purge.py | 2 + .../tasks/statistics/statistics_history.py | 2 + tests/system/python/api/test_audit.py | 26 +++++----- tests/system/python/api/test_configuration.py | 15 +++++- 12 files changed, 162 insertions(+), 125 deletions(-) diff --git a/python/fledge/common/process.py b/python/fledge/common/process.py index db9804521c..c6dbdb6ffb 100644 --- a/python/fledge/common/process.py +++ b/python/fledge/common/process.py @@ -65,6 +65,9 @@ class FledgeProcess(ABC): _start_time = None """ time at which this python process started """ + _dryrun = False + """ this is a dry run invocation of the process used to populate configuration """ + def __init__(self): """ All processes must have these three command line arguments passed: @@ -88,7 +91,9 @@ def __init__(self): if self._core_management_port not in r: raise ArgumentParserError("Invalid Port: {}".format(self._core_management_port)) for item in args: - if item.startswith('--'): + if item == "--dryrun": + self._dryrun = True + elif item.startswith('--'): kv = item.split('=') if len(kv) == 2: if len(kv[1].strip()) == 0: @@ -198,3 +203,15 @@ def delete_configuration_item(self, category_name, config_item): """ return self._core_microservice_management_client.delete_configuration_item(category_name, config_item) + def is_dry_run(self): + """ + + Return true if this is a dry run of the process. Dry runs are used + to allow a task or service to add configuration without that task or + service performing whatever operation it normally does. Thus the user + can then update the configuration before the task or service is ever + started in anger. + + :return: Boolean + """ + return self._dryrun diff --git a/python/fledge/plugins/storage/postgres/backup_restore/backup_postgres.py b/python/fledge/plugins/storage/postgres/backup_restore/backup_postgres.py index b24128bc55..ab5bafa99d 100644 --- a/python/fledge/plugins/storage/postgres/backup_restore/backup_postgres.py +++ b/python/fledge/plugins/storage/postgres/backup_restore/backup_postgres.py @@ -526,9 +526,6 @@ def run(self): print("[FLEDGE] {0} - ERROR - {1}".format(current_time, message), file=sys.stderr) sys.exit(1) - # Starts - _logger.info(_MESSAGES_LIST["i000001"]) - # Initializes FledgeProcess and Backup classes - handling the command line parameters try: backup_process = BackupProcess() @@ -538,20 +535,23 @@ def run(self): _logger.info(_MESSAGES_LIST["i000002"]) sys.exit(1) - # Executes the backup - try: - # noinspection PyProtectedMember - _logger.debug("{module} - name |{name}| - address |{addr}| - port |{port}|".format( - module=_MODULE_NAME, - name=backup_process._name, - addr=backup_process._core_management_host, - port=backup_process._core_management_port)) - backup_process.run() - _logger.info(_MESSAGES_LIST["i000002"]) - sys.exit(0) - except Exception as ex: - message = _MESSAGES_LIST["e000002"].format(ex) - _logger.exception(message) - backup_process.shutdown() - _logger.info(_MESSAGES_LIST["i000002"]) - sys.exit(1) + if not backup_process.is_dry_run(): + try: + # noinspection PyProtectedMember + _logger.debug("{module} - name |{name}| - address |{addr}| - port |{port}|".format( + module=_MODULE_NAME, + name=backup_process._name, + addr=backup_process._core_management_host, + port=backup_process._core_management_port)) + _logger.info(_MESSAGES_LIST["i000001"]) + backup_process.run() + _logger.info(_MESSAGES_LIST["i000002"]) + sys.exit(0) + except Exception as ex: + message = _MESSAGES_LIST["e000002"].format(ex) + _logger.exception(message) + backup_process.shutdown() + sys.exit(1) + else: + # Put any configuration here if required for the backup + sys.exit() diff --git a/python/fledge/plugins/storage/postgres/backup_restore/restore_postgres.py b/python/fledge/plugins/storage/postgres/backup_restore/restore_postgres.py index 52372e62a2..bed0ae5eac 100644 --- a/python/fledge/plugins/storage/postgres/backup_restore/restore_postgres.py +++ b/python/fledge/plugins/storage/postgres/backup_restore/restore_postgres.py @@ -868,7 +868,6 @@ def init(self): Returns: Raises: """ - # Setups signals handlers, to avoid the termination of the restore # a) SIGINT: Keyboard interrupt # b) SIGTERM: kill or system shutdown @@ -920,7 +919,6 @@ def run(self): Raises: exceptions.RestoreFailed """ - self.init() try: @@ -952,40 +950,34 @@ def run(self): print("[FLEDGE] {0} - ERROR - {1}".format(current_time, message), file=sys.stderr) sys.exit(1) - # Starts - _logger.info(_MESSAGES_LIST["i000001"]) - # Initializes FledgeProcess and RestoreProcess classes - handling also the command line parameters try: restore_process = RestoreProcess() - except Exception as ex: message = _MESSAGES_LIST["e000004"].format(ex) _logger.exception(message) - _logger.info(_MESSAGES_LIST["i000002"]) sys.exit(1) - # Executes the Restore - try: - # noinspection PyProtectedMember - _logger.debug("{module} - name |{name}| - address |{addr}| - port |{port}| " - "- file |{file}| - backup_id |{backup_id}| ".format( - module=_MODULE_NAME, - name=restore_process._name, - addr=restore_process._core_management_host, - port=restore_process._core_management_port, - file=restore_process._file_name, - backup_id=restore_process._backup_id)) - - restore_process.run() - - _logger.info(_MESSAGES_LIST["i000002"]) - sys.exit(0) - - except Exception as ex: - message = _MESSAGES_LIST["e000002"].format(ex) - _logger.exception(message) - - _logger.info(_MESSAGES_LIST["i000002"]) - sys.exit(1) + if not restore_process.is_dry_run(): + try: + # noinspection PyProtectedMember + _logger.debug("{module} - name |{name}| - address |{addr}| - port |{port}| " + "- file |{file}| - backup_id |{backup_id}| ".format( + module=_MODULE_NAME, + name=restore_process._name, + addr=restore_process._core_management_host, + port=restore_process._core_management_port, + file=restore_process._file_name, + backup_id=restore_process._backup_id)) + _logger.info(_MESSAGES_LIST["i000001"]) + restore_process.run() + _logger.info(_MESSAGES_LIST["i000002"]) + sys.exit(0) + except Exception as ex: + message = _MESSAGES_LIST["e000002"].format(ex) + _logger.exception(message) + sys.exit(1) + else: + # Put any configuration here if required for the restore + sys.exit() diff --git a/python/fledge/plugins/storage/sqlite/backup_restore/backup_sqlite.py b/python/fledge/plugins/storage/sqlite/backup_restore/backup_sqlite.py index 5d83f16621..aca8d0864a 100644 --- a/python/fledge/plugins/storage/sqlite/backup_restore/backup_sqlite.py +++ b/python/fledge/plugins/storage/sqlite/backup_restore/backup_sqlite.py @@ -162,7 +162,6 @@ def init(self): Raises: exceptions.BackupOrRestoreAlreadyRunning """ - self._logger.debug("{func}".format(func="init")) self._backup_lib.evaluate_paths() @@ -391,38 +390,31 @@ def run(self): print("[FLEDGE] {0} - ERROR - {1}".format(current_time, message), file=sys.stderr) sys.exit(1) - # Starts - _logger.info(_MESSAGES_LIST["i000001"]) - # Initializes FledgeProcess and Backup classes - handling the command line parameters try: backup_process = BackupProcess() - except Exception as ex: message = _MESSAGES_LIST["e000004"].format(ex) _logger.exception(message) - - _logger.info(_MESSAGES_LIST["i000002"]) sys.exit(1) - # Executes the backup - try: - # noinspection PyProtectedMember - _logger.debug("{module} - name |{name}| - address |{addr}| - port |{port}|".format( - module=_MODULE_NAME, - name=backup_process._name, - addr=backup_process._core_management_host, - port=backup_process._core_management_port)) - - backup_process.run() - - _logger.info(_MESSAGES_LIST["i000002"]) - sys.exit(0) - - except Exception as ex: - message = _MESSAGES_LIST["e000002"].format(ex) - _logger.exception(message) - - backup_process.shutdown() - _logger.info(_MESSAGES_LIST["i000002"]) - sys.exit(1) + if not backup_process.is_dry_run(): + try: + # noinspection PyProtectedMember + _logger.debug("{module} - name |{name}| - address |{addr}| - port |{port}|".format( + module=_MODULE_NAME, + name=backup_process._name, + addr=backup_process._core_management_host, + port=backup_process._core_management_port)) + _logger.info(_MESSAGES_LIST["i000001"]) + backup_process.run() + _logger.info(_MESSAGES_LIST["i000002"]) + sys.exit(0) + except Exception as ex: + message = _MESSAGES_LIST["e000002"].format(ex) + _logger.exception(message) + backup_process.shutdown() + sys.exit(1) + else: + # Put any configuration here if required for the backup + sys.exit() diff --git a/python/fledge/plugins/storage/sqlite/backup_restore/restore_sqlite.py b/python/fledge/plugins/storage/sqlite/backup_restore/restore_sqlite.py index 75e7f66620..d35fa1acdc 100644 --- a/python/fledge/plugins/storage/sqlite/backup_restore/restore_sqlite.py +++ b/python/fledge/plugins/storage/sqlite/backup_restore/restore_sqlite.py @@ -898,7 +898,6 @@ def init(self): Returns: Raises: """ - # Setups signals handlers, to avoid the termination of the restore # a) SIGINT: Keyboard interrupt # b) SIGTERM: kill or system shutdown @@ -982,40 +981,33 @@ def run(self): print("[FLEDGE] {0} - ERROR - {1}".format(current_time, message), file=sys.stderr) sys.exit(1) - # Starts - _logger.info(_MESSAGES_LIST["i000001"]) - # Initializes FledgeProcess and RestoreProcess classes - handling also the command line parameters try: restore_process = RestoreProcess() - except Exception as ex: message = _MESSAGES_LIST["e000004"].format(ex) _logger.exception(message) - - _logger.info(_MESSAGES_LIST["i000002"]) sys.exit(1) - # Executes the Restore - try: - # noinspection PyProtectedMember - _logger.debug("{module} - name |{name}| - address |{addr}| - port |{port}| " - "- file |{file}| - backup_id |{backup_id}| ".format( - module=_MODULE_NAME, - name=restore_process._name, - addr=restore_process._core_management_host, - port=restore_process._core_management_port, - file=restore_process._file_name, - backup_id=restore_process._backup_id)) - - restore_process.run() - - _logger.info(_MESSAGES_LIST["i000002"]) - sys.exit(0) - - except Exception as ex: - message = _MESSAGES_LIST["e000002"].format(ex) - _logger.exception(message) - - _logger.info(_MESSAGES_LIST["i000002"]) - sys.exit(1) + if not restore_process.is_dry_run(): + try: + # noinspection PyProtectedMember + _logger.debug("{module} - name |{name}| - address |{addr}| - port |{port}| " + "- file |{file}| - backup_id |{backup_id}| ".format( + module=_MODULE_NAME, + name=restore_process._name, + addr=restore_process._core_management_host, + port=restore_process._core_management_port, + file=restore_process._file_name, + backup_id=restore_process._backup_id)) + _logger.info(_MESSAGES_LIST["i000001"]) + restore_process.run() + _logger.info(_MESSAGES_LIST["i000002"]) + sys.exit(0) + except Exception as ex: + message = _MESSAGES_LIST["e000002"].format(ex) + _logger.exception(message) + sys.exit(1) + else: + # Put any configuration here if required for the restore + sys.exit() diff --git a/python/fledge/services/core/server.py b/python/fledge/services/core/server.py index 3961063b58..618b298c53 100755 --- a/python/fledge/services/core/server.py +++ b/python/fledge/services/core/server.py @@ -895,7 +895,23 @@ def _start_core(cls, loop=None): "Therefore, starting the service...") loop.run_until_complete(cls.add_and_enable_dispatcher()) _logger.info("Dispatcher service started.") - + # dryrun execution of all the tasks that are installed but have schedule type other than STARTUP + schedule_list = loop.run_until_complete(cls.scheduler.get_schedules()) + for sch in schedule_list: + # STARTUP type exclusion + if int(sch.schedule_type) != 1: + schedule_row = cls.scheduler._ScheduleRow( + id=sch.schedule_id, + name=sch.name, + type=sch.schedule_type, + time=(sch.time.hour * 60 * 60 + sch.time.minute * 60 + sch.time.second) if sch.time else 0, + day=sch.day, + repeat=sch.repeat, + repeat_seconds=sch.repeat.total_seconds() if sch.repeat else 0, + exclusive=sch.exclusive, + enabled=sch.enabled, + process_name=sch.process_name) + loop.run_until_complete(cls.scheduler._start_task(schedule_row, dryrun=True)) # Everything is complete in the startup sequence, write the audit log entry cls._audit = AuditLogger(cls._storage_client_async) audit_msg = {"message": "Running in safe mode"} if cls.running_in_safe_mode else None diff --git a/python/fledge/tasks/automation_script/__main__.py b/python/fledge/tasks/automation_script/__main__.py index 8682c6b647..3d6b35c35b 100755 --- a/python/fledge/tasks/automation_script/__main__.py +++ b/python/fledge/tasks/automation_script/__main__.py @@ -7,6 +7,7 @@ """Automation script starter""" +import sys import logging import json import http.client @@ -30,6 +31,12 @@ script_name = getattr(namespace, 'name') core_management_host = getattr(namespace, 'address') core_management_port = getattr(namespace, 'port') + + if '--dryrun' in args: + # Put any configuration setting here + # if --dryrun option exists in args then simply exit. You can't return because you're not in a function + sys.exit() + # Get services list get_svc_conn = http.client.HTTPConnection("{}:{}".format(core_management_host, core_management_port)) get_svc_conn.request("GET", '/fledge/service') diff --git a/python/fledge/tasks/north/sending_process.py b/python/fledge/tasks/north/sending_process.py index eaa29a721e..e49fbb3ac7 100644 --- a/python/fledge/tasks/north/sending_process.py +++ b/python/fledge/tasks/north/sending_process.py @@ -924,7 +924,6 @@ async def _start(self): cat_keep_original=True) exec_sending_process = self._config['enable'] - if self._config['enable']: # Checks if the plug is defined if not end the execution @@ -976,6 +975,11 @@ async def run(self): global _log_performance global _LOGGER + # Return early if task runs with --dryrun arg + # In future if any runtime configuration required for a task then it should be created before it + if self.is_dry_run(): + return + # Setups signals handlers, to properly handle the termination # a) SIGTERM - 15 : kill or system shutdown signal.signal(signal.SIGTERM, SendingProcess._signal_handler) diff --git a/python/fledge/tasks/purge/purge.py b/python/fledge/tasks/purge/purge.py index fa4833469c..91ef7ca5f1 100644 --- a/python/fledge/tasks/purge/purge.py +++ b/python/fledge/tasks/purge/purge.py @@ -265,6 +265,8 @@ async def run(self): """ try: config = await self.set_configuration() + if self.is_dry_run(): + return total_purged, unsent_purged = await self.purge_data(config) await self.write_statistics(total_purged, unsent_purged) await self.purge_stats_history(config) diff --git a/python/fledge/tasks/statistics/statistics_history.py b/python/fledge/tasks/statistics/statistics_history.py index 40163209aa..db19f64407 100644 --- a/python/fledge/tasks/statistics/statistics_history.py +++ b/python/fledge/tasks/statistics/statistics_history.py @@ -48,6 +48,8 @@ async def run(self): 1. INSERT the delta between `value` and `previous_value` into statistics_history 2. UPDATE the previous_value in statistics table to be equal to statistics.value at snapshot """ + if self.is_dry_run(): + return current_time = common_utils.local_timestamp() results = await self._storage_async.query_tbl("statistics") # Bulk updates payload diff --git a/tests/system/python/api/test_audit.py b/tests/system/python/api/test_audit.py index 126e8d32c1..9d92cfff90 100644 --- a/tests/system/python/api/test_audit.py +++ b/tests/system/python/api/test_audit.py @@ -55,16 +55,16 @@ def test_get_severity(self, fledge_url): assert Counter([0, 1, 2, 4]) == Counter(index) @pytest.mark.parametrize("request_params, total_count, audit_count", [ - ('', 11, 11), - ('?limit=1', 11, 1), - ('?skip=4', 11, 7), - ('?limit=1&skip=8', 11, 1), + ('', 13, 13), + ('?limit=1', 13, 1), + ('?skip=4', 13, 9), + ('?limit=1&skip=8', 13, 1), ('?source=START', 1, 1), - ('?source=CONAD', 10, 10), - ('?source=CONAD&limit=1', 10, 1), - ('?source=CONAD&skip=1', 10, 9), - ('?source=CONAD&skip=6&limit=1', 10, 1), - ('?severity=INFORMATION', 11, 11), + ('?source=CONAD', 12, 12), + ('?source=CONAD&limit=1', 12, 1), + ('?source=CONAD&skip=1', 12, 11), + ('?source=CONAD&skip=6&limit=1', 12, 1), + ('?severity=INFORMATION', 13, 13), ('?severity=failure', 0, 0), ('?source=CONAD&severity=failure', 0, 0), ('?source=START&severity=INFORMATION', 1, 1), @@ -88,10 +88,10 @@ def test_default_get_audit(self, fledge_url, wait_time, request_params, total_co assert audit_count == len(elems) @pytest.mark.parametrize("payload, total_count", [ - ({"source": "LOGGN", "severity": "warning", "details": {"message": "Engine oil pressure low"}}, 12), - ({"source": "NHCOM", "severity": "success", "details": {}}, 13), - ({"source": "START", "severity": "information", "details": {"message": "fledge started"}}, 14), - ({"source": "CONCH", "severity": "failure", "details": {"message": "Scheduler configuration failed"}}, 15) + ({"source": "LOGGN", "severity": "warning", "details": {"message": "Engine oil pressure low"}}, 14), + ({"source": "NHCOM", "severity": "success", "details": {}}, 15), + ({"source": "START", "severity": "information", "details": {"message": "fledge started"}}, 16), + ({"source": "CONCH", "severity": "failure", "details": {"message": "Scheduler configuration failed"}}, 17) ]) def test_create_audit_entry(self, fledge_url, payload, total_count): conn = http.client.HTTPConnection(fledge_url) diff --git a/tests/system/python/api/test_configuration.py b/tests/system/python/api/test_configuration.py index 17b2753518..1d7b797ef6 100644 --- a/tests/system/python/api/test_configuration.py +++ b/tests/system/python/api/test_configuration.py @@ -122,7 +122,20 @@ def test_default(self, fledge_url, reset_and_start_fledge, wait_time, storage_pl 'key': 'Utilities', 'description': 'Utilities', 'displayName': 'Utilities', - 'children': [] + 'children': [ + { + 'key': 'purge_system', + 'description': 'Configuration of the Purge System', + 'displayName': 'Purge System', + 'children': [] + }, + { + 'key': 'PURGE_READ', + 'description': 'Purge the readings, log, statistics history table', + 'displayName': 'Purge', + 'children': [] + } + ] } ] From 9703eba51e3f4c14c410db544bc639e23ad4d328 Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Tue, 27 Sep 2022 16:03:37 +0530 Subject: [PATCH 21/48] malformed table & untitled short fixes in rest api developer guide documentation Signed-off-by: ashish-jabble --- docs/rest_api_guide/03_RESTservices.rst | 42 +++++++++++----------- docs/rest_api_guide/06_GrafanaExamples.rst | 2 +- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/docs/rest_api_guide/03_RESTservices.rst b/docs/rest_api_guide/03_RESTservices.rst index 57888f5e34..586d9ea3fd 100644 --- a/docs/rest_api_guide/03_RESTservices.rst +++ b/docs/rest_api_guide/03_RESTservices.rst @@ -83,28 +83,26 @@ In order to discover the services registered within a Fledge instance and what s The data returned for each service includes -+-----------------+-----------------------------------------------------------------------------+ -| Key | Description | -+=================+=============================================================================+ -| name | The name of the service | -+-----------------+-----------------------------------------------------------------------------+ -| type | The service type. This may be one of Northbound, Southbound, Core, Storage, | -| | Notification or Dispatcher. In addition other storage types may also be | -| | installed to extend the functionality of Fledge. | -+-----------------+-----------------------------------------------------------------------------+ -| address | The Address the service can be contacted via. Normally localhost or 0.0.0.0 | -| | if the service is running on the same machine as the Core service of the | -| | Fledge instance. | -+-----------------+-----------------------------------------------------------------------------+ -| management_port | The management port the service is using to communicate with the core. | -+-----------------+-----------------------------------------------------------------------------+ -| service_port | The port the service is using to expose the service API of the service. | -+-----------------+-----------------------------------------------------------------------------+ -| protocol | The protocol the service is using for its control API. | -+-----------------+-----------------------------------------------------------------------------+ -| status | The status of the service. This may be running, shutdown, unresponsive or | -| | failed. | -+-----------------+-----------------------------------------------------------------------------+ +.. list-table:: + :widths: 20 50 + :header-rows: 1 + + * - Key + - Description + * - name + - The name of the service. + * - type + - The service type. This may be one of Northbound, Southbound, Core, Storage, Notification or Dispatcher. In addition other storage types may also be installed to extend the functionality of Fledge. + * - address + - The Address the service can be contacted via. Normally localhost or 0.0.0.0 if the service is running on the same machine as the Core service of the Fledge instance. + * - management_port + - The management port the service is using to communicate with the core. + * - service_port + - The port the service is using to expose the service API of the service. + * - protocol + - The protocol the service is using for its control API. + * - status + - The status of the service. This may be running, shutdown, unresponsive or failed. Parameters ~~~~~~~~~~ diff --git a/docs/rest_api_guide/06_GrafanaExamples.rst b/docs/rest_api_guide/06_GrafanaExamples.rst index 4eee69af59..dc933ed7c0 100644 --- a/docs/rest_api_guide/06_GrafanaExamples.rst +++ b/docs/rest_api_guide/06_GrafanaExamples.rst @@ -17,7 +17,7 @@ Grafana Examples The REST API of Fledge provides a way to integrate other applications with Fledge, these applications can control Fledge or that may be used to monitor the operation of Fledge itself or to visualize the data held within a Fledge instance. One such tool is |grafana|. Here we will show some simple examples of how the Fledge REST API can be used with Grafana and the Infinity data source plugin. This is intended to be a simple example, more complex systems can be built using these tools. Show Fledge Status ------------------- +------------------- Using the *GET /fledge/ping* endpoint we can retrieve information about the number of readings read, sent, purged etc. From f9a696659515553078c41621d96f9a242c6d4a94 Mon Sep 17 00:00:00 2001 From: Amandeep Singh Arora Date: Thu, 29 Sep 2022 15:38:42 +0530 Subject: [PATCH 22/48] FOGL-6945: Command line option to change parallel make jobs setting was not working correctly; fixed the same Signed-off-by: Amandeep Singh Arora --- tests/unit/C/scripts/RunAllTests.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit/C/scripts/RunAllTests.sh b/tests/unit/C/scripts/RunAllTests.sh index c23f999147..572b8eb484 100755 --- a/tests/unit/C/scripts/RunAllTests.sh +++ b/tests/unit/C/scripts/RunAllTests.sh @@ -1,12 +1,13 @@ -#!/bin/sh +#!/usr/bin/env bash #set -e # # This is the shell script wrapper for running C unit tests # jobs="-j4" -if [ "$1" = "-j*" ]; then +if [[ "$1" == -j* ]]; then jobs="$1" fi +# echo "Using $jobs option for parallel make jobs" COVERAGE_HTML=0 COVERAGE_XML=0 From a55226107576578f4108a286502251662bcff714 Mon Sep 17 00:00:00 2001 From: Amandeep Singh Arora Date: Thu, 29 Sep 2022 18:13:29 +0530 Subject: [PATCH 23/48] Acquire and release GIL for calls to python library Signed-off-by: Amandeep Singh Arora --- tests/unit/C/common/test_python_reading.cpp | 46 +++++++++++++++++++ .../unit/C/common/test_python_reading_set.cpp | 4 ++ .../C/common/test_python_readingnumpy.cpp | 4 ++ 3 files changed, 54 insertions(+) diff --git a/tests/unit/C/common/test_python_reading.cpp b/tests/unit/C/common/test_python_reading.cpp index cd977b84e3..48f785f36c 100644 --- a/tests/unit/C/common/test_python_reading.cpp +++ b/tests/unit/C/common/test_python_reading.cpp @@ -158,9 +158,11 @@ TEST_F(PythonReadingTest, SimpleSizeLong) long i = 1234; DatapointValue value(i); Reading reading("test", new Datapoint("long", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *obj = callPythonFunc("count", pyReading); long rval = PyLong_AsLong(obj); + PyGILState_Release(state); EXPECT_EQ(rval, 1); } @@ -169,8 +171,10 @@ TEST_F(PythonReadingTest, IsDict) long i = 1234; DatapointValue value(i); Reading reading("test", new Datapoint("long", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); EXPECT_EQ(PyDict_Check(pyReading), true); + PyGILState_Release(state); } TEST_F(PythonReadingTest, PyIsDict) @@ -178,6 +182,7 @@ TEST_F(PythonReadingTest, PyIsDict) long i = 1234; DatapointValue value(i); Reading reading("test", new Datapoint("long", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); EXPECT_EQ(PyDict_Check(pyReading), true); PyObject *obj = callPythonFunc("isDict", pyReading); @@ -188,6 +193,7 @@ TEST_F(PythonReadingTest, PyIsDict) } else EXPECT_STREQ("Expected object to be returned", ""); + PyGILState_Release(state); } TEST_F(PythonReadingTest, Py2IsDict) @@ -195,6 +201,7 @@ TEST_F(PythonReadingTest, Py2IsDict) long i = 1234; DatapointValue value(i); Reading reading("test", new Datapoint("long", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); EXPECT_EQ(PyDict_Check(pyReading), true); PyObject *obj = callPythonFunc("returnIt", pyReading); @@ -204,6 +211,7 @@ TEST_F(PythonReadingTest, Py2IsDict) } else EXPECT_EQ(true, false); + PyGILState_Release(state); } TEST_F(PythonReadingTest, SimpleLong) @@ -211,6 +219,7 @@ TEST_F(PythonReadingTest, SimpleLong) long i = 1234; DatapointValue value(i); Reading reading("test", new Datapoint("long", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); EXPECT_EQ(PyDict_Check(pyReading), true); PyObject *element = PyUnicode_FromString("long"); @@ -218,6 +227,7 @@ TEST_F(PythonReadingTest, SimpleLong) EXPECT_EQ(PyLong_Check(obj), true); long rval = PyLong_AsLong(obj); EXPECT_EQ(rval, 1234); + PyGILState_Release(state); } TEST_F(PythonReadingTest, SimpleDouble) @@ -225,6 +235,7 @@ TEST_F(PythonReadingTest, SimpleDouble) double i = 1234.5; DatapointValue value(i); Reading reading("test", new Datapoint("double", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); EXPECT_EQ(PyDict_Check(pyReading), true); PyObject *element = PyUnicode_FromString("double"); @@ -232,6 +243,7 @@ TEST_F(PythonReadingTest, SimpleDouble) EXPECT_EQ(PyFloat_Check(obj), true); double rval = PyFloat_AS_DOUBLE(obj); EXPECT_EQ(rval, 1234.5); + PyGILState_Release(state); } TEST_F(PythonReadingTest, DictCheck) @@ -239,24 +251,29 @@ TEST_F(PythonReadingTest, DictCheck) long i = 1234; DatapointValue value(i); Reading reading("test", new Datapoint("long", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); EXPECT_EQ(PyDict_Check(pyReading), true); + PyGILState_Release(state); } TEST_F(PythonReadingTest, SimpleSizeString) { DatapointValue value("just a string"); Reading reading("test", new Datapoint("str", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *obj = callPythonFunc("count", pyReading); long rval = PyLong_AsLong(obj); EXPECT_EQ(rval, 1); + PyGILState_Release(state); } TEST_F(PythonReadingTest, SimpleString) { DatapointValue value("just a string"); Reading reading("test", new Datapoint("str", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("str"); PyObject *obj = callPythonFunc2("element", pyReading, element); @@ -270,12 +287,14 @@ TEST_F(PythonReadingTest, SimpleString) { EXPECT_STREQ("Expected a string object", ""); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, AssetCode) { DatapointValue value("just a string"); Reading reading("testAsset", new Datapoint("str", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *obj = callPythonFunc("assetCode", pyReading); if (obj) @@ -288,6 +307,7 @@ TEST_F(PythonReadingTest, AssetCode) { EXPECT_STREQ("Expected a string object", ""); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, TwoDataPoints) @@ -297,9 +317,11 @@ TEST_F(PythonReadingTest, TwoDataPoints) values.push_back(new Datapoint("s1", value)); values.push_back(new Datapoint("s2", value)); Reading reading("test", values); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *obj = callPythonFunc("count", pyReading); long rval = PyLong_AsLong(obj); + PyGILState_Release(state); EXPECT_EQ(rval, 2); } @@ -311,6 +333,7 @@ TEST_F(PythonReadingTest, TwoDifferentDataPoints) values.push_back(new Datapoint("s", v1)); values.push_back(new Datapoint("l", v2)); Reading reading("test", values); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *obj = callPythonFunc("count", pyReading); long rval = PyLong_AsLong(obj); @@ -323,6 +346,7 @@ TEST_F(PythonReadingTest, TwoDifferentDataPoints) element = PyUnicode_FromString("l"); obj = callPythonFunc2("element", pyReading, element); rval = PyLong_AsLong(obj); + PyGILState_Release(state); EXPECT_EQ(rval, 12345678); } @@ -333,6 +357,7 @@ TEST_F(PythonReadingTest, TwoDataPointsFetchString1) values.push_back(new Datapoint("s1", value)); values.push_back(new Datapoint("s2", value)); Reading reading("test", values); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("s1"); PyObject *obj = callPythonFunc2("element", pyReading, element); @@ -346,6 +371,7 @@ TEST_F(PythonReadingTest, TwoDataPointsFetchString1) { EXPECT_STREQ("Expected a string object", ""); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, TwoDataPointsFetchString2) @@ -355,6 +381,7 @@ TEST_F(PythonReadingTest, TwoDataPointsFetchString2) values.push_back(new Datapoint("s1", value)); values.push_back(new Datapoint("s2", value)); Reading reading("test", values); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("s2"); PyObject *obj = callPythonFunc2("element", pyReading, element); @@ -368,6 +395,7 @@ TEST_F(PythonReadingTest, TwoDataPointsFetchString2) { EXPECT_STREQ("Expected a string object", ""); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, DoubleListDataPoint) @@ -377,6 +405,7 @@ TEST_F(PythonReadingTest, DoubleListDataPoint) values.push_back(3.7); DatapointValue value(values); Reading reading("test", new Datapoint("array", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("array"); PyObject *obj = callPythonFunc2("element", pyReading, element); @@ -388,6 +417,7 @@ TEST_F(PythonReadingTest, DoubleListDataPoint) { EXPECT_STREQ("Expected a LIST object", ""); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, DictDataPoint) @@ -398,6 +428,7 @@ TEST_F(PythonReadingTest, DictDataPoint) values->push_back(new Datapoint("s2", value)); DatapointValue dict(values, true); Reading reading("test", new Datapoint("child", dict)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("child"); PyObject *obj = callPythonFunc2("element", pyReading, element); @@ -409,6 +440,7 @@ TEST_F(PythonReadingTest, DictDataPoint) { EXPECT_STREQ("Expected a DICT object", ""); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, DataBuffer) @@ -419,6 +451,7 @@ TEST_F(PythonReadingTest, DataBuffer) *(ptr + 1) = 5678; DatapointValue buf(buffer); Reading reading("test", new Datapoint("buffer", buf)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("buffer"); PyObject *obj = callPythonFunc2("element", pyReading, element); @@ -439,6 +472,7 @@ TEST_F(PythonReadingTest, DataBuffer) { EXPECT_STREQ("Expected a long object", ""); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, SimpleLongRoundTrip) @@ -446,6 +480,7 @@ TEST_F(PythonReadingTest, SimpleLongRoundTrip) long i = 1234; DatapointValue value(i); Reading reading("test", new Datapoint("long", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); EXPECT_EQ(PyDict_Check(pyReading), true); PyObject *obj = callPythonFunc("returnIt", pyReading); @@ -469,12 +504,14 @@ TEST_F(PythonReadingTest, SimpleLongRoundTrip) { EXPECT_STREQ("Expect PythonReading object missing", ""); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, SimpleStringRoundTrip) { DatapointValue value("this is a string"); Reading reading("test", new Datapoint("str", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); EXPECT_EQ(PyDict_Check(pyReading), true); PyObject *obj = callPythonFunc("returnIt", pyReading); @@ -499,6 +536,7 @@ TEST_F(PythonReadingTest, SimpleStringRoundTrip) { EXPECT_STREQ("Expect PythonReading object missing", ""); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, DataBufferSwapRoundTrip) @@ -509,6 +547,7 @@ TEST_F(PythonReadingTest, DataBufferSwapRoundTrip) *(ptr + 1) = 5678; DatapointValue buf(buffer); Reading reading("test", new Datapoint("buffer", buf)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("buffer"); PyObject *obj = callPythonFunc2("array_swap", pyReading, element); @@ -529,6 +568,7 @@ TEST_F(PythonReadingTest, DataBufferSwapRoundTrip) EXPECT_EQ(*ptr, 5678); EXPECT_EQ(*(ptr + 1), 1234); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, ImageRoundTrip) @@ -537,6 +577,7 @@ TEST_F(PythonReadingTest, ImageRoundTrip) DPImage *image = new DPImage(64, 96, 8, data); DatapointValue img(image); Reading reading("test", new Datapoint("image", img)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("image"); PyObject *obj = callPythonFunc2("image_swap", pyReading, element); @@ -557,6 +598,7 @@ TEST_F(PythonReadingTest, ImageRoundTrip) EXPECT_EQ(image2->getHeight(), image->getHeight()); EXPECT_EQ(image2->getDepth(), image->getDepth()); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, UpdateAssetCode) @@ -564,6 +606,7 @@ TEST_F(PythonReadingTest, UpdateAssetCode) long i = 1234; DatapointValue value(i); Reading reading("test", new Datapoint("long", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); EXPECT_EQ(PyDict_Check(pyReading), true); PyObject *newName = PyUnicode_FromString("shorter"); @@ -588,6 +631,7 @@ TEST_F(PythonReadingTest, UpdateAssetCode) { EXPECT_STREQ("Expect PythonReading object missing", ""); } + PyGILState_Release(state); } TEST_F(PythonReadingTest, Double2DArray) @@ -603,6 +647,7 @@ TEST_F(PythonReadingTest, Double2DArray) DatapointValue value(array); Reading reading("test2d", new Datapoint("array", value)); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("array"); PyObject *obj = callPythonFunc2("row_swap", pyReading, element); @@ -624,6 +669,7 @@ TEST_F(PythonReadingTest, Double2DArray) { EXPECT_STREQ("Expected a LIST object", ""); } + PyGILState_Release(state); } }; diff --git a/tests/unit/C/common/test_python_reading_set.cpp b/tests/unit/C/common/test_python_reading_set.cpp index 3f94f04a6e..545dc1c014 100644 --- a/tests/unit/C/common/test_python_reading_set.cpp +++ b/tests/unit/C/common/test_python_reading_set.cpp @@ -117,9 +117,11 @@ TEST_F(PythonReadingSetTest, SingleReading) DatapointValue value(i); readings->push_back(new Reading("test", new Datapoint("long", value))); ReadingSet set(readings); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pySet = ((PythonReadingSet *)(&set))->toPython(); PyObject *obj = callPythonFunc("count", pySet); long rval = PyLong_AsLong(obj); + PyGILState_Release(state); EXPECT_EQ(rval, 1); } @@ -132,9 +134,11 @@ TEST_F(PythonReadingSetTest, MultipleReadings) readings->push_back(new Reading("test", new Datapoint("long", value))); readings->push_back(new Reading("test", new Datapoint("long", value))); ReadingSet set(readings); + PyGILState_STATE state = PyGILState_Ensure(); PyObject *pySet = ((PythonReadingSet *)(&set))->toPython(); PyObject *obj = callPythonFunc("count", pySet); long rval = PyLong_AsLong(obj); + PyGILState_Release(state); EXPECT_EQ(rval, 3); } } diff --git a/tests/unit/C/common/test_python_readingnumpy.cpp b/tests/unit/C/common/test_python_readingnumpy.cpp index 7550e1a2a5..4b1aae1b4d 100644 --- a/tests/unit/C/common/test_python_readingnumpy.cpp +++ b/tests/unit/C/common/test_python_readingnumpy.cpp @@ -136,10 +136,12 @@ TEST_F(PythonReadingNumpyTest, ArraySort) *(ptr + 4) = 1; DatapointValue buf(buffer); Reading reading("test", new Datapoint("buffer", buf)); + PyGILState_STATE state = PyGILState_Ensure(); // Take GIL PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("buffer"); PyObject *obj = callPythonFunc2("array_sort", pyReading, element); PythonReading pyr(obj); + PyGILState_Release(state); EXPECT_STREQ(pyr.getAssetName().c_str(), "test"); EXPECT_EQ(pyr.getDatapointCount(), 1); Datapoint *dp = pyr.getDatapoint("buffer"); @@ -171,11 +173,13 @@ TEST_F(PythonReadingNumpyTest, ImageFloat) DPImage *image = new DPImage(64, 96, 8, data); DatapointValue img(image); Reading reading("test", new Datapoint("image", img)); + PyGILState_STATE state = PyGILState_Ensure(); // Take GIL PyObject *pyReading = ((PythonReading *)(&reading))->toPython(); PyObject *element = PyUnicode_FromString("image"); PyObject *obj = callPythonFunc2("image_normalise", pyReading, element); EXPECT_NE(obj, (PyObject *)NULL); PythonReading pyr(obj); + PyGILState_Release(state); // Release GIL EXPECT_STREQ(pyr.getAssetName().c_str(), "test"); EXPECT_EQ(pyr.getDatapointCount(), 1); Datapoint *dp = pyr.getDatapoint("image"); From bc3e5e17b9cb558ab36184630043000a79b6d61f Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Thu, 29 Sep 2022 13:44:45 +0100 Subject: [PATCH 24/48] FOGL-6950 Add option to senbd audit log table north (#835) Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/services/north/data_load.cpp | 6 +-- .../north/sending_process/sending_process.cpp | 43 +++++++++++++++++-- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/C/services/north/data_load.cpp b/C/services/north/data_load.cpp index 073edc568f..6a2d9d9d87 100755 --- a/C/services/north/data_load.cpp +++ b/C/services/north/data_load.cpp @@ -253,7 +253,7 @@ ReadingSet *DataLoad::fetchAudit(unsigned int blockSize) tmpReturn->timezone("utc"); columns.push_back(tmpReturn); - columns.push_back(new Returns("log")); + columns.push_back(new Returns("log", "reading")); // Build the query with fields, aliases and where Query qStatistics(columns, wId); // Set limit @@ -262,8 +262,8 @@ ReadingSet *DataLoad::fetchAudit(unsigned int blockSize) Sort* sort = new Sort("id"); qStatistics.sort(sort); - // Query the statistics_history table and get a ReadingSet result - return m_storage->queryTableToReadings("statistics_history", qStatistics); + // Query the audit table and get a ReadingSet result + return m_storage->queryTableToReadings("log", qStatistics); } /** diff --git a/C/tasks/north/sending_process/sending_process.cpp b/C/tasks/north/sending_process/sending_process.cpp index c201cb827d..6ef59e8efb 100644 --- a/C/tasks/north/sending_process/sending_process.cpp +++ b/C/tasks/north/sending_process/sending_process.cpp @@ -187,16 +187,16 @@ static void loadDataThread(SendingProcess *loadData) ReadingSet* readings = NULL; try { - bool isReading = !loadData->getDataSourceType().compare("statistics") ? false : true; + string source = loadData->getDataSourceType(); //high_resolution_clock::time_point t1 = high_resolution_clock::now(); - if (isReading) + if (source.compare("readings") == 0) { // Read from storage all readings with id > last sent id unsigned long lastReadId = loadData->getLastFetchId() + 1; readings = loadData->getStorageClient()->readingFetch(lastReadId, loadData->getReadBlockSize()); } - else + else if (source.compare("statistics") == 0) { // SELECT id, // key AS asset_code, @@ -231,10 +231,45 @@ static void loadDataThread(SendingProcess *loadData) Sort* sort = new Sort("id"); qStatistics.sort(sort); - // Query the statistics_history tbale and get a ReadingSet result + // Query the statistics_history table and get a ReadingSet result readings = loadData->getStorageClient()->queryTableToReadings("statistics_history", qStatistics); } + else if (source.compare("audit") == 0) + { + const Condition conditionId(GreaterThan); + // WHERE id > lastId + Where* wId = new Where("id", + conditionId, + to_string(loadData->getLastFetchId())); + vector columns; + // Add colums and needed aliases + columns.push_back(new Returns("id")); + columns.push_back(new Returns("code", "asset_code")); + columns.push_back(new Returns("ts")); + + Returns *tmpReturn = new Returns("ts", "user_ts"); + tmpReturn->timezone("utc"); + columns.push_back(tmpReturn); + + columns.push_back(new Returns("log", "reading")); + // Build the query with fields, aliases and where + Query qLog(columns, wId); + // Set limit + qLog.limit(loadData->getReadBlockSize()); + // Set sort + Sort* sort = new Sort("id"); + qLog.sort(sort); + + // Query the log table and get a ReadingSet result + readings = loadData->getStorageClient()->queryTableToReadings("log", + qLog); + } + else + { + Logger::getLogger()->error("Unsupported source '%s' for north task.", + source.c_str()); + } //high_resolution_clock::time_point t2 = high_resolution_clock::now(); //auto duration = duration_cast( t2 - t1 ).count(); } From 01eaccfe34a50742a752e58755254af4a3df0d02 Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Fri, 30 Sep 2022 12:09:14 +0530 Subject: [PATCH 25/48] exclusion list fixes in documentation scripts Signed-off-by: ashish-jabble --- docs/scripts/fledge_plugin_list | 3 ++- docs/scripts/plugin_and_service_documentation | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/scripts/fledge_plugin_list b/docs/scripts/fledge_plugin_list index ed5969ee73..2bcf967b98 100755 --- a/docs/scripts/fledge_plugin_list +++ b/docs/scripts/fledge_plugin_list @@ -59,7 +59,8 @@ fetchFledgeReposPyScript=' import os,json,sys;\ repos=json.load(sys.stdin);\ exclude_topic_packages=os.environ["EXCLUDE_FLEDGE_TOPIC_REPOSITORIES"];\ -fRepos = [r["name"] for r in repos if r["name"] not in exclude_topic_packages];\ +all_repos = [r["name"] for r in repos if r["archived"] is False];\ +fRepos = list(set(all_repos) - set(exclude_topic_packages.split()));\ print("\n".join(fRepos)); ' REPOSITORIES=$(echo ${fledgeRepos} | python3 -c "$fetchFledgeReposPyScript" | sort -f) diff --git a/docs/scripts/plugin_and_service_documentation b/docs/scripts/plugin_and_service_documentation index 2699dd4989..0b9241fbda 100644 --- a/docs/scripts/plugin_and_service_documentation +++ b/docs/scripts/plugin_and_service_documentation @@ -138,7 +138,8 @@ fetchFledgeReposPyScript=' import os,json,sys;\ repos=json.load(sys.stdin);\ exclude_topic_packages=os.environ["EXCLUDE_FLEDGE_TOPIC_REPOSITORIES"];\ -fRepos = [r["name"] for r in repos if r["name"] not in exclude_topic_packages];\ +all_repos = [r["name"] for r in repos if r["archived"] is False];\ +fRepos = list(set(all_repos) - set(exclude_topic_packages.split()));\ print("\n".join(fRepos)); ' REPOSITORIES=$(echo ${fledgeRepos} | python3 -c "$fetchFledgeReposPyScript" | sort -f) From c00260c20e743cbfe54d01650b127cd56e205b5b Mon Sep 17 00:00:00 2001 From: YashTatkondawar Date: Fri, 30 Sep 2022 07:44:49 -0500 Subject: [PATCH 26/48] Fix the test to upload a script when python35 filter is used (#841) --- tests/system/python/packages/test_filters.py | 39 +++++++------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/tests/system/python/packages/test_filters.py b/tests/system/python/packages/test_filters.py index b3d31f1786..ec8aab58bb 100644 --- a/tests/system/python/packages/test_filters.py +++ b/tests/system/python/packages/test_filters.py @@ -127,17 +127,6 @@ def test_filter_python35_with_uploaded_script(self, clean_setup_fledge_packages, generate_json(ASSET_NAME_PY35) - call_fogbench(wait_time) - - ping_response = verify_ping(fledge_url) - assert 10 == ping_response["dataRead"] - - asset_response = verify_asset(fledge_url, ASSET_NAME_PY35) - assert 10 == asset_response["count"] - - reading_resp = verify_readings(fledge_url, ASSET_NAME_PY35) - assert 12.25 == reading_resp["reading"]["sensor"] - url = fledge_url + urllib.parse.quote('/fledge/category/{}_py35/script/upload' .format(HTTP_SOUTH_SVC_NAME)) script_path = 'script=@{}/readings35.py'.format(DATA_DIR_ROOT) @@ -148,10 +137,10 @@ def test_filter_python35_with_uploaded_script(self, clean_setup_fledge_packages, call_fogbench(wait_time) ping_response = verify_ping(fledge_url) - assert 20 == ping_response["dataRead"] + assert 10 == ping_response["dataRead"] asset_response = verify_asset(fledge_url, ASSET_NAME_PY35) - assert 20 == asset_response["count"] + assert 10 == asset_response["count"] reading_resp = verify_readings(fledge_url, ASSET_NAME_PY35) assert 2.45 == reading_resp["reading"]["sensor"] @@ -177,10 +166,10 @@ def test_filter_python35_with_updated_content(self, fledge_url, retries, wait_ti call_fogbench(wait_time) ping_response = verify_ping(fledge_url) - assert 30 == ping_response["dataRead"] + assert 20 == ping_response["dataRead"] asset_response = verify_asset(fledge_url, ASSET_NAME_PY35) - assert 30 == asset_response["count"] + assert 20 == asset_response["count"] reading_resp = verify_readings(fledge_url, ASSET_NAME_PY35) assert 122.5 == reading_resp["reading"]["sensor"] @@ -197,10 +186,10 @@ def test_filter_python35_disable_enable(self, fledge_url, retries, wait_time): call_fogbench(wait_time) ping_response = verify_ping(fledge_url) - assert 40 == ping_response["dataRead"] + assert 30 == ping_response["dataRead"] asset_response = verify_asset(fledge_url, ASSET_NAME_PY35) - assert 40 == asset_response["count"] + assert 30 == asset_response["count"] reading_resp = verify_readings(fledge_url, ASSET_NAME_PY35) assert 12.25 == reading_resp["reading"]["sensor"] @@ -212,10 +201,10 @@ def test_filter_python35_disable_enable(self, fledge_url, retries, wait_time): call_fogbench(wait_time) ping_response = verify_ping(fledge_url) - assert 50 == ping_response["dataRead"] + assert 40 == ping_response["dataRead"] asset_response = verify_asset(fledge_url, ASSET_NAME_PY35) - assert 50 == asset_response["count"] + assert 40 == asset_response["count"] reading_resp = verify_readings(fledge_url, ASSET_NAME_PY35) assert 122.5 == reading_resp["reading"]["sensor"] @@ -234,10 +223,10 @@ def test_filter_python35_expression(self, add_filter_expression, fledge_url, wai call_fogbench(wait_time) ping_response = verify_ping(fledge_url) - assert 60 == ping_response["dataRead"] + assert 50 == ping_response["dataRead"] asset_response = verify_asset(fledge_url, ASSET_NAME_PY35) - assert 60 == asset_response["count"] + assert 50 == asset_response["count"] reading_resp = verify_readings(fledge_url, ASSET_NAME_PY35) assert 122.5 == reading_resp["reading"]["sensor"] @@ -257,10 +246,10 @@ def test_delete_filter_python35(self, fledge_url, wait_time): call_fogbench(wait_time) ping_response = verify_ping(fledge_url) - assert 70 == ping_response["dataRead"] + assert 60 == ping_response["dataRead"] asset_response = verify_asset(fledge_url, ASSET_NAME_PY35) - assert 70 == asset_response["count"] + assert 60 == asset_response["count"] reading_resp = verify_readings(fledge_url, ASSET_NAME_PY35) assert 12.25 == reading_resp["reading"]["sensor"] @@ -302,10 +291,10 @@ def test_filter_python35_by_enabling_disabling_south(self, fledge_url, wait_time call_fogbench(wait_time) ping_response = verify_ping(fledge_url) - assert 80 == ping_response["dataRead"] + assert 70 == ping_response["dataRead"] asset_response = verify_asset(fledge_url, ASSET_NAME_PY35) - assert 80 == asset_response["count"] + assert 70 == asset_response["count"] reading_resp = verify_readings(fledge_url, ASSET_NAME_PY35) assert 2.45 == reading_resp["reading"]["sensor"] From 9cf859e83604263a4f97abaa4f71d43892fe15bc Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Fri, 30 Sep 2022 14:51:45 +0100 Subject: [PATCH 27/48] FOGL-6959 Allow for recursion in JSON objects when converting to (#840) * FOGL-6959 Allow for recursion in JSON objects when converting to readings Signed-off-by: Mark Riddoch * Add in missign image and data buffer support Signed-off-by: Mark Riddoch * Fix bad escape sequence Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/common/include/reading_set.h | 3 +- C/common/management_client.cpp | 2 +- C/common/reading_set.cpp | 366 +++++++++++++-------------------- 3 files changed, 151 insertions(+), 220 deletions(-) diff --git a/C/common/include/reading_set.h b/C/common/include/reading_set.h index 14f8ce7dc1..d38aed4407 100755 --- a/C/common/include/reading_set.h +++ b/C/common/include/reading_set.h @@ -71,7 +71,8 @@ class JSONReading : public Reading { unsigned long getId() const { return m_id; }; private: - void escapeCharacter(std::string& stringToEvaluate, std::string pattern); + Datapoint *datapoint(const std::string& name, const rapidjson::Value& json); + void escapeCharacter(std::string& stringToEvaluate, std::string pattern); }; class ReadingSetException : public std::exception diff --git a/C/common/management_client.cpp b/C/common/management_client.cpp index f719616210..e871cbd46c 100644 --- a/C/common/management_client.cpp +++ b/C/common/management_client.cpp @@ -1756,7 +1756,7 @@ bool ManagementClient::addStorageAssetTrackingTuple(const std::string& service, convert << " \"asset\" : \"" << asset << "\", "; convert << " \"event\" : \"" << event << "\", "; convert << " \"deprecated\" :\"" << deprecated << "\", "; - convert << " \"data\" : { \"datapoints\" : \[ \"" << d << "\" \], "; + convert << " \"data\" : { \"datapoints\" : \[ \"" << d << "\" ], "; convert << " \"count\" : " << count << " } }"; auto res = this->getHttpClient()->request("POST", "/fledge/track", convert.str()); diff --git a/C/common/reading_set.cpp b/C/common/reading_set.cpp index ed9a557f80..2040d145cb 100755 --- a/C/common/reading_set.cpp +++ b/C/common/reading_set.cpp @@ -325,224 +325,9 @@ JSONReading::JSONReading(const Value& json) if (json["reading"].IsObject()) { // Add 'reading' values - for (auto &m : json["reading"].GetObject()) { - switch (m.value.GetType()) { - // String - case (kStringType): { - string str = m.value.GetString(); - if (str[0] == '_' && str[1] == '_') - { - // special encoded type - size_t pos = str.find_first_of(':'); - if (str.compare(2, 10, "DATABUFFER") == 0) - { - DataBuffer *databuffer = new Base64DataBuffer(str.substr(pos + 1)); - DatapointValue value(databuffer); - this->addDatapoint(new Datapoint(m.name.GetString(), value)); - } - else if (str.compare(2, 7, "DPIMAGE") == 0) - { - DPImage *image = new Base64DPImage(str.substr(pos + 1)); - DatapointValue value(image); - this->addDatapoint(new Datapoint(m.name.GetString(), value)); - } - - } - else - { - DatapointValue value(str); - this->addDatapoint(new Datapoint(m.name.GetString(), value)); - } - break; - } - - // Number - case (kNumberType): { - if (m.value.IsInt() || - m.value.IsUint() || - m.value.IsInt64() || - m.value.IsUint64()) { - - DatapointValue *value; - if (m.value.IsInt()) { - value = new DatapointValue((long) m.value.GetInt()); - } else { - // Handle Uint as 64 bits - value = new DatapointValue((long) m.value.GetInt64()); - } - this->addDatapoint(new Datapoint(m.name.GetString(), - *value)); - delete value; - break; - } else if (m.value.IsDouble()) { - DatapointValue value(m.value.GetDouble()); - this->addDatapoint(new Datapoint(m.name.GetString(), - value)); - break; - } else { - string errMsg = "Cannot parse the numeric type"; - errMsg += " of reading element '"; - errMsg.append(m.name.GetString()); - errMsg += "'"; - - throw new ReadingSetException(errMsg.c_str()); - break; - } - } - - case kArrayType: - { - if ((m.value.GetArray())[0].IsArray()) - { - // We have a 2D array - vector< vector *> array; - for (auto& v : m.value.GetArray()) - { - vector *arrayValues = new vector; - for (auto& v : m.value.GetArray()) - { - if (v.IsDouble()) - { - arrayValues->push_back(v.GetDouble()); - } - else if (v.IsInt() || v.IsUint()) - { - double i = (double)v.GetInt(); - arrayValues->push_back(i); - } - else if (v.IsInt64() || v.IsUint64()) - { - double i = (double)v.GetInt64(); - arrayValues->push_back(i); - } - } - array.push_back(arrayValues); - } - DatapointValue value(array); - this->addDatapoint(new Datapoint(m.name.GetString(), - value)); - } - else - { - vector arrayValues; - for (auto& v : m.value.GetArray()) - { - if (v.IsDouble()) - { - arrayValues.push_back(v.GetDouble()); - } - else if (v.IsInt() || v.IsUint()) - { - double i = (double)v.GetInt(); - arrayValues.push_back(i); - } - else if (v.IsInt64() || v.IsUint64()) - { - double i = (double)v.GetInt64(); - arrayValues.push_back(i); - } - } - DatapointValue value(arrayValues); - this->addDatapoint(new Datapoint(m.name.GetString(), - value)); - } - break; - - } - case kObjectType: - { - // TODO This should be recursive - vector *obj = new vector; - for (auto &mo : m.value.GetObject()) { - switch (mo.value.GetType()) { - // String - case (kStringType): { - DatapointValue value(mo.value.GetString()); - obj->push_back(new Datapoint(mo.name.GetString(), - value)); - break; - } - - // Number - case (kNumberType): { - if (mo.value.IsInt() || - mo.value.IsUint() || - mo.value.IsInt64() || - mo.value.IsUint64()) { - - DatapointValue *value; - if (mo.value.IsInt() || - mo.value.IsUint()) { - value = new DatapointValue((long) mo.value.GetInt()); - } else { - value = new DatapointValue((long) mo.value.GetInt64()); - } - obj->push_back(new Datapoint(mo.name.GetString(), - *value)); - delete value; - break; - } else if (mo.value.IsDouble()) { - DatapointValue value(mo.value.GetDouble()); - obj->push_back(new Datapoint(mo.name.GetString(), - value)); - break; - } else { - string errMsg = "Cannot parse the numeric type"; - errMsg += " of reading element '"; - errMsg.append(mo.name.GetString()); - errMsg += "'"; - - throw new ReadingSetException(errMsg.c_str()); - break; - } - } - - case kArrayType: - { - vector arrayValues; - for (auto& v : mo.value.GetArray()) - { - if (v.IsDouble()) - { - arrayValues.push_back(v.GetDouble()); - } - else if (v.IsInt() || v.IsUint()) - { - double i = (double)v.GetInt(); - arrayValues.push_back(i); - } - else if (v.IsInt64() || v.IsUint64()) - { - double i = (double)v.GetInt64(); - arrayValues.push_back(i); - } - } - DatapointValue value(arrayValues); - obj->push_back(new Datapoint(mo.name.GetString(), - value)); - break; - - } - } - } - DatapointValue value(obj, true); - this->addDatapoint(new Datapoint(m.name.GetString(), - value)); - break; - } - - default: { - string errMsg = "Cannot handle unsupported type '"; - errMsg += kTypeNames[m.value.GetType()]; - errMsg += "' of reading element '"; - errMsg.append(m.name.GetString()); - errMsg += "'"; - - throw new ReadingSetException(errMsg.c_str()); - - break; - } - } + for (auto &m : json["reading"].GetObject()) + { + addDatapoint(datapoint(m.name.GetString(), m.value)); } } else @@ -602,6 +387,151 @@ JSONReading::JSONReading(const Value& json) } } +/** + * Create a Datapoint from a JSON item in a reading + * + * @param item The JSON object forthe data point + * @return Datapoint* The new data point + */ +Datapoint *JSONReading::datapoint(const string& name, const Value& item) +{ +Datapoint *rval = NULL; + + switch (item.GetType()) + { + // String + case (kStringType): + { + string str = item.GetString(); + if (str[0] == '_' && str[1] == '_') + { + // special encoded type + size_t pos = str.find_first_of(':'); + if (str.compare(2, 10, "DATABUFFER") == 0) + { + DataBuffer *databuffer = new Base64DataBuffer(str.substr(pos + 1)); + DatapointValue value(databuffer); + rval = new Datapoint(name, value); + } + else if (str.compare(2, 7, "DPIMAGE") == 0) + { + DPImage *image = new Base64DPImage(str.substr(pos + 1)); + DatapointValue value(image); + rval = new Datapoint(name, value); + } + + } + else + { + DatapointValue value(item.GetString()); + rval = new Datapoint(name, value); + } + break; + } + + // Number + case (kNumberType): + { + if (item.IsInt() || + item.IsUint() || + item.IsInt64() || + item.IsUint64()) + { + + DatapointValue *value; + if (item.IsInt() || item.IsUint()) + { + value = new DatapointValue((long) item.GetInt()); + } + else + { + value = new DatapointValue((long) item.GetInt64()); + } + rval = new Datapoint(name, *value); + delete value; + break; + } + else if (item.IsDouble()) + { + DatapointValue value(item.GetDouble()); + rval = new Datapoint(name, value); + break; + } + else + { + string errMsg = "Cannot parse the numeric type"; + errMsg += " of reading element '"; + errMsg.append(name); + errMsg += "'"; + + throw new ReadingSetException(errMsg.c_str()); + break; + } + } + + // Arrays + case kArrayType: + { + vector arrayValues; + for (auto& v : item.GetArray()) + { + if (v.IsDouble()) + { + arrayValues.push_back(v.GetDouble()); + } + else if (v.IsInt() || v.IsUint()) + { + double i = (double)v.GetInt(); + arrayValues.push_back(i); + } + else if (v.IsInt64() || v.IsUint64()) + { + double i = (double)v.GetInt64(); + arrayValues.push_back(i); + } + } + DatapointValue value(arrayValues); + rval = new Datapoint(name, value); + break; + + } + + // Nested object + case kObjectType: + { + vector *obj = new vector; + for (auto &mo : item.GetObject()) + { + obj->push_back(datapoint(mo.name.GetString(), mo.value)); + } + DatapointValue value(obj, true); + rval = new Datapoint(name, value); + break; + } + + case kTrueType: + { + DatapointValue value("true"); + rval = new Datapoint(name, value); + break; + } + case kFalseType: + { + DatapointValue value("false"); + rval = new Datapoint(name, value); + break; + } + + default: + { + char errMsg[80]; + snprintf(errMsg, sizeof(errMsg), "Unhandled type for %s in JSON payload %d", name.c_str(), item.GetType()); + throw new ReadingSetException(errMsg); + } + } + return rval; +} + /** * Escapes a character in a string to be properly handled as JSON * From 2bd621deff699606c270e3ab7728822a31c1e928 Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Mon, 3 Oct 2022 11:30:13 +0100 Subject: [PATCH 28/48] FOGL-6961 Add support for ADH (#838) * FOGL-6961 Add ADH as a destination for OMF north Signed-off-by: Mark Riddoch * Update documentation to include ADH Signed-off-by: Mark Riddoch * Add missing UI validity rules Signed-off-by: Mark Riddoch * Fix URL for getting token Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/plugins/common/include/ocs.h | 4 ++ C/plugins/common/ocs.cpp | 16 ++++--- C/plugins/north/OMF/include/omf.h | 3 +- C/plugins/north/OMF/omf.cpp | 28 ++++++++---- C/plugins/north/OMF/plugin.cpp | 70 +++++++++++++++++------------- docs/OMF.rst | 41 +++++++++++++++-- docs/fledge-north-OMF.rst | 2 +- docs/images/omf-plugin-adh.jpg | Bin 0 -> 93385 bytes docs/images/omf-plugin-ocs.jpg | Bin 93472 -> 92308 bytes 9 files changed, 116 insertions(+), 48 deletions(-) create mode 100644 docs/images/omf-plugin-adh.jpg diff --git a/C/plugins/common/include/ocs.h b/C/plugins/common/include/ocs.h index f59de114f5..3070fe7825 100644 --- a/C/plugins/common/include/ocs.h +++ b/C/plugins/common/include/ocs.h @@ -15,6 +15,7 @@ using namespace std; #define OCS_HOST "dat-b.osisoft.com:443" +#define ADH_HOST "uswe.datahub.connect.aveva.com" #define TIMEOUT_CONNECT 10 #define TIMEOUT_REQUEST 10 #define RETRY_SLEEP_TIME 1 @@ -31,11 +32,14 @@ class OCS { public: OCS(); + OCS(bool adh); // Destructor ~OCS(); string retrieveToken(const string& clientId, const string& clientSecret); string extractToken(const string& response); + private: + bool m_adh; }; #endif diff --git a/C/plugins/common/ocs.cpp b/C/plugins/common/ocs.cpp index 3f62d7554f..c30cfd9d57 100644 --- a/C/plugins/common/ocs.cpp +++ b/C/plugins/common/ocs.cpp @@ -23,7 +23,11 @@ using namespace std; using namespace rapidjson; -OCS::OCS() +OCS::OCS() : m_adh(false) +{ +} + +OCS::OCS(bool adh) : m_adh(adh) { } @@ -78,7 +82,7 @@ std::string OCS::retrieveToken(const string& clientId, const string& clientSecre vector> header; int httpCode; - endPoint = new SimpleHttps(OCS_HOST, + endPoint = new SimpleHttps(m_adh ? ADH_HOST : OCS_HOST, TIMEOUT_CONNECT, TIMEOUT_REQUEST, RETRY_SLEEP_TIME, @@ -89,8 +93,10 @@ std::string OCS::retrieveToken(const string& clientId, const string& clientSecre payload = PAYLOAD_RETRIEVE_TOKEN; - StringReplace(payload, "CLIENT_ID_PLACEHOLDER", clientId); - StringReplace(payload, "CLIENT_SECRET_ID_PLACEHOLDER", clientSecret); + StringReplace(payload, "CLIENT_ID_PLACEHOLDER", urlEncode(clientId)); + StringReplace(payload, "CLIENT_SECRET_ID_PLACEHOLDER", urlEncode(clientSecret)); + + Logger::getLogger()->fatal("FIXME: Encoded payload is %s", payload.c_str()); // Anonymous auth string authMethod = "a"; @@ -124,4 +130,4 @@ std::string OCS::retrieveToken(const string& clientId, const string& clientSecre delete endPoint; return token; -} \ No newline at end of file +} diff --git a/C/plugins/north/OMF/include/omf.h b/C/plugins/north/OMF/include/omf.h index 23a0888d7e..8872ec0fd7 100644 --- a/C/plugins/north/OMF/include/omf.h +++ b/C/plugins/north/OMF/include/omf.h @@ -30,7 +30,8 @@ enum OMF_ENDPOINT { ENDPOINT_PIWEB_API, ENDPOINT_CR, ENDPOINT_OCS, - ENDPOINT_EDS + ENDPOINT_EDS, + ENDPOINT_ADH }; // Documentation about the Naming Scheme available at: https://fledge-iot.readthedocs.io/en/latest/OMF.html#naming-scheme diff --git a/C/plugins/north/OMF/omf.cpp b/C/plugins/north/OMF/omf.cpp index d163f91518..c29ef5d86d 100644 --- a/C/plugins/north/OMF/omf.cpp +++ b/C/plugins/north/OMF/omf.cpp @@ -131,7 +131,7 @@ const char *AF_HIERARCHY_1LEVEL_LINK = QUOTE( * * @param reading Reading for which the OMF message must be generated * @param measurementId Name/Reference of the object of the Data Archive at which the data must be assigned - * @param PIServerEndpoint End point for which the OMF message must be prepared among: PIWebAPI, OCS, EDS... + * @param PIServerEndpoint End point for which the OMF message must be prepared among: PIWebAPI, ADH, OCS, EDS... * @param AFHierarchyPrefix Unused at the current stage * @param hints OMF hints for the specific reading for changing the behaviour of the operation * @@ -1148,6 +1148,7 @@ uint32_t OMF::sendToServer(const vector& readings, } if (m_PIServerEndpoint == ENDPOINT_CR || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_OCS || m_PIServerEndpoint == ENDPOINT_EDS ) @@ -1738,6 +1739,7 @@ const std::string OMF::createTypeData(const Reading& reading, OMFHints *hints) // Connector relay / ODS / EDS if (m_PIServerEndpoint == ENDPOINT_CR || m_PIServerEndpoint == ENDPOINT_OCS || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_EDS ) { @@ -2082,6 +2084,7 @@ const std::string OMF::createStaticData(const Reading& reading) } else if (m_PIServerEndpoint == ENDPOINT_OCS || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_EDS) { sData.append(assetName); @@ -2130,8 +2133,9 @@ std::string OMF::createLinkData(const Reading& reading, std::string& AFHierarch // Handles the structure for the Connector Relay // not supported by PI Web API - // Connector relay / ODS / EDS + // Connector relay / ADH / ODS / EDS if (m_PIServerEndpoint == ENDPOINT_CR || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_OCS || m_PIServerEndpoint == ENDPOINT_EDS ) @@ -2191,6 +2195,7 @@ std::string OMF::createLinkData(const Reading& reading, std::string& AFHierarch lData.append(assetName); } else if (m_PIServerEndpoint == ENDPOINT_OCS || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_EDS) { // Add asset_name @@ -3593,6 +3598,7 @@ long OMF::getAssetTypeId(const string& assetName) // Connector relay / ODS / EDS if (m_PIServerEndpoint == ENDPOINT_CR || m_PIServerEndpoint == ENDPOINT_OCS || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_EDS ) { @@ -3647,9 +3653,10 @@ long OMF::getNamingScheme(const string& assetName) string AFHierarchyPrefix; string AFHierarchyLevel; - // Connector relay / ODS / EDS + // Connector relay / ADH / ODS / EDS if (m_PIServerEndpoint == ENDPOINT_CR || m_PIServerEndpoint == ENDPOINT_OCS || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_EDS ) { @@ -3709,9 +3716,10 @@ string OMF::getHashStored(const string& assetName) string AFHierarchyPrefix; string AFHierarchyLevel; - // Connector relay / ODS / EDS + // Connector relay / ADH / ODS / EDS if (m_PIServerEndpoint == ENDPOINT_CR || m_PIServerEndpoint == ENDPOINT_OCS || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_EDS ) { @@ -3763,8 +3771,9 @@ string OMF::getPathStored(const string& assetName) string AFHierarchyPrefix; string AFHierarchyLevel; - // Connector relay / ODS / EDS + // Connector relay / ADH / OCS / EDS if (m_PIServerEndpoint == ENDPOINT_CR || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_OCS || m_PIServerEndpoint == ENDPOINT_EDS ) @@ -3816,8 +3825,9 @@ string OMF::getPathOrigStored(const string& assetName) string AFHierarchyPrefix; string AFHierarchyLevel; - // Connector relay / ODS / EDS + // Connector relay / ADH / ODS / EDS if (m_PIServerEndpoint == ENDPOINT_CR || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_OCS || m_PIServerEndpoint == ENDPOINT_EDS ) @@ -3872,8 +3882,9 @@ bool OMF::setPathStored(const string& assetName, string &afHierarchy) string AFHierarchyPrefix; string AFHierarchyLevel; - // Connector relay / ODS / EDS + // Connector relay / ADH / ODS / EDS if (m_PIServerEndpoint == ENDPOINT_CR || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_OCS || m_PIServerEndpoint == ENDPOINT_EDS ) @@ -4052,8 +4063,9 @@ bool OMF::setCreatedTypes(const Reading& row, OMFHints *hints) assetName = m_assetName; retrieveAFHierarchyFullPrefixAssetName(assetName, AFHierarchyPrefix, AFHierarchy); - // Connector relay / ODS / EDS + // Connector relay / ADH / ODS / EDS if (m_PIServerEndpoint == ENDPOINT_CR || + m_PIServerEndpoint == ENDPOINT_ADH || m_PIServerEndpoint == ENDPOINT_OCS || m_PIServerEndpoint == ENDPOINT_EDS ) diff --git a/C/plugins/north/OMF/plugin.cpp b/C/plugins/north/OMF/plugin.cpp index 3b893f099a..fd79b5ad27 100755 --- a/C/plugins/north/OMF/plugin.cpp +++ b/C/plugins/north/OMF/plugin.cpp @@ -88,15 +88,17 @@ using namespace SimpleWeb; #define ENDPOINT_URL_PI_WEB_API "https://HOST_PLACEHOLDER:PORT_PLACEHOLDER/piwebapi/omf" #define ENDPOINT_URL_CR "https://HOST_PLACEHOLDER:PORT_PLACEHOLDER/ingress/messages" #define ENDPOINT_URL_OCS "https://dat-b.osisoft.com:PORT_PLACEHOLDER/api/v1/tenants/TENANT_ID_PLACEHOLDER/Namespaces/NAMESPACE_ID_PLACEHOLDER/omf" +#define ENDPOINT_URL_ADH "https://uswe.datahub.connect.aveva.com:PORT_PLACEHOLDER/api/v1/Tenants/TENANT_ID_PLACEHOLDER/Namespaces/NAMESPACE_ID_PLACEHOLDER/omf" #define ENDPOINT_URL_EDS "http://localhost:PORT_PLACEHOLDER/api/v1/tenants/default/namespaces/default/omf" static bool s_connected = true; // if true, access to PI Web API is working enum OMF_ENDPOINT_PORT { ENDPOINT_PORT_PIWEB_API=443, - ENDPOINT_PORT_POINT_CR=5460, - ENDPOINT_PORT_POINT_OCS=443, - ENDPOINT_PORT_POINT_EDS=5590 + ENDPOINT_PORT_CR=5460, + ENDPOINT_PORT_OCS=443, + ENDPOINT_PORT_EDS=5590, + ENDPOINT_PORT_ADH=443 }; /** @@ -111,7 +113,7 @@ enum OMF_ENDPOINT_PORT { "Property does not exist in the type definition", \ "Container is not defined", \ "Unable to find the property of the container of type" \ - ] \ + ] \ } \ ) @@ -119,7 +121,7 @@ enum OMF_ENDPOINT_PORT { { \ "EventInfo" : [ \ "The specified value is outside the allowable range" \ - ] \ + ] \ } \ ) @@ -139,7 +141,7 @@ const char *PLUGIN_DEFAULT_CONFIG_INFO = QUOTE( "PIServerEndpoint": { "description": "Select the endpoint among PI Web API, Connector Relay, OSIsoft Cloud Services or Edge Data Store", "type": "enumeration", - "options":["PI Web API", "Connector Relay", "OSIsoft Cloud Services", "Edge Data Store"], + "options":["PI Web API", "AVEVA Data Hub", "Connector Relay", "OSIsoft Cloud Services", "Edge Data Store"], "default": "PI Web API", "order": "1", "displayName": "Endpoint" @@ -166,7 +168,7 @@ const char *PLUGIN_DEFAULT_CONFIG_INFO = QUOTE( "default": "localhost", "order": "4", "displayName": "Server hostname", - "validity" : "PIServerEndpoint != \"Edge Data Store\" && PIServerEndpoint != \"OSIsoft Cloud Services\"" + "validity" : "PIServerEndpoint != \"Edge Data Store\" && PIServerEndpoint != \"OSIsoft Cloud Services\" && PIServerEndpoint != \"AVEVA Data Hub\"" }, "ServerPort": { "description": "Port on which the endpoint either PI Web API or Connector Relay or Edge Data Store is listening, 0 will use the default one", @@ -174,7 +176,7 @@ const char *PLUGIN_DEFAULT_CONFIG_INFO = QUOTE( "default": "0", "order": "5", "displayName": "Server port, 0=use the default", - "validity" : "PIServerEndpoint != \"OSIsoft Cloud Services\"" + "validity" : "PIServerEndpoint != \"OSIsoft Cloud Services\" && PIServerEndpoint != \"AVEVA Data Hub\"" }, "producerToken": { "description": "The producer token that represents this Fledge stream", @@ -307,36 +309,36 @@ const char *PLUGIN_DEFAULT_CONFIG_INFO = QUOTE( "validity" : "PIServerEndpoint == \"PI Web API\" && PIWebAPIAuthenticationMethod == \"kerberos\"" }, "OCSNamespace" : { - "description" : "Specifies the OCS namespace where the information are stored and it is used for the interaction with the OCS API", + "description" : "Specifies the namespace where the information are stored and it is used for the interaction with AVEVA Data Hub or OCS", "type" : "string", "default": "name_space", "order": "23", - "displayName" : "OCS Namespace", - "validity" : "PIServerEndpoint == \"OSIsoft Cloud Services\"" + "displayName" : "Namespace", + "validity" : "PIServerEndpoint == \"OSIsoft Cloud Services\" || PIServerEndpoint == \"AVEVA Data Hub\"" }, "OCSTenantId" : { - "description" : "Tenant id associated to the specific OCS account", + "description" : "Tenant id associated to the specific AVEVA Data Hub or OCS account", "type" : "string", "default": "ocs_tenant_id", "order": "24", - "displayName" : "OCS Tenant ID", - "validity" : "PIServerEndpoint == \"OSIsoft Cloud Services\"" + "displayName" : "Tenant ID", + "validity" : "PIServerEndpoint == \"OSIsoft Cloud Services\" || PIServerEndpoint == \"AVEVA Data Hub\"" }, "OCSClientId" : { - "description" : "Client id associated to the specific OCS account, it is used to authenticate the source for using the OCS API", + "description" : "Client id associated to the specific account, it is used to authenticate when using the AVEVA Data Hub or OCS", "type" : "string", "default": "ocs_client_id", "order": "25", - "displayName" : "OCS Client ID", - "validity" : "PIServerEndpoint == \"OSIsoft Cloud Services\"" + "displayName" : "Client ID", + "validity" : "PIServerEndpoint == \"OSIsoft Cloud Services\" || PIServerEndpoint == \"AVEVA Data Hub\"" }, "OCSClientSecret" : { - "description" : "Client secret associated to the specific OCS account, it is used to authenticate the source for using the OCS API", + "description" : "Client secret associated to the specific account, it is used to authenticate with AVEVA Data Hub or OCS", "type" : "password", "default": "ocs_client_secret", "order": "26", - "displayName" : "OCS Client Secret", - "validity" : "PIServerEndpoint == \"OSIsoft Cloud Services\"" + "displayName" : "Client Secret", + "validity" : "PIServerEndpoint == \"OSIsoft Cloud Services\" || PIServerEndpoint == \"AVEVA Data Hub\"" }, "PIWebAPInotBlockingErrors": { "description": "These errors are considered not blocking in the communication with the PI Web API, the sending operation will proceed with the next block of data if one of these is encountered", @@ -486,21 +488,28 @@ PLUGIN_HANDLE plugin_init(ConfigCategory* configData) Logger::getLogger()->debug("PI-Server end point manually selected - Connector Relay "); connInfo->PIServerEndpoint = ENDPOINT_CR; url = ENDPOINT_URL_CR; - endpointPort = ENDPOINT_PORT_POINT_CR; + endpointPort = ENDPOINT_PORT_CR; + } + else if(PIServerEndpoint.compare("AVEVA Data Hub") == 0) + { + Logger::getLogger()->debug("End point manually selected - AVEVA Data Hub"); + connInfo->PIServerEndpoint = ENDPOINT_ADH; + url = ENDPOINT_URL_ADH; + endpointPort = ENDPOINT_PORT_ADH; } else if(PIServerEndpoint.compare("OSIsoft Cloud Services") == 0) { Logger::getLogger()->debug("End point manually selected - OSIsoft Cloud Services"); connInfo->PIServerEndpoint = ENDPOINT_OCS; url = ENDPOINT_URL_OCS; - endpointPort = ENDPOINT_PORT_POINT_OCS; + endpointPort = ENDPOINT_PORT_OCS; } else if(PIServerEndpoint.compare("Edge Data Store") == 0) { - Logger::getLogger()->debug("End point manually selected - OSIsoft Cloud Services"); + Logger::getLogger()->debug("End point manually selected - Edge Data Store"); connInfo->PIServerEndpoint = ENDPOINT_EDS; url = ENDPOINT_URL_EDS; - endpointPort = ENDPOINT_PORT_POINT_EDS; + endpointPort = ENDPOINT_PORT_EDS; } ServerPort = (ServerPort.compare("0") == 0) ? to_string(endpointPort) : ServerPort; } @@ -845,9 +854,9 @@ uint32_t plugin_send(const PLUGIN_HANDLE handle, connInfo->sender->setOCSClientId (connInfo->OCSClientId); connInfo->sender->setOCSClientSecret (connInfo->OCSClientSecret); - // OCS - retrieves the authentication token - // It is retrieved at every send as it can expire and the configuration is only in OCS - if (connInfo->PIServerEndpoint == ENDPOINT_OCS) + // OCS or ADH - retrieves the authentication token + // It is retrieved at every send as it can expire and the configuration is only in OCS and ADH + if (connInfo->PIServerEndpoint == ENDPOINT_OCS || connInfo->PIServerEndpoint == ENDPOINT_ADH) { connInfo->OCSToken = OCSRetrieveAuthToken(connInfo); connInfo->sender->setOCSToken (connInfo->OCSToken); @@ -1426,7 +1435,10 @@ string OCSRetrieveAuthToken(CONNECTOR_INFO* connInfo) string token; OCS *ocs; - ocs = new OCS(); + if (connInfo->PIServerEndpoint == ENDPOINT_OCS) + ocs = new OCS(); + else if (connInfo->PIServerEndpoint == ENDPOINT_ADH) + ocs = new OCS(true); token = ocs->retrieveToken(connInfo->OCSClientId , connInfo->OCSClientSecret); @@ -1598,4 +1610,4 @@ bool IsPIWebAPIConnected(CONNECTOR_INFO* connInfo) } return s_connected; -} \ No newline at end of file +} diff --git a/docs/OMF.rst b/docs/OMF.rst index ec303fd3c9..9a49ebc333 100644 --- a/docs/OMF.rst +++ b/docs/OMF.rst @@ -6,6 +6,7 @@ .. |omf_plugin_connector_relay_config| image:: images/omf-plugin-connector-relay.jpg .. |omf_plugin_eds_config| image:: images/omf-plugin-eds.jpg .. |omf_plugin_ocs_config| image:: images/omf-plugin-ocs.jpg +.. |omf_plugin_adh_config| image:: images/omf-plugin-adh.jpg .. Links .. |OMFHint filter plugin| raw:: html @@ -86,6 +87,38 @@ Select Edge Data Store from the Endpoint options. - **Number Format:** Used to match Fledge data types to the data type configured in PI. The default is float64 but may be set to any OMF datatype that supports floating point values. - **Compression:** Compress the readings data before sending them to the Edge Data Store. +AVEVA Data Hub OMF Endpoint +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Go to the Fledge user interface, create a new North instance and select the “OMF” plugin on the first screen. +The second screen will request the following information: + ++-------------------------+ +| |omf_plugin_adh_config| | ++-------------------------+ + +Select AVEVA Data Hubfrom the Endpoint options. + +- Basic Information + - **Endpoint:** This is the type of OMF endpoint. In this case, choose AVEVA Data Hub. + - **Naming scheme:** Defines the naming scheme to be used when creating the PI points within the PI Server. See :ref:`Naming_Scheme`. + - **Data Source:** Defines which data is sent to AVEVA Data Hub. Choices are: readings or statistics (that is, Fledge's internal statistics). + - **Static Data:** Data to include in every reading sent to AVEVA Data Hub. For example, you can use this to specify the location of the devices being monitored by the Fledge server. +- Authentication + - **Namespace:** Your namespace within the AVEVA Data Hub. + - **Tenant ID:** Your AVEVA Data Hub Tenant ID for your account. + - **Client ID:** Your AVEVA Data Hub Client ID for your account. + - **Client Secret:** Your AVEVA Data Hub Client Secret. +- Connection management (These should only be changed with guidance from support) + - **Sleep Time Retry:** Number of seconds to wait before retrying the HTTP connection (Fledge doubles this time after each failed attempt). + - **Maximum Retry:** Maximum number of times to retry connecting to the AVEVA Data Hub. + - **HTTP Timeout:** Number of seconds to wait before Fledge will time out an HTTP connection attempt. +- Other (Rarely changed) + - **Integer Format:** Used to match Fledge data types to the data type configured in AVEVA Data Hub. This defaults to int64 but may be set to any OMF data type compatible with integer data, e.g. int32. + - **Number Format:** Used to match Fledge data types to the data type configured in AVEVA Data Hub. The default is float64 but may be set to any OMF datatype that supports floating point values. + - **Compression:** Compress the readings data before sending them to AVEVA Data Hub. + + OSIsoft Cloud Services OMF Endpoint ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -104,10 +137,10 @@ Select OSIsoft Cloud Services from the Endpoint options. - **Data Source:** Defines which data is sent to OSIsoft Cloud Services. Choices are: readings or statistics (that is, Fledge's internal statistics). - **Static Data:** Data to include in every reading sent to OSIsoft Cloud Services. For example, you can use this to specify the location of the devices being monitored by the Fledge server. - Authentication - - **OCS Namespace:** Your namespace within OSIsoft Cloud Services. - - **OCS Tenant ID:** Your OSIsoft Cloud Services Tenant ID for your account. - - **OCS Client ID:** Your OSIsoft Cloud Services Client ID for your account. - - **OCS Client Secret:** Your OSIsoft Cloud Services Client Secret. + - **Namespace:** Your namespace within OSIsoft Cloud Services. + - **Tenant ID:** Your OSIsoft Cloud Services Tenant ID for your account. + - **Client ID:** Your OSIsoft Cloud Services Client ID for your account. + - **Client Secret:** Your OSIsoft Cloud Services Client Secret. - Connection management (These should only be changed with guidance from support) - **Sleep Time Retry:** Number of seconds to wait before retrying the HTTP connection (Fledge doubles this time after each failed attempt). - **Maximum Retry:** Maximum number of times to retry connecting to the PI server. diff --git a/docs/fledge-north-OMF.rst b/docs/fledge-north-OMF.rst index 689f2094e2..74e1a6bf90 100644 --- a/docs/fledge-north-OMF.rst +++ b/docs/fledge-north-OMF.rst @@ -2,5 +2,5 @@ OMF === -The *OMF* north plugin is included in all distributions of the Fledge core and provides the north bound interface to the OSIsoft data historians in all it forms; PI Server, Edge Data Store and OSIsoft Cloud Services. +The *OMF* north plugin is included in all distributions of the Fledge core and provides the north bound interface to the OSIsoft data historians in all it forms; PI Server, Edge Data Store, AVEVA Data Hub and OSIsoft Cloud Services. diff --git a/docs/images/omf-plugin-adh.jpg b/docs/images/omf-plugin-adh.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9dfcd1e54f0f7f0daf1f5854ade877df6fa5bec1 GIT binary patch literal 93385 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�Xc@MFL|E!U)o~IXO8cE1OU0(js`%>kE7pPihlW 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

=R zWYJgo>C&)lM?=p2?vz3@nodJG!*dezGyz>K>Qv6}LBw|{*dW|-rwseF^R<|skd;wc zWSsU@OqKlo<1;tbxsXyEmwFjjZ#;PJ{~>)>4K_H9$Cl!*;niX4w=vK_7kb3G60c(8 z>GhfT4m!fx^~Qwmjho9FRuY_jjAvfH;Xm(`z2pb=p##2~v5)dli`^il&r{qx+of;C zVhZXj2Qb?!u_nNAyV0RSC%5!6k; zlx|bM2>QLfV58;I4gk%Vk3Uq9%ZF``aFs~h9CPQA_LA00|K{o?-N*fi! zv6r=hk@lAm=+~e9oEu+g<_ck>nm5Pl;391PE*~h@}gASgFZ(l%KHF%eJYN4w>r)}+6#ZAb3z>t45 zd7aJc*lV%o_!|tm1^Cbuhq!O(9hJbg#mcQvUP(+(7sF|dtig<_x&B-`5<-QbE)>ZX2zyH zC;je*@%ISCN;0wNvbcc_|6nVV^Dp;*pY;0Siphoq#)y?_L@7?NstKw#@o=kAe2I?P0KR3~Af025lf3Xv%uGT(+GPYnKf+$zUV}f@y*>Nc>}d1zBRZpSrjif#s)~g;2~%%AD07P{CWQfq*?>yhqN}%@- zKpGXgNa1sSrHo}tCwJp&ZjzI$>+yj>X>Yzh($?$a@jLkfk_KF_Ohpv^kU4sHpF61A z#N!7dFP)YB+}^0fAuzt@;jpop@dU31m@(e(06Bs&S>F!|-3)?14sLNBfxhhs5%=KT zG2eYI7*=M7AYG0?YmJD5;Uf^|4}&~akQr&X1$b4v@I`fk-FKfIQd!9U(KB_A|9a#P zvixE2OR#@bpVG1pIXU)Y_Z1@X9xJW`(g+ij=vy>`&Dj2ekK)2R6Ut<^!dzE5{!sKax+xo~~!M|~Aw`@)T z>s=+e*1q`^j?zh}^D6taP4sA&e&fs=J@Yv=!MJ<0XSCxOL}6gatG8F)J&e=XhLY60 z%MSPdvJ;hvgpEEY2_OnynXnWdftYA^>UG?0TimmDMW&3V*F7ZH>wO&Qn(D>$)Ur;5 z2A%-zfquJJC|q=NSm4zQ00cVuJ81M@_4Dtq#C3lPrbDuTEP*G0F7y}%MtJY6*FKO& z=Qz9Bsh|qvX*#WqL-vlR(*SR#;CFIEBhg;Y50ek#rza z;lKW;fdK%P`g#cDhm&CQ5Fo?o;|ht4Xh;6`XNgw-yn5vSn1cUz72!{${{E4D?VlO{ zPtd|YPo(>$g@9Gb*3|q%G7{(&&^R?2;gPBgKKhCDqkl&0{`j~56SVLrf;E2>%Re*z zZ!JOw3xul!F8pN|{-@3F|Fj7I&)J0= z=be_`kX;pB$z5Xjn$Dn**)aHJli}Mkn79jRkNNkH{+F+cHj)P30{9CfKr7Bq5dL96 z-uKgYTmRR+s;HrYphZfJB(BW zdw^b~uP!YaMAbwPguE4lO417K#p;W76ypRw_dj8QUBG}IZ!{!|)sgcnI_@G!C)Uum zsGe@1#gf`HbbR|$&xq}ZO2X@tlhrdHBPS1KF1b!Yi~9XuWW9W*DNNrg{OSdBZy7Z) z4RU`ctfd06WsN4kUiW6K`fkuX_+Rb4XINA1x-J?(ML|S*Cv;GnB7)K)C{09~bOEJE z6CxcX5I{hR5CH)}DN;nG_fF_VK%_&c0qHGK2!VunhV!hsrhe<1^ZV91YhQcqef+_7 zy%~)1j%U2}dG6=FFSOgRVf*1N-$58XC^<|HlNSXOri^Z2plz>*Fyj{uv^j2#6hXIO z_C-!A{;ZN)1w2W1XH8yan-sNshsBNQUjTtfMbcJmcu0F)(fc>PK8EGUrq3(pE;naU zo=N6cXD=t(q%kH%qGXM!=IIMKSb0X$d9n6kF#h9}1JRe|wI$@IUKSM2ZrcXi)xO?} z6_8L{48cvLBIr}5Zrqw-steH(aY9=n8Pfmg)^MI=llRJvT9z$aI@X&nxE6qwQBQ|Gn z&BL-axtKHOgH-b;f%6?E=cq%JDc%&7>x_G9TP|-8Xf}kbJD-9@=R~P`hg-a<(jXHw zccysqB!u=c$y~vWzz4)rG5TU#N)ZXd{bRk)G#pgy|dC~%pQ8ALQ$u`*1u-g zgRhl-d*<7+Yuw4BUb+y`JxQF#XQCH|vK?6ozz4L^{oc4)2#ZW%?wj(I?Y(?|#WNi~ zW}uW>N88A3gR?F}A=%;pQ%CyhtQe*`V#kX{z73U@d(@c#nS^FlrwIBx;=;c!847d~ zG~`Vvfa*=ho4f&iZ1FjpEzBmId6-I4QlP;+B~kek(s!-)f;l5*l(EFyX<2jJYaVeBluRSNZCakkcV|22nI1}PTt%KsnRbz#to6ZA_ z5a&$slx=YOK=zF~iPx##xp{z6(OH!zMm43SUpv}*kJTp7@oU7>%-b`P9bLkEbOzF5 zqn%Enxr_!3<+Q(~dSS}bgaOeY9yXrj`$~7;v1zGI+&kIL#x!L7%@j=wxZtXcTQi~$ z2Re41SYc97cYUAWg2%;$1|`H-Ea+F-st>j5)@3iSs#(kGsbuXduE?rINdcqNUQ8<-9mu^tmO7g(FwVT;Vq}%B1Nfk zr^3AxTQYDuhg%gc8z_xuAZQhDfzi~+hy<7xR`Lmnh3H%peQTs^%C$H=?1O_|nNA%m zu{YYJcxK)?%*bTHkKdd6`S~@o>aB9Sc_gJWcC<-y&63L*%-KWj3%;Fh;YL(bP<1sKJNLYw55$&e6J7Mqk;RF&kSr?A396es|j3 zOxjtxv@5MIuA(&j-UaH@@M$C5IxDaN7i#vc_ znQ52S*`7Pu;q9txtciquO_W=t09l;qGWba#6@Xd@C9)mGH*pdnM`^nduC;U_%uXAG zb#mP(H7&7QOWRw%QCgj=wC>q8lc~tr7Q@u5oU+L^;mwqL9VW9pSeB=9`NQ<6)Lf@Voj{dqrv%nm)tpVh6>jrre;AC znG4EA@yL_`8luQi9*hgXWVKsy2hwO_**~`F;p;IZ*3F_V*TrZ?9T?$Og@UF8COVCY< zOoc)5f&|9NC2Hg6HPa84gCK7=B!Q_!9}9#Xf_Jx!J}sIJp+gq-bz(jJ^Br7$B5ad* zw6bp61Uzd#ftvV4XT;)iXFr`RZA{s0^7Q&liwCfZm&#+c)?MSycaf!DO$~*W4T%SnMA_8?g)71TZb{ z7UGKZJv<~%B`%t@v{Rht_oKSG61ZwZ_4XR=y&(tn&A;*7Nv6{__C|_fa3{XoPQa%H^lTr5`;m7C058*ZzJp*Hn4$&XHcefg z@TCO!oKW&+vIPvtuxir58w2-w^vkK)o5}ER0PtWZfy6Yeca1ewn&C#7^ao?_i|KL? zs#df9r+kG!_ZKUf9(_PMBc9HcNjyQvICnk1U0bBJaP*k=%vzEXcd1;=W_2~4mec~1 zopsg~iG1iL6XpXy&5#O6lUgWyHp(svf1uboMagGia60MXogZjPd$5p8x zlj+P-EMW6RQ&O*!j93?tR{+8~NxUEg7*8D_sOkllP7VtXopMZdG>n690#&aev8CX~ zRqlwZizDX?5qXHCY3X~_DRa-3*uOY{=V$3k^J(Tj9^ztt9m`#nPLDnDWMM-q?dHm@ z(gc01%$uWJKe&sOiG`MkRDGw7!`4i;3HCf)5E;Q{9zI1o4~Cqn+GNa)G=e#*ru-wC`qP` z3#(NsV+`_<0!BWm*G^7Ck2zU7>YQxK34#m2G=Ui-XnavXr^pH+ORWat2=a_j|Hi!@#xc_@suwuldQ zo~0sN1|lE(L{|HHXqJub724|zt{{gz>qQR)qRvSySI>Ta*4dtfa3$k;Eu*;D2B}1} z%&|Bk>AhS|EH602!;Ga+8)YY(bg`ygfwzPqjRwcwDRb#C9eB*|;03;eIwYg#=pSH_ zTWt%Ik`F6&o|4!wZ|mRs8k^NuSB*=0dS`4w18FMjd!aJBwp8nreughjGvJb2iYKPp zxlbqK!Uq+M{p`-fV4s?&Zroyb^Nt^CbrG7nEqY$T?L&7Vb>ba+i~7KaUqG~XKYs^3 z+zCbj^ZO}uMP2PPnEjvx>^izD6)a8@QYMD*Iwb5eTF5>4do;*NrI^p z@&pfNw!FyU!Ym%%iIR-mjbT>2QIk5ZRg%=RwOv^;IA0SNt+i~ffRm+hjo=p}RKKI# ziRtPbcw&@{GD`7T*kTq<^OpDXoJc1f_wU}G>kZD-KS;ELCrJf8bv>c|$Y`$8zWLi? zafA}tSmnD4QxYrJ1?T<8uX58~fKiwOT)U3wG2Z7v?rN-yg@N9IT~?S|;>Po|ojc^j zTiC6=&p9>2^ht~}NI=R%5)Hg|ETKS$zX6oluU+wF=cALbVp@a}_!dqm3 z9hd&|x&1?j~P*6M!%?0x~; z%{NIS@kp0NuX0S<>+&^O>bG=q94^lpYhKLm(ARbQG+R?wnm>1|_>#d?1x4)@Nc);h ztM#}&s!q`2e*H}=*y+Acn1IG2K=6_iNq^P$74OZalOT$1ou8m|Kf~%8z^&XDMjI}^ zopM0Ze;L`ioL}vDw<}Lm;o>RIP-XGl+R*bsw0%qA?p>^1alVpmV9tzo5><4kjK_7G zEKL`&_mmShCBY|RF&gCUH)b6g;zrI>oP73PFE|xMF#Z|b_XnikZ`9pyIOG4d*uwRO zOCD}+E0JI9r>Z$(-CiG#GyIn@RR4>E-mPQ1wR^lQ&p*o8%a_S5eg@y1`A}_KRdthn z4Hv#P@*Q*@vvIm$DiV_Gvu+Zsq_zid%cnYOM!~vuQ z=0p*SSHGN>O`-$#O*>r&831FQ&eoPN$sfL0NMeLT9UKdfFBI95S5Ou7^>m4=b0Ptie(F@rcbQSs2S&)C!(K&}SI|N^;CdtjA)p59l z?;u4ab_}5Q2Q7aG{o}O%9j{_NE+!oFAoSMiyi`fJ%1OnO@{Zp@C|t&L28jq5vi&oq zB)~}6_#L#rNF4YMVo)dY?E|qi#5V|0+naeGw=cQW)gW`KEnDasz>R2McsKJ5?LRTw zj>zx-{k_fo+?;;f@QYbG3U3 zGtw`*=d^PoZ_w3lwqo|91f(kzmA&w^Q!)fe+axw+Za(2VL<_FihfjJqLJKDG-U~yD zm-M2>mQtNnYoi`KZ*O1WK_oLBqOst4WSdTODv(}P9AO5}jG61A@z?%F)I)PvsPt+!e#^BgZ~5S7v*0bMcNl%2w3hn{>o)p5I1zAS z;ksB-A$vDJSxT(!Nx`mOqyxw=wiMV|tQ{ft5XbRa&D3bW-7VSXL-WNv~7caFnd zx!t-wj+Z+M`wXV1y7kO7wguuW!k3Rn3Q)|`o`$#R2A=cPTFhvl%HZ&|B(y`QJqOtF zR@W;>$F$7PNsB`1Cmfe&%tqeT)Iyx<#AO!i1RpV0Q59PN8$dt6D<0`PfD?xv^EF2+ z)xU9MUs_mK5*}qRPh#yDi+-b4EFM;q@|mMh#gv)jQE0b!Q?th6W}y!0R6T*k8O&n7 zn4Ud9aH(D2DM@am_~;ExT&QW7FP7t~Z8;11(DjFL!tw0%r6ppSmo6&J6q5SE>LxV`fpYHBHdYuc@!3yPrx_WAl?9)9XbyUSkkA)T$E5tzjI; z1!0o66pMkWpxiiCtjKes;S_p~(HGKcg?ZLrh>R-oa(o~pT~leBI<26>!y2Fc=pM*u zVAZ}AiK<_ejc&M1&{>W6Q&r06ThPH5T;CKOVSBU0Jg-hMhV> zAnoCkZ-I%^V7@BoP_+vul!hLV(%PtRJ4(q((ar&{UD9e-@(ecLIeSeYOjj;I7zf2) ze51NJAzjGvQ73X-YS#BCx%kvWX9q}`9kSN5B*Qo5%N%|9(I8!CU-#3Q zS0rj5bPtIh*nI<8YfsC

!K0w$Z%$QKRu2!#mPs)KY2sT5w5OExDr?16*}ijb~R` zg!d%dfre?{3}y}dbZEbsSL~oI9PDYXDAT4>61%;8&c%9=SZ-@w7i(Cj$#bDoUr#b6 zvBz3-AYvNcauI36M&xyycOWW$FgLNXT9->)tHv^y(sX<|Y;fxcz`Y7>WVoyD`8+fA zoW&xH-q_I%aVXgKBU?ZXL7$eR9T)XAb1ET5USAM1TKp0x|J zt^3DLOuN_U(**421-53CZ6{zMn)up0UvGy>#S;#$6&v^8Tfyzj?oLew#EM2#3_~XL zJ*$NTQ|{3p7hWE?JbR9ld^B=kRP)#P<`9ZXy#qjw`v)hrFEW)C2loG3xnJeNQUIti61=2}58EqeaO3a&X zgYxy2W^Z9gDcOV>?L1Y9x(uo+#mf|Qm+BV5><8%&eMi3DUj_`_6 z-4mtm_zbC7PFIw@&|Szijo>`tI4CP{{^k?W)8KkB_v#p-4~{D3={x=Gu`i(H931XZAj~wYZq&; zRLEnaTxAy*nzRbc_do$^Jcnh@NQM%d@(cy z;A+qQekQG2R>OCYG2RqIu+-We-L1)Ef1AOb=*i);Beo!6#Q$Vp*?aBDfLUNZrmb0S z$_e^mE$+5gu#=>Z{eEjtwQ@Zr$uwOJ!VcPT_(M+1PKAH3Hl)?4djD(AS!IWKO@U`j zbWCJo?HCYe{A1%(JT)#9Z-G7YbxL!vIF*|4HjcllHYWQ)Jd<%89mYB?(bS5r-tMH= z$Fp6?%0bTzIy|!^?Z()ekDb4DiO%V4cTLU+ro^X@lskM8Pmy+#;puExQuN{!uh>@y zBcxqb_~PmOrSn~`2fFp?C-<`&Le$R_s|+HXFzYAsgE@^=>tuSt+JLnP*Pnk4`O)g=QFTiis59CwcTZ4Q9PUePU3*i5pwhA=yf7x>;qpz2QTn=ZD z;sbrias+`qL9Re_#?}lT2q%082?GMWCh&j4em6okI5lBD1$o8&b%I}F6Hi$r%MhFB zT?3HT0bB}yXRFiug`EquDN+Rai9rvLi!=U-=MG2!6Gi;_vhJi5XQf)6pDXn z3V|@O3Fs*VE8H1oGPJe)d23H?FqL#MZ~ct!Og8Vcb9%zFZ0BP47Ol$RZ5gOb^R!zY zgeyd0{7S)e#eN;MeFN{Av1PhvJG?t7Je*Tfn)LOd;-YCg;aC~DnubBpDN^VvfMN8( z^*0{nHn0&aVYl#q&7Yz*cVn4(wMbV(MXcKN7+8b-Wwbm>!8>6)BM;~I~eH2PTh>;!c( zEg}2sYd|Z5aqI>R3Y!07KLQYp$K(c%!#R}B2BN@>;FhNIrNcyn1!$zwspGe}m1JQC08b2J5`l9WB5DNvSni?0W_fsfyXUHxY7-^f8aTmPao@!w<^lUw6~M9Ow4DdnpP9VQqgvP z){f%AK|!bVKlWM;?p>ziSLVETJ~)UHXs;w~q#a_4Ww9CnOhzWp(I`>jqsBXvQ5o&U zk(xdjv~(M8VzV%J1j;uOI6<3IS+p2SHpEQ3^zNHpj1?a6XC0S0YE*E>2m$^qT$3bb zZ!F(WIM_y3Zwh6p^=3VtXVj*=v81M|sx`-%f%tq{ZWfSApU$UU-=UB%?dQu9@&-w{ zyG?(l{MNR(Gi8pe1C&ZkdNBOP*wG(S=1S)gZktm(*gvop;Ve; zQ08nK*%xT-s%+Q(ODE#bsT7SJHK1~zJeN8_w(~?KOO#oc%vF8gfyA#h7X$ zV>B)u18$*4pc1;8&JQ)%V5XWauMF=V!3~D=Kke;Ea~XB3^2VDp60W57>LxLRAMm`) zc$n=D^a;(;1vn?%-s(w41tP4Vfd-qeA-5c913!@?jjK(kHqEOR%x0mxF5u{K)~3Ga zwIP$K_x$2e_!nPP@%3r%~d zZ6W!9hs`NXtB0k1Yjnnm)?#gofUMKp9EXzJgab2@z9GOi)jl}zqA&Z#O>DxH$#jJH zOWiaV}A+x|!#n0jz*QkaV4hxeAspIEsRFG7;Og zU{t(NetG+Oy2$WuF|*^CmTeR7p!8b0NHKqOVkDH8hRwHxQY`e5^U@rXV+>{(hrlE^ zrzvq=F~u7IZV>Y9sO?_us^PpE7V&~hr?ks>Z1s_RoFD8;W4a)tt7O*KJn}Ng& z&TXv`?vsY+xL1IkUu{LSSIzKVewuwNRuPFqgiDHfksU7(=cE{jm5t^d!ygo(EiYAz zT74Fj=KI?h&l^koj{!b65+Ev@49A0ai&}wY025-5@@Qx68d%XcdSNyOUCah==P?=X0 zg-bQRxSI0yPKfU=lRGULo*QK%Ts2r=TSNtw$);|lO(zM zMn0Or!9h64qvKGkIxFp?^l)qpujcrIUm#hJ(iB$3rod_ZRvQ@Yx%#tB?gFx0@h4t< zvT+u<$!6jr8S--4IOOqSY@&HP_;?eeZ@Oub7o2uNVO*-?a(mY7MS)H>{ug2~)e^Z2 zDj(a!QI|gJlFds-K87PI%{N>W?Ly6zsT(fcVAjZSbmfg>8&fwH6|6spB7bHpAI|!f zpo8*gOX?{wTgN4{7}wn{m3VQ#^cl1LrM~AP^m0q7BF~;3&|#Wo&?S$L_FLzU%_twQ zOsl9fGr#eiXJ}h!80p3B%}WsNsAUkgu2T6je>ydd#7b1ixXo^ei?;VUGa%kHO!aAq zd_mtL=kzDDYXT3fwIF?(t_~F4%SUfs=_hC>w5Eec?4ts1jC8(POfUu4nLvQok{+gI4i9-;+)+%U7XQkEZ$rO2N=@@l1Kp)i8|t!*lt)vX z1opM!Ku)64NO7^3;&qkbmD-W#>ONvggXN!|I8yU7^#3H`ZlJ2Gr{3dtsL&b z`1M*0CraO}yEMLBDltyNu=<=e83o%kOJOoDXz*TbQ{^j_(fvt|m(8&v4;)u2?l|(s z*rZI?(6*d^_vq2grS`oJk$&Cf5UjV76BSG1dtJA-D0Pdgc3xDzAf% zyQ7R-;9+L+bG?pe!U>mKa(63|u(iH9Q!gV$N%>#y3eRw;b5em88t!8WH!uU?070T2 zn5b2Gq+KAOVv}SDEuXH-s?e8K?)&`VqWwfr)z=z9yQ-sX7>iP=&s)XV+|$g)+V+CG z&qXTe)jgBk1HZw^uTGy6J8{ikySt!mH~~G^wp(p}<8uX;Uj54lY6n~d?qmJ6shE2E z6t`jeDSBh_pD{;aUu?q3M3)+;oN7y|$G+bS5 zUetz}>XzDFohVwbU1bZJPt8!p&<4X~KWG)=eN;G9r0 z*Z8~CTXPRCie8ai*@TL^!us=EA2~4)RA3ZV6v+1BMFcItv@OfkQ|@9;xIMKg`smDQ zHTb1odWsh9sd7}1Vqny_7=uM{t2k}D93-@|mzx>=Tf$hs{VSI6Ny*>;oG zI%qi)Gu}D(MCsDF0A}C`(IRWT?uBm8BV3XXMn|rVF@~WwhO^{OoGDvr(E6RPCo^ep zXEh|N;RzVwc1!w^1~?jUeyqx(&OBRIyslq8Qn*x6;niv6nAqnQ7x%o6R+=z?fKXH% zQL14Lzk{Cbibx~rH28*!1x8%PW)FIr&HbpuQpzV!N&l=c2hbG%yV~48E8jJ0bnw!l zUpu^0KEO!h;w5@g&{xyeLFLOE{YR|W*B;ln3Yh>uODhxLaUU23n5Irl!?7PBXsTiO z%K8todkR+wehHv6HUL9!2x7v^+=lt09V?MzmE>^p3)kDT|y&Ripm!_Xmp#V`lZ*# z$DoYL{Evo`>r`YJLFCuNLEt{<8Gs>G2c?5xFvb2d-hm!uH!4$E|C|UrM}} z2s`mS)haBFGw%?{11v9HiqtfSbUM3U(DCol5-J!1rj;LIb1GK<00ezG}sk@HcQWlq* z>+X)HvPA6Cn77smZY?9SCg0XSuC{UtakKFf>|0WsDp0mtQDQr7(g9bk(4~}|ho1pc z`iiP!B2$WPC)z>nSFS#AREQXrrSEu|@GM?aDQEoWOr1X~8;b&gcK#}00dHxXamdx^ zW!SqRBiA$LaygCr$^!@9bY{&Qhj2lMDV`4y9ZA-%$Do6a1(&=n=?tbX<4v4*dxf7q z%=~;z&i;^oYF6{|63XeVso-_@x1t6v0{&bqj}C4;eQew_OIHPimS1kno*m<8Pi8q3 zJZdn@{q!OpeqY-|tk*HOGO=QZUg323>bi*Sjj*WWVg@2QYk4Rl6hO!lz{Jx)m?UnM zUJ4Ti2vM>F_VJ)X>UcT%OGAqxlzKza7%ykQ@Lx zixRMSpa9_OUmh!sFTxKgCx8WoZ3Yo>jdP&oK9(zxd9`ifON?Yh!xP+CyvY6MRg2Yq zT7H5-8Vn8|3@>}Xywg=d=oT4o1w-hp45%Un-#fhfhZFA*eYeC?@`y3SdU z3FQ&)zXmR1G+vQx8^E6f@HKl_;e}8zwRDz3DA~MxYbwZ zfAW6nt;m}f&eeZXxiA>cbCz}lCHmEMibPe5re%bg;0-Wy=z$;w&G*9XV7iTTmQk8M zJ(Q(`S$G&jW4pmrd5O=ncYZ3}m<1+E(i#st&a!1KOGBIe@ z(!toS;4SHXM)2SDkqZg1!ofd!G=4WB4GX z^9cNH7{hmvax|ED67d}rRTRAmz?i44dI8xf^~u8Tpc*7lbF-kUbALE7o5YZD447=J zfysuPAAoIt7<-?O_qb78Qa-v8K5L=BxS15m3+jg?ecjYC`nu@dm6d?1QtF2ubr6w< zBV?a|y|V`(gMQisn4NCGiH2azYrHV&2{Qyw2ke-cELi^W^wP~r=ou%u%Iz>41*uub zSu4~Ved>-Cnw}c(=@aVjGO3WiUaL+NRyqaDT^$J0F?Aq~%aF#uGyM#vDmWjX-F_Qq z7WlM&E1@5H{zI6dd(Vr${BW?ef3ml+d}7dM;D4!th;sAqAUC)qsS@PzCv`Da#W};b zB>^1FSoS|meT{SH4|V<#`yK#f<1hYL(9i)Ya)yHesdI$r1Nh!M!e!(>3&8ikp-Ue>JP8)q`r%0?F#g>Az>$g1^xbN9lsmo@4ogY!-%tE-58=EzX{<(gX+9y zb2Kdl*}mBmIptWb_ovaw|0Uv7)c@%Fw+df zG0zy4AIjgCMK+t-vFlZjuU91XUahT2H%Zfys;ELh`FYQqvv#fKGLjvXzk|1k!|e+V z+75NXp_S0Hl|^wMdcGDN@dlz3yZ0(GuiI0Y;CC77EhjFoz4v| zy9JDN$v>n!@3KdM4%Bh3N6#B*39=irBG{Rt`eNU%j;2e_I$Mad_@s6Dd_qJ4T|A2J zOUE&~>t}t=$EiG#X#cVZHvUuJ`ma8BrjN7m?yWrdc;X7_Db&L7-a3i}mp09UvFNu~ zI3?hO*%ZhL(;^p8=hE}H2db65FuvI++yRcpK^Vr(qIJw2Ji9f`B`@h!llp4YS7c<< z-H(#DEPWDu2q_8^cZ7RKd_&7mTWm^9SY1C_8Iyjip)XlVV6#qq$P6^_v=rdc^y34qhKwR7_#Cz%D>x1qT4biJxQM1@2~z2 zVg)kYe*T$B8|(?FX|?-+nY{)gn&h!uvDG$3>m^Psa`y-0SzY-n>uPHvB|vFesjB7( zk-qz<(Xv+_*jNT*>T&Ma{mmKo!|K*$0si%)f4Ccd-{jY(@!KZ!Up-SqyqnSMWoHO`0M9v&00 ziwfeu!DUfzp9-4&tJu=NkVUMb64LkRc%UvYo0(LO55ib5bzrd5V7Bg5lp#h z_-*<`R}P2&6RPO}S0j^$UmDH|wg(S`f=oo&iT&7cB!<1K-RhJi+!o-d+6X*{;Yxl+ z3^;mu_yqyaeG}bkTqwY9I}U36lv=jp=#vDw(EYAM4Me%ecKY*lYclh8nL1y%kwK!J zLdeN=8bI?MaMqaq}rXcTFA2Gj0CQZNt2*S{s+87?TSIO01gDP5m& zQpY{Xz`QR*y6j`=!7Zww6GPd3$0sNbU9ymAa8{x|77m1H=0hPgBwjGrtZ%+$O+xcU zs|_XB-pV?;u{5U9f+4l*(j`g+$5a(tZ#Aj-rE+XRpc2Lt&Y~pHi*fF#8$ni7fWbRr z7205(QORZcRWQnX!;NVxsvDP|SNNv(LA*(je)j2$006Y%-5=6M{tP%FnmSgQcDq-v zYN#UGWcvZYZK3n(T%@732rVyXyjJY!(D)w$1fc6j*^3#6$5HTkn;)}g15+B~B8!zu$(NkP`l3u8?%;LeaxxAz_o00b=9ctli>jeAL zggeVM-bW>{%g&j2czfMI*ySU+u67TVq5-So&f>H&V{ z+SFN|4{_;bw(%g!*RWSmg4ZeuJbIZ6()l=GW^WFcbNJv@o+I=9yc*la(X3|&Wzz-z zP5rq&0>SN0xwpsNH`s#$%71y_uQsq^#kb)OF=Hw7#dH8IPZQm^>)Rpe{1}zbmL11m z`*@g7n$1<#nhG8JC}UKJXs4Nr2@J?i$- z+VIy7GjbT=?60Va3x&hP-gsX*v4TUy!dF><_8JUCMLI=DgV=#1@+}DFA`;)>E87f3 zsaeI6u8cmcm|Z*?-Pf5dDgnPAs`sV|>F-Gxo{QT%(!M)i-Bqtax6 zqsIZiLJIcIz_S9w2I3D^HomV4asyJflmJ9}rbQm<1Q0!7%_gXKL3XKujK5|eK(fd* zp?8fF{;%rh&8SNW{uk!62xI(RkzYF1Z;SkKnE9V7EbZddE6@`$)CGa=f#j(G zo#>$mldGV(&--k7|H-}E-*Hq-Z5wszud?ygw;M-`_$xzE7H46Rc)Sa*(iidNrz>SA~1 zl|6dylzEGbJM^B3iwi&9-4fMHLZcjl?GCa<9A7L0^$@utnY2mcXxhylFB^%3h1vzI z_KUtE7noN5K(Tpt<~=UH5&N1OuuJD`bvrbV&5xVr`^w{N#|w&fXFP6VI+hv^t^?IpCawAR;+nO7ARc7C3J~NsaRKCZ17O2 z8se9@U^ssxGMLq2g!kYYQ~v}}0Z(RAMDu99%;H#@giTrfxI|IKYHpOWn40{#BJMGW zkg9R0z%`YRZxwTm!5YBbCFcuialUwG#ifC^e8`zq`gM7wu|rSqu|i1F-Mp99R9230 zAGbfr%E+beAklJv^V%aZyb%0{^>>+Pj7bc|e{;YCu6lC7g&zfY9rp z5c12f-?#Z~o8Rq5>|gY$4|2?TZ#THbN1&dsBDUW!Cq*_1ovDBFNuyi9mi&z3Mh(E_ z`PathKTkGRKrYgD7KZ{n5&OZefkH6H@lE38OjLuLrk_7gj6#pedA?Y!`qI{{kiN%M z*g4w3X@D95@l3k-w6oG_Y)n-pPM)rd!hs?<7E)n%B zAo9M<14<$z_566p09Xr?v9Qy!MW$dEfGO@wA_>-D0Qy~r!x-eGt2k?mV2g%of9-2+ z+SJw1_Z-1|O%nJtf&!45#0|5XFMj5Yq}<(kI!=dw)qzUeOUwlnrXzvGu{L8lm$cbj z0jUVvhMF4BXA#`c^AJh@d700&Qv=6+%WqXLTu4=k*C6(JB->aLM>T!NldY32e zSV`Y|vD*|h-RlK;;h-mGsHVc)Rd&O%`l7pC_I7p*18xd^^jET;G5dI5q56;+uh~qF zOxg+0!015mB1)0iWOQ*P3|2Q1x5f>|LtXM_O{~^7)7b*ZKe1Nkn@8p}Ffi7n**P)~ z&92MmCOBVc<{wl7;*2d9;SN`%A(YpP@!tLc*V~P(7(I)*6vs*urW%V1J=|oUj+u-t z1Bn*W?mX2h)?%I43e18anO2N2Z~UcsF z^BXd|bS}buVsG3vKERJb9CSkFfZQq}Y&AerLuZDM)~>Ae7kyeS#yz`yfh{XlmRdmn zxSdPvhba@zdrz#AXE~1&U^W26=~y5pZ?nFbC{&lwo_ZoBM>znUuN^pbtI0+ER!x*9 zbhDDxHho6eFok}0@?0brE{R#^e>i3mMGNs(heMV>16{o#5;&-AJH-~zmHE&EWbRDBO z6dh^sn@>aWD8gT<5iM76p>C zyV4qHmOiSBN2mWa9mLOp_`B)VLb)D=ldDNA&PB0pNS_`VKmzodGzv>fxkIrX;@cCSFGp zKRf)X0)#pHZJNaPms!QH&8;M%XUfh?tP@)=FD1xqs+S)(f7He6wx|<(aqW`D6p)Ig zRe?dRUz|#_U{tEQ?mFyqz)BYaB3Q}*>3sPBk`%yo{Q4+$B0nJSc|^Gla8}I#fN{1W z$@X+fe1D#LfowRD4f_7_+i05QbPhukrOEfT&oyn^TW4=(nsnF5CpPpw3Ikg}7fmMp;+=?fM14S`_aQCqSHiAcUM+CrW zy(kTDl?M)f4%{IfO##vD)Gw6~CZc6krZoTK^8o6fKNw?&Y<*U8T!G&v-WB6=->o#Jv98AziTU^DQ}}H(r#e`;`s;uugD4Hrm)@i#_u2>aYI#*I}-EU8N5s02+)vkA@N7xUw{4&xDhY*M2Q-t zq!_+a4<$h?EEvgFnmCc;o={p7M;1B3MNMZYqgXd?NsBK`;K4n&E;jNiIGSe^xk?Fy z-2#BH+u^!H<{7nNg1P~grm4`)?(z$7+_%;n{cK`(4iQ~RJHz)sxmkGqCxB8vkL7<> zw&Y!qJm7#Ty$8lIasPmyBGnaS=K+Gc%Yb-k5aj!RO!qp#EvQx0NA0OCo{kn$^nUJU znWV($dyB`hh+XRO`ZnObi9dK_i zI8ZcX)j_Z!ZQyrj z_&=pHynx-p=mE44|Ckx-e~HT0C*q^glx(qUuckgG9KI{QTH9!0Ws+f_DpFR`toSHX zWME!|LNjnn?ztyp1=;sO()@O|5$CwLmmQsrg-h4Xm7+jw=IKlK>8?UPCJ>asU(X*g zl3o8%5FrgbB}O4tLArk{K*|BQIA8JLHOBw9gxJKxyYqK-kJJ7rWdFYOx0(Linnb3F r%2n`3psmqVmqna)eqRyB5^SRD#WZNHdm=(P$|Cxv9F-a9`{e%vI~ytW literal 0 HcmV?d00001 diff --git a/docs/images/omf-plugin-ocs.jpg b/docs/images/omf-plugin-ocs.jpg index 12d6d25a085e55e94d420f134dc448d2abe36f26..2af48e14c83141ae9c1e00db0a59854b5208a248 100644 GIT binary patch literal 92308 zcmeFZ2V7Iz)-Sqf(nUIg5(Gq)rbv+*lrAC)N{2{q0@5T%iK0}2P!tpt1O${SC7`rO zS3$b;mY_%{0f9h5au@rYv(Mh=ocry)zxUnyd++yLu#&M>X69UT%sI#Wj~2=ZWd=BO zQAb|~prQf*J@5~pU;uY*xSKNo7#aen003YBsHr#r8jzv_|9~hrfc6&}0K~v|0H8^Z z1n9wc4)DD4g8CnyQm?*VC+=j!cG!7v_k_4mJ}EFh%EYYulj9F!b|q3S}aaAmmXEl($ZJ0ZB|O)o!XxSH@Ul`Dhv{%sjy zp-?1~m-g%Y$NMk! z|N62uv=0LTU_ffWE{Yw3dfsJ-a}nk#o2e{x``2RsnP74RVG;Nd2|Vo_Zu$CysPYC# ziv;@L+NU3YG?y>jUqM>Z{x|ns zenbDgU9bp1f8~;_ocx)6@_+X5cY=d`002$zTS2~VF0TGU=RpoR3F&(|NJ|RIo|csb zfPH@dt<{Z@U-(GH!|>00Zdw4KFbe?GPXD~;fC7MbTmZn1`sclqlVG=*007N#%g)#C zZ}ow%R9m!u&S$|^_G#uC0H8~yP&UlKE}sN|yoiot05v-m4LcR36@Y->rK9@g_@$!#x~OSr=?>5{FfuWN1yF}Tjev%RnwEx+Zhso$IhHTzl;5dx3&p8yZim30%-o$E%5bkJ^Pn_v4j1hrlqB!rQh!t6?Nc#$JuG=j-5HcasDd3 zoe!t5>^%mq3rX4KO^hOEjd9%ezI{wQqH>ty`2DW^(z8F;vGD&^&wlOLKl?QfXo4$y z|DXo{X{f2ep`rl~+5@!v#{v2SzZ~>`KNx;F821n6Uk?gc3Dy2LX=v!ce`baQ48MN% zrwPg=sO_Dmi~%e(RN!QyVF#c98I$ld-^G1gOMiBi4Oj9FCmNR>-%# z*e!Vj?aj$Zc~l0!7p$dK?=Bs7tK^P)J-CklX}N+ZL^!eD#x5Zv8P3ZUuzZXo7|l zSg}GDSh0gHNl2Cg^avP%Wy;I0<=j;*BOf}9_#R*IjRK7H{cQFplYdUBp9|>!)#9R` z0yNW|AmLD;{A1cwCS~uHQ23iIh*anP?BP%}VKp%_YGV}O=W;Mx z5*hGn45rOm#k27~Hp!w#b;A&Kn^yF0Sj2vPLWkF-j4+@K91>Vi4w0?mv}`SnqP=O$ z3TIok!S`UZT2- z*!e1uxtlw8@ka;4BA`F$Ua+h!m&lMqb0|O~J>lx!<2+CXSHZU5QvjxlBiQ&A4G5)| zJZ)z$Uv!KD7_lSfFEp&yGs*0*jv|IzVY_@~p)aUo#s7ZBdPGYNs*$2O5Vc1EbHwZD*UJlITi&M06=t3_j>SnmF|ExH)bb3gEX5|r zEA%BAdS1UOdx*e@P=N3lMDKIlcd)ZIMik)DAfj290?=_#fNT{^51FerivpZ1sv!!N zkw^s;;6BKLk4Lh`1}VVzNh1<3bX~nar%?*r|Bz&+;}qaRU`rP1WB`UX9}w&3_ezY&q2L2G z`B4Col~WSfX@Va3Q4Z|Ki4Y}l`lNwve3OUZlE5Nb==sY8uv~;R*qKl6(DFrausw0eGq}m16$ZJ)Fp``a93q^IUA3F`?|qv z3b3AzT)uFlb?Lj z4Q^vZlUFCJ42sk@b7Cbr)UM>jiUa?XXITuwm2FhSijei%qjtK*h*K9cjQ2z}l%gGi zz5N315L>cnmn@#Z+R#B>_QD4n$KG8PwKLVeRfMd5^@5F_AcM2qz?6_{W?_eylHs{+ z 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 literal 93472 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 From a41cc7ae6fe325e50d05c46287d95d25349a037d Mon Sep 17 00:00:00 2001 From: pronoob Date: Mon, 3 Oct 2022 18:54:54 +0530 Subject: [PATCH 29/48] made both local asset and remote asset name same. It was causing failure in assertion at local. (#842) Fixed C north service pair system tests. --- tests/system/python/pair/test_c_north_service_pair.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/python/pair/test_c_north_service_pair.py b/tests/system/python/pair/test_c_north_service_pair.py index 4656b2b2fd..e596c568dc 100644 --- a/tests/system/python/pair/test_c_north_service_pair.py +++ b/tests/system/python/pair/test_c_north_service_pair.py @@ -21,7 +21,7 @@ # Local machine local_south_plugin = "sinusoid" -local_south_asset_name = "sinusoid" +local_south_asset_name = "north_svc_pair_C_sinusoid" local_south_service_name = "Sine #1" local_north_plugin = "httpc" local_north_service_name = "HN #1" @@ -29,7 +29,7 @@ # Remote machine remote_south_plugin = "http_south" remote_south_service_name = "HS #1" -remote_south_asset_name = "north_svc_pair_sinusoid" +remote_south_asset_name = "north_svc_pair_C_sinusoid" remote_north_plugin = "OMF" remote_north_service_name = "NorthReadingsToPI_WebAPI" From 2768a18fe4f0dd526cf463d89fc7779de4584b9a Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Wed, 5 Oct 2022 14:21:58 +0100 Subject: [PATCH 30/48] FOGL-6995 Improve recovery and error messages for missing statistics in (#844) table Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- .../storage/sqlite/common/connection.cpp | 14 +++++++++-- .../storage/sqlitelb/common/connection.cpp | 14 +++++++++-- C/services/north/data_load.cpp | 6 ++++- C/services/south/include/ingest.h | 3 +++ C/services/south/ingest.cpp | 24 +++++++++++++++---- 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/C/plugins/storage/sqlite/common/connection.cpp b/C/plugins/storage/sqlite/common/connection.cpp index a55dab911d..33f2283a97 100644 --- a/C/plugins/storage/sqlite/common/connection.cpp +++ b/C/plugins/storage/sqlite/common/connection.cpp @@ -1356,7 +1356,13 @@ std::size_t arr = data.find("inserts"); int insert = sqlite3_changes(dbHandle); if (insert == 0) - raiseError("insert", "Not all inserts within transaction succeeded"); + { + char buf[100]; + snprintf(buf, sizeof(buf), + "Not all inserts into table '%s.%s' within transaction succeeded", + schema.c_str(), table.c_str()); + raiseError("insert", buf); + } // Return the status return (insert ? ins : -1); @@ -1753,7 +1759,11 @@ vector asset_codes; if (update == 0) { - raiseError("update", "Not all updates within transaction succeeded"); + char buf[100]; + snprintf(buf, sizeof(buf), + "Not all updates of table '%s.%s' within transaction succeeded", + schema.c_str(), table.c_str()); + raiseError("update", buf); return_value = -1; } else diff --git a/C/plugins/storage/sqlitelb/common/connection.cpp b/C/plugins/storage/sqlitelb/common/connection.cpp index a3ccc19286..4f7874e530 100644 --- a/C/plugins/storage/sqlitelb/common/connection.cpp +++ b/C/plugins/storage/sqlitelb/common/connection.cpp @@ -1280,7 +1280,13 @@ std::size_t arr = data.find("inserts"); int insert = sqlite3_changes(dbHandle); if (insert == 0) - raiseError("insert", "Not all inserts within transaction succeeded"); + { + char buf[100]; + snprintf(buf, sizeof(buf), + "Not all inserts within transaction '%s.%s' succeeded", + schema.c_str(), table.c_str()); + raiseError("insert", buf); + } // Return the status return (insert ? ins : -1); @@ -1678,7 +1684,11 @@ SQLBuffer sql; if (update == 0) { - raiseError("update", "Not all updates within transaction succeeded"); + char buf[100]; + snprintf(buf, sizeof(buf), + "Not all updates within transaction '%s.%s' succeeded", + schema.c_str(), table.c_str()); + raiseError("update", buf); return_value = -1; } else diff --git a/C/services/north/data_load.cpp b/C/services/north/data_load.cpp index 6a2d9d9d87..b7fa2d3cc0 100755 --- a/C/services/north/data_load.cpp +++ b/C/services/north/data_load.cpp @@ -553,7 +553,7 @@ void DataLoad::updateStatistic(const string& key, const string& description, uin // Perform UPDATE fledge.statistics SET value = value + x WHERE key = 'name' int row_affected = m_storage->updateTable("statistics", updateValue, wLastStat); - if (row_affected == -1) + if (row_affected < 1) { // The required row is not in the statistics table yet // this situation happens only at the initial setup @@ -578,6 +578,10 @@ void DataLoad::updateStatistic(const string& key, const string& description, uin } } + else if (row_affected > 1) + { + Logger::getLogger()->error("There appear to be multiple rows in the statistics table for %s", key.c_str()); + } } diff --git a/C/services/south/include/ingest.h b/C/services/south/include/ingest.h index 38b8d5ad02..160849624d 100644 --- a/C/services/south/include/ingest.h +++ b/C/services/south/include/ingest.h @@ -29,6 +29,8 @@ #define INGEST_SUFFIX "-Ingest" // Suffix for per service ingest statistic +#define STATS_UPDATE_FAIL_THRESHOLD 10 // After this many update fails try creatign new stats + /** * The ingest class is used to ingest asset readings. * It maintains a queue of readings to be sent to storage, @@ -124,6 +126,7 @@ class Ingest : public ServiceHandler { int m_failCnt; bool m_storageFailed; int m_storesFailed; + int m_statsUpdateFails; }; #endif diff --git a/C/services/south/ingest.cpp b/C/services/south/ingest.cpp index 0d680d5872..410c1ad141 100755 --- a/C/services/south/ingest.cpp +++ b/C/services/south/ingest.cpp @@ -60,7 +60,7 @@ int Ingest::createStatsDbEntry(const string& assetName) string statistics_key = assetName; for (auto & c: statistics_key) c = toupper(c); - // SELECT * FROM fledge.configuration WHERE key = categoryName + // SELECT * FROM fledge.statiatics WHERE key = statistics_key const Condition conditionKey(Equals); Where *wKey = new Where("key", conditionKey, statistics_key); Query qKey(wKey); @@ -215,11 +215,27 @@ void Ingest::updateStats() try { int rv = m_storage.updateTable("statistics", statsUpdates); - if (rv<0) - Logger::getLogger()->info("%s:%d : Update stats failed, rv=%d", __FUNCTION__, __LINE__, rv); + if (rv < 0) + { + if (++m_statsUpdateFails > STATS_UPDATE_FAIL_THRESHOLD) + { + Logger::getLogger()->warn("Update of statistics failure has persisted, attempting recovery"); + createServiceStatsDbEntry(); + statsDbEntriesCache.clear(); + m_statsUpdateFails = 0; + } + else if (m_statsUpdateFails == 1) + { + Logger::getLogger()->warn("Update of statistics failed"); + } + else + { + Logger::getLogger()->warn("Update of statistics still failing"); + } + } else { - m_discardedReadings=0; + m_discardedReadings = 0; statsPendingEntries.clear(); } } From 41b93e605f06399f735af110fa690799cc8c6fcc Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Fri, 7 Oct 2022 10:25:10 +0100 Subject: [PATCH 31/48] Remove debug left in ADH (#846) Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/plugins/common/ocs.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/C/plugins/common/ocs.cpp b/C/plugins/common/ocs.cpp index c30cfd9d57..7dc9002631 100644 --- a/C/plugins/common/ocs.cpp +++ b/C/plugins/common/ocs.cpp @@ -96,8 +96,6 @@ std::string OCS::retrieveToken(const string& clientId, const string& clientSecre StringReplace(payload, "CLIENT_ID_PLACEHOLDER", urlEncode(clientId)); StringReplace(payload, "CLIENT_SECRET_ID_PLACEHOLDER", urlEncode(clientSecret)); - Logger::getLogger()->fatal("FIXME: Encoded payload is %s", payload.c_str()); - // Anonymous auth string authMethod = "a"; endPoint->setAuthMethod (authMethod); From 1c4d2530722e18b84a077891337a81838261735c Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Mon, 10 Oct 2022 11:19:58 +0530 Subject: [PATCH 32/48] schema version bumped to 58 Signed-off-by: ashish-jabble --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 5a7de8415f..782dfcd125 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ fledge_version=2.0.0 -fledge_schema=57 +fledge_schema=58 From 4525c6abecf9546b5710752a6da024c8b2764a5f Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Mon, 10 Oct 2022 11:22:47 +0530 Subject: [PATCH 33/48] AUMRK audit log code schema changes for sqlite engine Signed-off-by: ashish-jabble --- scripts/plugins/storage/sqlite/downgrade/57.sql | 3 +++ scripts/plugins/storage/sqlite/init.sql | 13 +++++++------ scripts/plugins/storage/sqlite/upgrade/58.sql | 3 +++ 3 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 scripts/plugins/storage/sqlite/downgrade/57.sql create mode 100644 scripts/plugins/storage/sqlite/upgrade/58.sql diff --git a/scripts/plugins/storage/sqlite/downgrade/57.sql b/scripts/plugins/storage/sqlite/downgrade/57.sql new file mode 100644 index 0000000000..74c6528466 --- /dev/null +++ b/scripts/plugins/storage/sqlite/downgrade/57.sql @@ -0,0 +1,3 @@ +-- Delete Audit marker log and log codes entry +DELETE from fledge.log WHERE code = 'AUMRK'; +DELETE from fledge.log_codes WHERE code = 'AUMRK'; diff --git a/scripts/plugins/storage/sqlite/init.sql b/scripts/plugins/storage/sqlite/init.sql index de17d8aa6f..8e36d612b9 100644 --- a/scripts/plugins/storage/sqlite/init.sql +++ b/scripts/plugins/storage/sqlite/init.sql @@ -668,7 +668,7 @@ INSERT INTO fledge.log_codes ( code, description ) ( 'SRVRG', 'Service Registered' ), ( 'SRVUN', 'Service Unregistered' ), ( 'SRVFL', 'Service Fail' ), - ( 'SRVRS', 'Service Restart' ), + ( 'SRVRS', 'Service Restart' ), ( 'NHCOM', 'North Process Complete' ), ( 'NHDWN', 'North Destination Unavailable' ), ( 'NHAVL', 'North Destination Available' ), @@ -685,11 +685,12 @@ INSERT INTO fledge.log_codes ( code, description ) ( 'PKGRM', 'Package purged' ), ( 'DSPST', 'Dispatcher Startup' ), ( 'DSPSD', 'Dispatcher Shutdown' ), - ( 'ESSRT', 'External Service Startup' ), - ( 'ESSTP', 'External Service Shutdown' ), - ( 'ASTDP', 'Asset deprecated' ), - ( 'ASTUN', 'Asset un-deprecated' ), - ( 'PIPIN', 'Pip installation' ); + ( 'ESSRT', 'External Service Startup' ), + ( 'ESSTP', 'External Service Shutdown' ), + ( 'ASTDP', 'Asset deprecated' ), + ( 'ASTUN', 'Asset un-deprecated' ), + ( 'PIPIN', 'Pip installation' ), + ( 'AUMRK', 'Audit Log Marker' ); -- -- Configuration parameters diff --git a/scripts/plugins/storage/sqlite/upgrade/58.sql b/scripts/plugins/storage/sqlite/upgrade/58.sql new file mode 100644 index 0000000000..8a76a20a70 --- /dev/null +++ b/scripts/plugins/storage/sqlite/upgrade/58.sql @@ -0,0 +1,3 @@ +-- Audit Log Marker log code +INSERT INTO fledge.log_codes ( code, description ) + VALUES ( 'AUMRK', 'Audit Log Marker' ); \ No newline at end of file From 52f326b6b1de35c26baa788641b0260ba3a6eb0c Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Mon, 10 Oct 2022 11:23:22 +0530 Subject: [PATCH 34/48] AUMRK audit log code schema changes for sqlitelb engine Signed-off-by: ashish-jabble --- scripts/plugins/storage/sqlitelb/downgrade/57.sql | 3 +++ scripts/plugins/storage/sqlitelb/init.sql | 13 +++++++------ scripts/plugins/storage/sqlitelb/upgrade/58.sql | 3 +++ 3 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 scripts/plugins/storage/sqlitelb/downgrade/57.sql create mode 100644 scripts/plugins/storage/sqlitelb/upgrade/58.sql diff --git a/scripts/plugins/storage/sqlitelb/downgrade/57.sql b/scripts/plugins/storage/sqlitelb/downgrade/57.sql new file mode 100644 index 0000000000..74c6528466 --- /dev/null +++ b/scripts/plugins/storage/sqlitelb/downgrade/57.sql @@ -0,0 +1,3 @@ +-- Delete Audit marker log and log codes entry +DELETE from fledge.log WHERE code = 'AUMRK'; +DELETE from fledge.log_codes WHERE code = 'AUMRK'; diff --git a/scripts/plugins/storage/sqlitelb/init.sql b/scripts/plugins/storage/sqlitelb/init.sql index 496c5de958..9721c1a438 100644 --- a/scripts/plugins/storage/sqlitelb/init.sql +++ b/scripts/plugins/storage/sqlitelb/init.sql @@ -652,7 +652,7 @@ INSERT INTO fledge.log_codes ( code, description ) ( 'SRVRG', 'Service Registered' ), ( 'SRVUN', 'Service Unregistered' ), ( 'SRVFL', 'Service Fail' ), - ( 'SRVRS', 'Service Restart' ), + ( 'SRVRS', 'Service Restart' ), ( 'NHCOM', 'North Process Complete' ), ( 'NHDWN', 'North Destination Unavailable' ), ( 'NHAVL', 'North Destination Available' ), @@ -669,11 +669,12 @@ INSERT INTO fledge.log_codes ( code, description ) ( 'PKGRM', 'Package purged' ), ( 'DSPST', 'Dispatcher Startup' ), ( 'DSPSD', 'Dispatcher Shutdown' ), - ( 'ESSRT', 'External Service Startup' ), - ( 'ESSTP', 'External Service Shutdown' ), - ( 'ASTDP', 'Asset deprecated' ), - ( 'ASTUN', 'Asset un-deprecated' ), - ( 'PIPIN', 'Pip installation' ); + ( 'ESSRT', 'External Service Startup' ), + ( 'ESSTP', 'External Service Shutdown' ), + ( 'ASTDP', 'Asset deprecated' ), + ( 'ASTUN', 'Asset un-deprecated' ), + ( 'PIPIN', 'Pip installation' ), + ( 'AUMRK', 'Audit Log Marker' ); -- -- Configuration parameters diff --git a/scripts/plugins/storage/sqlitelb/upgrade/58.sql b/scripts/plugins/storage/sqlitelb/upgrade/58.sql new file mode 100644 index 0000000000..8a76a20a70 --- /dev/null +++ b/scripts/plugins/storage/sqlitelb/upgrade/58.sql @@ -0,0 +1,3 @@ +-- Audit Log Marker log code +INSERT INTO fledge.log_codes ( code, description ) + VALUES ( 'AUMRK', 'Audit Log Marker' ); \ No newline at end of file From 4d6b234f97555c7b53fd576bca58d5b2de074c84 Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Mon, 10 Oct 2022 11:28:44 +0530 Subject: [PATCH 35/48] AUMRK audit log code schema changes for PostgreSQL engine Signed-off-by: ashish-jabble --- scripts/plugins/storage/postgres/downgrade/57.sql | 3 +++ scripts/plugins/storage/postgres/init.sql | 13 +++++++------ scripts/plugins/storage/postgres/upgrade/58.sql | 3 +++ 3 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 scripts/plugins/storage/postgres/downgrade/57.sql create mode 100644 scripts/plugins/storage/postgres/upgrade/58.sql diff --git a/scripts/plugins/storage/postgres/downgrade/57.sql b/scripts/plugins/storage/postgres/downgrade/57.sql new file mode 100644 index 0000000000..74c6528466 --- /dev/null +++ b/scripts/plugins/storage/postgres/downgrade/57.sql @@ -0,0 +1,3 @@ +-- Delete Audit marker log and log codes entry +DELETE from fledge.log WHERE code = 'AUMRK'; +DELETE from fledge.log_codes WHERE code = 'AUMRK'; diff --git a/scripts/plugins/storage/postgres/init.sql b/scripts/plugins/storage/postgres/init.sql index 6bdd7cc2f4..5c4c8160b4 100644 --- a/scripts/plugins/storage/postgres/init.sql +++ b/scripts/plugins/storage/postgres/init.sql @@ -881,7 +881,7 @@ INSERT INTO fledge.log_codes ( code, description ) ( 'SRVRG', 'Service Registered' ), ( 'SRVUN', 'Service Unregistered' ), ( 'SRVFL', 'Service Fail' ), - ( 'SRVRS', 'Service Restart' ), + ( 'SRVRS', 'Service Restart' ), ( 'NHCOM', 'North Process Complete' ), ( 'NHDWN', 'North Destination Unavailable' ), ( 'NHAVL', 'North Destination Available' ), @@ -898,11 +898,12 @@ INSERT INTO fledge.log_codes ( code, description ) ( 'PKGRM', 'Package purged' ), ( 'DSPST', 'Dispatcher Startup' ), ( 'DSPSD', 'Dispatcher Shutdown' ), - ( 'ESSRT', 'External Service Startup' ), - ( 'ESSTP', 'External Service Shutdown' ), - ( 'ASTDP', 'Asset deprecated' ), - ( 'ASTUN', 'Asset un-deprecated' ), - ( 'PIPIN', 'Pip installation' ); + ( 'ESSRT', 'External Service Startup' ), + ( 'ESSTP', 'External Service Shutdown' ), + ( 'ASTDP', 'Asset deprecated' ), + ( 'ASTUN', 'Asset un-deprecated' ), + ( 'PIPIN', 'Pip installation' ), + ( 'AUMRK', 'Audit Log Marker' ); -- -- Configuration parameters diff --git a/scripts/plugins/storage/postgres/upgrade/58.sql b/scripts/plugins/storage/postgres/upgrade/58.sql new file mode 100644 index 0000000000..8a76a20a70 --- /dev/null +++ b/scripts/plugins/storage/postgres/upgrade/58.sql @@ -0,0 +1,3 @@ +-- Audit Log Marker log code +INSERT INTO fledge.log_codes ( code, description ) + VALUES ( 'AUMRK', 'Audit Log Marker' ); \ No newline at end of file From de21032db616b570eda11230c018f90ef00cb5a4 Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Mon, 10 Oct 2022 11:34:09 +0530 Subject: [PATCH 36/48] audit system api tests updated as per new audit log code entry Signed-off-by: ashish-jabble --- tests/system/python/api/test_audit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/python/api/test_audit.py b/tests/system/python/api/test_audit.py index 9d92cfff90..40740fb908 100644 --- a/tests/system/python/api/test_audit.py +++ b/tests/system/python/api/test_audit.py @@ -27,7 +27,7 @@ def test_get_log_codes(self, fledge_url, reset_and_start_fledge): 'SRVFL', 'SRVRS', 'NHCOM', 'NHDWN', 'NHAVL', 'UPEXC', 'BKEXC', 'NTFDL', 'NTFAD', 'NTFSN', 'NTFCL', 'NTFST', 'NTFSD', 'PKGIN', 'PKGUP', 'PKGRM', 'DSPST', 'DSPSD', - 'ESSRT', 'ESSTP', 'ASTDP', 'ASTUN', 'PIPIN'] + 'ESSRT', 'ESSTP', 'ASTDP', 'ASTUN', 'PIPIN', 'AUMRK'] conn = http.client.HTTPConnection(fledge_url) conn.request("GET", '/fledge/audit/logcode') r = conn.getresponse() From b9787601502534e72f2da8a6d8ca935a8d2bd6c7 Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Mon, 10 Oct 2022 15:45:13 +0530 Subject: [PATCH 37/48] since request optional param support added in GET audit API Signed-off-by: ashish-jabble --- python/fledge/services/core/api/audit.py | 34 +++++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/python/fledge/services/core/api/audit.py b/python/fledge/services/core/api/audit.py index 95f17e0cb8..4647d9ed51 100644 --- a/python/fledge/services/core/api/audit.py +++ b/python/fledge/services/core/api/audit.py @@ -144,7 +144,7 @@ async def get_audit_entries(request): curl -X GET http://localhost:8081/fledge/audit?limit=5 - curl -X GET http://localhost:8081/fledge/audit?limit=5&skip=3 + curl -X GET "http://localhost:8081/fledge/audit?limit=5&skip=3" curl -X GET http://localhost:8081/fledge/audit?skip=2 @@ -153,7 +153,9 @@ async def get_audit_entries(request): curl -X GET http://localhost:8081/fledge/audit?source=NTFSD,NTFSN,NTFAD,NTFST,NTFDL,NTFCL curl -X GET http://localhost:8081/fledge/audit?severity=FAILURE - curl -X GET http://localhost:8081/fledge/audit?source=LOGGN&severity=INFORMATION&limit=10 + curl -X GET "http://localhost:8081/fledge/audit?source=LOGGN&severity=INFORMATION&limit=10" + + curl -X GET "http://localhost:8081/fledge/audit?source=CONAD&since=2022-10-10%2009:31:32" """ limit = __DEFAULT_LIMIT @@ -174,6 +176,15 @@ async def get_audit_entries(request): except ValueError: raise web.HTTPBadRequest(reason="Skip/Offset must be a positive integer") + # If microsend is required then add .%f into the __DATE_FORMAT & remove the split from datetime string conversion + __DATE_FORMAT = "%Y-%m-%d %H:%M:%S" + if 'since' in request.query and request.query['since'] != '': + try: + datetime.strptime(request.query['since'], __DATE_FORMAT) + except ValueError: + msg = "Incorrect date format, should be {}".format(__DATE_FORMAT) + raise web.HTTPBadRequest(reason=msg, body=json.dumps({"message": msg})) + source = None source_list = [] if 'source' in request.query and request.query['source'] != '': @@ -235,21 +246,30 @@ async def get_audit_entries(request): # SELECT * FROM log results = await storage_client.query_tbl_with_payload('log', payload.payload()) + rows = results['rows'] + # If 'since' datetime string param is passed then filter the records internally from the actual storage result + if 'since' in request.query: + since_dt = datetime.strptime(request.query['since'].split('.', 1)[0], __DATE_FORMAT) + temp_rows = [] + for row in results["rows"]: + convert_dt = datetime.strptime(row['timestamp'].split('.', 1)[0], __DATE_FORMAT) + if since_dt <= convert_dt: + temp_rows.append(row) + rows = temp_rows + total_count = len(rows) res = [] - for row in results['rows']: + for row in rows: r = dict() r["details"] = row["log"] severity_level = int(row["level"]) r["severity"] = Severity(severity_level).name if severity_level in (0, 1, 2, 4) else "UNKNOWN" r["source"] = row["code"] r["timestamp"] = row["timestamp"] - res.append(r) - except Exception as ex: raise web.HTTPInternalServerError(reason=str(ex)) - - return web.json_response({'audit': res, 'totalCount': total_count}) + else: + return web.json_response({'audit': res, 'totalCount': total_count}) async def get_audit_log_codes(request): From af8bf0e201f0fa4a13c2af02a93b2fc3851ce823 Mon Sep 17 00:00:00 2001 From: Innovative-ashwin <99904321+Innovative-ashwin@users.noreply.github.com> Date: Mon, 10 Oct 2022 16:51:06 +0530 Subject: [PATCH 38/48] C/services/south/ingest.cpp (#847) Signed-off-by: Innovative-ashwin Signed-off-by: Innovative-ashwin --- C/services/south/ingest.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/C/services/south/ingest.cpp b/C/services/south/ingest.cpp index 410c1ad141..cd1a6c034b 100755 --- a/C/services/south/ingest.cpp +++ b/C/services/south/ingest.cpp @@ -1255,15 +1255,9 @@ void Ingest::unDeprecateStorageAssetTrackingRecord(StorageAssetTrackingTuple* cu } } } - else - { - m_logger->error("Failure to get StorageAssetTracking record " - "for service '%s', asset '%s'", - m_serviceName.c_str(), - assetName.c_str()); - } - delete updatedTuple; + if (updatedTuple != nullptr) + delete updatedTuple; } From 10c3d985eff9aee98b3c3eaa62e7969f04fe9611 Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Mon, 10 Oct 2022 16:58:18 +0100 Subject: [PATCH 39/48] Control debug (#851) * Add diagnositcs to help track down issue in control Signed-off-by: Mark Riddoch * add message Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/services/north/north.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/C/services/north/north.cpp b/C/services/north/north.cpp index 25541af599..123ef1bdea 100755 --- a/C/services/north/north.cpp +++ b/C/services/north/north.cpp @@ -1053,7 +1053,8 @@ bool NorthService::sendToService(const string& southService, const string& name, if (res->status_code.compare("200 OK")) { Logger::getLogger()->error("Failed to send set point operation to service %s, %s", - southService.c_str(), res->status_code.c_str()); + southService.c_str(), res->status_code.c_str()); + Logger::getLogger()->error("Failed Payload: %s", payload.c_str()); return false; } } catch (exception& e) { @@ -1103,8 +1104,11 @@ bool NorthService::sendToDispatcher(const string& path, const string& payload) auto res = http.request("POST", path, payload, headers); if (res->status_code.compare("202 Accepted")) { - Logger::getLogger()->error("Failed to send control operation to dispatcher service, %s", - res->status_code.c_str()); + Logger::getLogger()->error( + "Failed to send control operation '%s' to dispatcher service, %s %s", + path.c_str(), res->status_code.c_str(), + res->content.string().c_str()); + Logger::getLogger()->error("Failed Payload: %s", payload.c_str()); return false; } } catch (exception& e) { From 4983ed0cedc993033d1a2b42877cb4d74f90be22 Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Tue, 11 Oct 2022 10:59:44 +0530 Subject: [PATCH 40/48] private repo handling added & other code refactoring in documentation scripts Signed-off-by: ashish-jabble --- docs/scripts/fledge_plugin_list | 11 ++++--- docs/scripts/plugin_and_service_documentation | 31 ++++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/docs/scripts/fledge_plugin_list b/docs/scripts/fledge_plugin_list index 2bcf967b98..62a2273a5f 100755 --- a/docs/scripts/fledge_plugin_list +++ b/docs/scripts/fledge_plugin_list @@ -36,9 +36,10 @@ function table { output=$1 rm -f $output +header="Authorization: token ${GITHUB_ACCESS_TOKEN}" # Get total number of respository pages in fledge org. -fledgeRepoPagesCount=`curl -sI https://api.github.com/orgs/fledge-iot/repos | grep -oP '\d+(?=>; rel="last")'` -fledgeRepos=$(curl -sX GET https://api.github.com/orgs/fledge-iot/repos\?page=[1-$fledgeRepoPagesCount]) +fledgeRepoPagesCount=$(curl -sI https://api.github.com/orgs/fledge-iot/repos | grep -oP '\d+(?=>; rel="last")') +fledgeRepos=$(curl -H "$header" -sX GET https://api.github.com/orgs/fledge-iot/repos\?page=[1-$fledgeRepoPagesCount]) fledgeRepos="$(echo $fledgeRepos | sed 's/\] \[/,/g')" fetchTopicReposPyScript=' import json,sys;\ @@ -46,9 +47,9 @@ repos=json.load(sys.stdin);\ fRepos = [r["name"] for r in repos["items"]];\ print("\n".join(fRepos)); ' -fledge_wip_repos=$(curl -sX GET -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=topic:wip+org:fledge-iot) -fledge_poc_repos=$(curl -sX GET -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=topic:poc+org:fledge-iot) -fledge_internal_repos=$(curl -sX GET -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=internal:wip+org:fledge-iot) +fledge_wip_repos=$(curl -sX GET -H "$header" -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=topic:wip+org:fledge-iot) +fledge_poc_repos=$(curl -sX GET -H "$header" -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=topic:poc+org:fledge-iot) +fledge_internal_repos=$(curl -sX GET -H "$header" -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=topic:internal+org:fledge-iot) fledge_wip_repos_name=$(echo ${fledge_wip_repos} | python3 -c "$fetchTopicReposPyScript" | sort -f) fledge_poc_repos_name=$(echo ${fledge_poc_repos} | python3 -c "$fetchTopicReposPyScript" | sort -f) fledge_internal_repos_name=$(echo ${fledge_internal_repos} | python3 -c "$fetchTopicReposPyScript" | sort -f) diff --git a/docs/scripts/plugin_and_service_documentation b/docs/scripts/plugin_and_service_documentation index 0b9241fbda..da47095039 100644 --- a/docs/scripts/plugin_and_service_documentation +++ b/docs/scripts/plugin_and_service_documentation @@ -27,22 +27,22 @@ function plugin_and_service_doc { repo_name=$1 dest=$2 dir_type=$3 - product=`echo ${repo_name} | sed -e 's/-.*//'` + product=$(echo ${repo_name} | sed -e 's/-.*//') org=fledge-iot - type=`echo ${repo_name} | sed -e 's/fledge-//' -e 's/-.*//'` - name=`echo ${repo_name} | sed -e 's/fledge-//' -e "s/${type}-//"` + type=$(echo ${repo_name} | sed -e 's/fledge-//' -e 's/-.*//') + name=$(echo ${repo_name} | sed -e 's/fledge-//' -e "s/${type}-//") mkdir -p /tmp/doc.$$ cd /tmp/doc.$$ git clone -b ${DOCBRANCH} --single-branch https://github.com/${org}/${repo_name}.git if [[ ${type} != "service" ]]; then # cloned directory replaced with installed directory name which is defined in Package file for each repo - installed_plugin_dir_name=`cat ${repo_name}/Package | grep plugin_install_dirname= | sed -e "s/plugin_install_dirname=//g"` + installed_plugin_dir_name=$(cat ${repo_name}/Package | grep plugin_install_dirname= | sed -e "s/plugin_install_dirname=//g") if [[ ${installed_plugin_dir_name} == "\${plugin_name}" ]]; then - installed_plugin_dir_name=`cat ${repo_name}/Package | grep plugin_name= | sed -e "s/plugin_name=//g"` + installed_plugin_dir_name=$(cat ${repo_name}/Package | grep plugin_name= | sed -e "s/plugin_name=//g") fi - old_plugin_name=`echo ${repo_name} | cut -d '-' -f3-` - new_plugin_name=`echo ${repo_name/$old_plugin_name/$installed_plugin_dir_name}` + old_plugin_name=$(echo ${repo_name} | cut -d '-' -f3-) + new_plugin_name=$(echo ${repo_name/$old_plugin_name/$installed_plugin_dir_name}) if [[ ${repo_name} != ${new_plugin_name} ]]; then mv ${repo_name} ${new_plugin_name} fi @@ -115,9 +115,10 @@ Fledge Notification Delivery Plugins EOFNOTIFY +header="Authorization: token ${GITHUB_ACCESS_TOKEN}" # Get total number of respository pages in fledge org. -fledgeRepoPagesCount=`curl -sI https://api.github.com/orgs/fledge-iot/repos | grep -oP '\d+(?=>; rel="last")'` -fledgeRepos=$(curl -sX GET https://api.github.com/orgs/fledge-iot/repos\?page=[1-$fledgeRepoPagesCount]) +fledgeRepoPagesCount=$(curl -sI https://api.github.com/orgs/fledge-iot/repos | grep -oP '\d+(?=>; rel="last")') +fledgeRepos=$(curl -H "$header" -sX GET https://api.github.com/orgs/fledge-iot/repos\?page=[1-$fledgeRepoPagesCount]) fledgeRepos="$(echo $fledgeRepos | sed 's/\] \[/,/g')" fetchTopicReposPyScript=' import json,sys;\ @@ -125,9 +126,9 @@ repos=json.load(sys.stdin);\ fRepos = [r["name"] for r in repos["items"]];\ print("\n".join(fRepos)); ' -fledge_wip_repos=$(curl -sX GET -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=topic:wip+org:fledge-iot) -fledge_poc_repos=$(curl -sX GET -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=topic:poc+org:fledge-iot) -fledge_internal_repos=$(curl -sX GET -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=internal:wip+org:fledge-iot) +fledge_wip_repos=$(curl -sX GET -H "$header" -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=topic:wip+org:fledge-iot) +fledge_poc_repos=$(curl -sX GET -H "$header" -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=topic:poc+org:fledge-iot) +fledge_internal_repos=$(curl -sX GET -H "$header" -H "Accept: application/vnd.github.mercy-preview+json" https://api.github.com/search/repositories?q=topic:internal+org:fledge-iot) fledge_wip_repos_name=$(echo ${fledge_wip_repos} | python3 -c "$fetchTopicReposPyScript" | sort -f) fledge_poc_repos_name=$(echo ${fledge_poc_repos} | python3 -c "$fetchTopicReposPyScript" | sort -f) fledge_internal_repos_name=$(echo ${fledge_internal_repos} | python3 -c "$fetchTopicReposPyScript" | sort -f) @@ -146,7 +147,7 @@ REPOSITORIES=$(echo ${fledgeRepos} | python3 -c "$fetchFledgeReposPyScript" | so echo "REPOS LIST: "${REPOSITORIES} for repo in ${REPOSITORIES} do - type=`echo $repo | sed -e 's/fledge-//' -e 's/foglamp-//' -e 's/-.*//'` + type=$(echo $repo | sed -e 's/fledge-//' -e 's/foglamp-//' -e 's/-.*//') if [ "$type" = "south" -o "$type" = "north" -o $type = "filter" -o $type = "rule" -o $type = "notify" ]; then dest=plugins/${type}.rst plugin_and_service_doc $repo $dest "plugins" @@ -163,7 +164,7 @@ cat OMF.rst >> plugins/fledge-north-OMF/index.rst sed -i -e 's/Naming_Scheme/Naming_Scheme_plugin/' plugins/fledge-north-OMF/index.rst # Create the Threshold rule documentation mkdir plugins/fledge-rule-Threshold -ln -s `pwd`/fledge-rule-Threshold/images plugins/fledge-rule-Threshold/images +ln -s $(pwd)/fledge-rule-Threshold/images plugins/fledge-rule-Threshold/images echo '.. include:: ../../fledge-rule-Threshold/index.rst' > plugins/fledge-rule-Threshold/index.rst # Always create a fresh set of Service documentation @@ -187,7 +188,7 @@ SERVICE_REPOS=$(echo "${REPOSITORIES}" | grep -o "[a-zA-Z0-9\-]*-service-[a-zA-Z echo "SERVICE REPOS LIST: "${SERVICE_REPOS} for repo in ${SERVICE_REPOS} do - type=`echo $repo | sed -e 's/fledge-//' -e 's/foglamp-//' -e 's/-.*//'` + type=$(echo $repo | sed -e 's/fledge-//' -e 's/foglamp-//' -e 's/-.*//') dest=services/index.rst plugin_and_service_doc $repo $dest "services" done From 3b76a01e4be5338da7ee55f1a3b7d98d0ef43638 Mon Sep 17 00:00:00 2001 From: ashish-jabble Date: Tue, 11 Oct 2022 11:25:23 +0530 Subject: [PATCH 41/48] some conditions added for environment variables & repository clone with username & githubaccesstoken Signed-off-by: ashish-jabble --- docs/scripts/fledge_plugin_list | 5 +++++ docs/scripts/plugin_and_service_documentation | 12 +++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/scripts/fledge_plugin_list b/docs/scripts/fledge_plugin_list index 62a2273a5f..d773d942ce 100755 --- a/docs/scripts/fledge_plugin_list +++ b/docs/scripts/fledge_plugin_list @@ -34,6 +34,11 @@ function table { echo "" >> "$output" } +if [[ "${GITHUB_ACCESS_TOKEN}" == "" ]]; then + echo "You must have set a GitHub access token environment variable; export GITHUB_ACCESS_TOKEN=YOUR_ACCESS_TOKEN" + exit 1 +fi + output=$1 rm -f $output header="Authorization: token ${GITHUB_ACCESS_TOKEN}" diff --git a/docs/scripts/plugin_and_service_documentation b/docs/scripts/plugin_and_service_documentation index da47095039..31771ef462 100644 --- a/docs/scripts/plugin_and_service_documentation +++ b/docs/scripts/plugin_and_service_documentation @@ -33,7 +33,7 @@ function plugin_and_service_doc { name=$(echo ${repo_name} | sed -e 's/fledge-//' -e "s/${type}-//") mkdir -p /tmp/doc.$$ cd /tmp/doc.$$ - git clone -b ${DOCBRANCH} --single-branch https://github.com/${org}/${repo_name}.git + git clone -b ${DOCBRANCH} --single-branch https://${USERNAME}:${GITHUB_ACCESS_TOKEN}@github.com/${org}/${repo_name}.git if [[ ${type} != "service" ]]; then # cloned directory replaced with installed directory name which is defined in Package file for each repo @@ -115,6 +115,16 @@ Fledge Notification Delivery Plugins EOFNOTIFY +if [[ "${USERNAME}" == "" ]]; then + echo "You must have set a GitHub username environment variable; export USERNAME=YOUR_USERNAME" + exit 1 +fi + +if [[ "${GITHUB_ACCESS_TOKEN}" == "" ]]; then + echo "You must have set a GitHub access token environment variable; export GITHUB_ACCESS_TOKEN=YOUR_ACCESS_TOKEN" + exit 1 +fi + header="Authorization: token ${GITHUB_ACCESS_TOKEN}" # Get total number of respository pages in fledge org. fledgeRepoPagesCount=$(curl -sI https://api.github.com/orgs/fledge-iot/repos | grep -oP '\d+(?=>; rel="last")') From ef09c5b61892de639e8895b163f9c851b13211b5 Mon Sep 17 00:00:00 2001 From: Praveen Garg Date: Tue, 11 Oct 2022 13:13:05 +0530 Subject: [PATCH 42/48] FOGL-7005 Fix enable/disable a schedule causing double audit entries for Schedule Change event (#849) * prevent double audit entry for enable/disable call; allow for new schedule as new schedule gets added enabled false initialy Signed-off-by: Praveen Garg --- .../services/core/scheduler/scheduler.py | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/python/fledge/services/core/scheduler/scheduler.py b/python/fledge/services/core/scheduler/scheduler.py index ca48a3eb57..91ee7ba0ec 100644 --- a/python/fledge/services/core/scheduler/scheduler.py +++ b/python/fledge/services/core/scheduler/scheduler.py @@ -1159,6 +1159,7 @@ async def save_schedule(self, schedule: Schedule, is_enabled_modified=None, dryr if dryrun and is_new_schedule: await self._start_task(schedule_row, dryrun=True) return + if is_enabled_modified is not None: if previous_enabled is None: # New Schedule # For a new schedule, if enabled is set to True, the schedule will be enabled. @@ -1169,9 +1170,9 @@ async def save_schedule(self, schedule: Schedule, is_enabled_modified=None, dryr bypass_check = True if previous_enabled != schedule.enabled else None if is_enabled_modified is True: - await self.enable_schedule(schedule.schedule_id, bypass_check=bypass_check) + await self.enable_schedule(schedule.schedule_id, bypass_check=bypass_check, record_audit_trail=is_new_schedule) else: - await self.disable_schedule(schedule.schedule_id, bypass_check=bypass_check) + await self.disable_schedule(schedule.schedule_id, bypass_check=bypass_check, record_audit_trail=is_new_schedule) async def remove_service_from_task_processes(self, service_name): """ @@ -1214,7 +1215,7 @@ async def remove_service_from_task_processes(self, service_name): schedule_type)) return False - async def disable_schedule(self, schedule_id: uuid.UUID, bypass_check=None): + async def disable_schedule(self, schedule_id: uuid.UUID, bypass_check=None, record_audit_trail=True): """ Find running Schedule, Terminate running process, Disable Schedule, Update database @@ -1317,12 +1318,13 @@ async def disable_schedule(self, schedule_id: uuid.UUID, bypass_check=None): schedule.name, str(schedule_id), schedule.process_name) - audit = AuditLogger(self._storage_async) - sch = await self.get_schedule(schedule_id) - await audit.information('SCHCH', {'schedule': sch.toDict()}) + if record_audit_trail: + audit = AuditLogger(self._storage_async) + sch = await self.get_schedule(schedule_id) + await audit.information('SCHCH', {'schedule': sch.toDict()}) return True, "Schedule successfully disabled" - async def enable_schedule(self, schedule_id: uuid.UUID, bypass_check=None): + async def enable_schedule(self, schedule_id: uuid.UUID, bypass_check=None, record_audit_trail=True): """ Get Schedule, Enable Schedule, Update database, Start Schedule @@ -1368,9 +1370,10 @@ async def enable_schedule(self, schedule_id: uuid.UUID, bypass_check=None): schedule.name, str(schedule_id), schedule.process_name) - audit = AuditLogger(self._storage_async) - sch = await self.get_schedule(schedule_id) - await audit.information('SCHCH', { 'schedule': sch.toDict() }) + if record_audit_trail: + audit = AuditLogger(self._storage_async) + sch = await self.get_schedule(schedule_id) + await audit.information('SCHCH', { 'schedule': sch.toDict() }) return True, "Schedule successfully enabled" async def queue_task(self, schedule_id: uuid.UUID, start_now=True) -> None: From 191e60fa15f2682aab61cb798800c01eac0d07ce Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Tue, 11 Oct 2022 14:12:24 +0100 Subject: [PATCH 43/48] FOGL-7009: escape quotes in write values and operation parameters (#852) * FOGL-7009: escape quotes in write values and operation parameters Signed-off-by: Mark Riddoch * Fix incorrect quoting Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/services/north/north.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/C/services/north/north.cpp b/C/services/north/north.cpp index 123ef1bdea..e953db9395 100755 --- a/C/services/north/north.cpp +++ b/C/services/north/north.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #define SERVICE_TYPE "Northbound" @@ -877,7 +878,9 @@ bool NorthService::write(const string& name, const string& value, const ControlD payload += "\"write\" : { \""; payload += name; payload += "\" : \""; - payload += value; + string escaped = value; + StringEscapeQuotes(escaped); + payload += escaped; payload += "\" } }"; return sendToDispatcher("/dispatch/write", payload); } @@ -920,7 +923,9 @@ bool NorthService::write(const string& name, const string& value, const ControlD payload += ", \"write\" : { \""; payload += name; payload += "\" : \""; - payload += value; + string escaped = name; + StringEscapeQuotes(escaped); + payload += escaped; payload += "\" } }"; return sendToDispatcher("/dispatch/write", payload); } @@ -954,7 +959,9 @@ int NorthService::operation(const string& name, int paramCount, char *names[], payload += "\""; payload += names[i]; payload += "\": \""; - payload += parameters[i]; + string escaped = parameters[i]; + StringEscapeQuotes(escaped); + payload += escaped; payload += "\""; if (i < paramCount -1) payload += ","; @@ -1004,18 +1011,20 @@ int NorthService::operation(const string& name, int paramCount, char *names[], c } payload += ", \"operation\" : { \""; payload += name; - payload += "\" : { \""; + payload += "\" : { "; for (int i = 0; i < paramCount; i++) { payload += "\""; payload += names[i]; payload += "\": \""; - payload += parameters[i]; + string escaped = parameters[i]; + StringEscapeQuotes(escaped); + payload += escaped; payload += "\""; if (i < paramCount -1) payload += ","; } - payload += "\" } }"; + payload += "} } }"; sendToDispatcher("/dispatch/operation", payload); return -1; } From ffd02ae3a92976952f36283f1079df685a89663b Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Wed, 12 Oct 2022 15:31:05 +0100 Subject: [PATCH 44/48] FOGL-7001 Add basic healthcheck option (#845) * FOGL-7001 Add basic healthcheck option Signed-off-by: Mark Riddoch * Allow for authentication Signed-off-by: Mark Riddoch * Add current service health Signed-off-by: Mark Riddoch * Correct output of unresponsive services Signed-off-by: Mark Riddoch * Address review comments Signed-off-by: Mark Riddoch * Move from jq to Python to process JSON Signed-off-by: Mark Riddoch * Resolve review comments Signed-off-by: Mark Riddoch * Address review comments Signed-off-by: Mark Riddoch * Address review comments Signed-off-by: Mark Riddoch * Address review comments Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- scripts/common/audittime.py | 17 ++++ scripts/common/disk_usage.py | 15 ++++ scripts/common/loglevel.py | 15 ++++ scripts/common/service_status.py | 14 ++++ scripts/fledge | 135 ++++++++++++++++++++++++++++++- 5 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 scripts/common/audittime.py create mode 100644 scripts/common/disk_usage.py create mode 100644 scripts/common/loglevel.py create mode 100644 scripts/common/service_status.py diff --git a/scripts/common/audittime.py b/scripts/common/audittime.py new file mode 100644 index 0000000000..09e88f4b5f --- /dev/null +++ b/scripts/common/audittime.py @@ -0,0 +1,17 @@ +""" +Extract the audit entries that have a timestamp that starts with +the timestamp string passed in as an argument. The output is +the details/name tag of the audit entry. + +The script takes as input the output of the GET /fledge/audit API call +""" + +import json +import sys + +if __name__ == '__main__': + json = json.loads(sys.stdin.readline()) + ts = sys.argv[1] + for audit in json["audit"]: + if audit["timestamp"].startswith(ts): + print(audit["details"]["name"]) diff --git a/scripts/common/disk_usage.py b/scripts/common/disk_usage.py new file mode 100644 index 0000000000..ed14cf002d --- /dev/null +++ b/scripts/common/disk_usage.py @@ -0,0 +1,15 @@ +""" +Extract the disk usage percentage and print it if the percentage +is greater than or equal to a value passed in. +The script takes as input the output of the GET /fledge/health/logging +or GET /fledge/health/storage API call +""" +import json +import sys + +if __name__ == '__main__': + json = json.loads(sys.stdin.readline()) + item = json["disk"] + usage=item["usage"] + if usage >= int(sys.argv[1]): + print(usage) diff --git a/scripts/common/loglevel.py b/scripts/common/loglevel.py new file mode 100644 index 0000000000..d2d8f268e5 --- /dev/null +++ b/scripts/common/loglevel.py @@ -0,0 +1,15 @@ +""" +Extract the names of services that have the current log level set +to a level passed in as an argument. The script takes as input the +output of the GET /fledge/health/logging API call +""" + +import json +import sys + +if __name__ == '__main__': + level = sys.argv[1] + json = json.loads(sys.stdin.readline()) + for service in json["levels"]: + if service["level"] == level: + print(service["name"]) diff --git a/scripts/common/service_status.py b/scripts/common/service_status.py new file mode 100644 index 0000000000..27292e89c8 --- /dev/null +++ b/scripts/common/service_status.py @@ -0,0 +1,14 @@ +""" +Utility to extract the names of services in a particular state given the output of +the API call GET /fledge/services +""" + +import json +import sys + +if __name__ == '__main__': + json = json.loads(sys.stdin.readline()) + state = sys.argv[1] + for service in json["services"]: + if service["status"] == state: + print(service["name"]) diff --git a/scripts/fledge b/scripts/fledge index c9525c8194..e3f3a875cd 100755 --- a/scripts/fledge +++ b/scripts/fledge @@ -22,7 +22,7 @@ set -e # # This is the startup script for fledge # -USAGE="Usage: `basename ${0}` {start|start --safe-mode|stop|status|reset|purge|kill|help|version}" +USAGE="Usage: `basename ${0}` {start|start --safe-mode|stop|status|reset|purge|kill|healthcheck|help|version}" # Check FLEDGE_ROOT if [ -z ${FLEDGE_ROOT+x} ]; then @@ -616,6 +616,7 @@ Arguments: stop - Stop all Fledge services and processes kill - Kill all Fledge services and processes status - Show the status for the Fledge services + healthcheck - Perform a number of checks on the health of the system, Fledge must be running reset - Restore Fledge factory settings WARNING! This command will destroy all your data! purge - Purge all readings data and non-configuration data. @@ -636,6 +637,135 @@ fledge_purge() { source "$FLEDGE_ROOT/scripts/storage" purge } +# Perform a healthcheck on the Fledge instance +fledge_healthcheck() { + + result=`fledge_status "silent"` + if [[ $result != "0" ]]; then + fledge_log "info" "Fledge appears not to be running, healthcheck should be performed on a running system . Start Fledge first." "all" "pretty" + exit 0 + fi + + echo Fledge Healthcheck + echo ================== + echo + + auth="optional" + result=`curl -k -s ${REST_API_URL}/fledge/health/logging` + + if [[ "${result}" == "401"* ]]; then + token=`fledge_authenticate` + if [[ "${token}" =~ "failed" ]]; then + fledge_log "info" "Failed authentication when attempting to run fledge healthcheck." "all" "pretty" + echo "Authentication failed." + exit 0 + fi + result=`curl -k -s -H "authorization: $token" ${REST_API_URL}/fledge/health/logging` + auth="required" + fi + + a=`echo $result | python3 -m scripts.common.loglevel info` + if [[ "$a" != "" ]]; then + echo The following services have a logging level set to info: + for i in $a; do + echo $i | sed -e s/\"//g -e 's/^/ /' + done + echo This is probably too high and may result in large log files + echo + fi + + a=`echo $result | python3 -m scripts.common.loglevel debug` + if [[ "$a" != "" ]]; then + echo The following services have a logging level set to debug: + for i in $a; do + echo $i | sed -e s/\"//g -e 's/^/ /' + done + echo This is probably too high and may result in large log files + echo + fi + + a=`echo $result | python3 -m scripts.common.disk_usage 80` + if [[ "$a" != "" ]]; then + echo The disk space in the logging directory is low, $a% + echo + fi + + if [[ "${auth}" == "required" ]]; then + result=`curl -k -s -H "authorization: $token" ${REST_API_URL}/fledge/health/storage` + else + result=`curl -s ${REST_API_URL}/fledge/health/storage` + fi + a=`echo $result | python3 -m scripts.common.disk_usage 80` + if [[ "$a" != "" ]]; then + echo The disk space in the storage directory is low, $a% + echo + fi + + # the && touch is a trick to defeat the fact we have done a set -e + service rsyslog status >/dev/null && touch /dev/null + status=$? + if [ $status -ne 0 ]; then + echo The rsyslog service does not appear to be running on the machine + echo No log entries will be seen on this machine, plesse restart the Linux service. + echo + fi + + month=`date +%Y-%m-%d` + if [[ "${auth}" == "required" ]]; then + result=`curl -k -s -H "authorization: $token" ${REST_API_URL}/fledge/audit?source=SRVFL` + else + result=`curl -s ${REST_API_URL}/fledge/audit?source=SRVFL` + fi + tmpname=/tmp/fledge.$$ + echo $result | python3 -m scripts.common.audittime $month | sort | uniq -c >$tmpname + if [[ -s $tmpname ]]; then + echo Some services have failed at least once today + echo "No. Failures | Service" + echo "--------------+--------------------" + sed -E 's/([0-9]) / \1 | /' $tmpname + echo + fi + rm $tmpname + + echo Service State + issue=none + if [[ "${auth}" == "required" ]]; then + result=`curl -k -s -H "authorization: $token" ${REST_API_URL}/fledge/service` + else + result=`curl -s ${REST_API_URL}/fledge/service` + fi + a=`echo $result | python3 -m scripts.common.service_status unresponsive` + if [[ "$a" != "" ]]; then + echo The following services are unresponsive: + for i in $a; do + echo $i | sed -e s/\"//g -e 's/^/ /' + done + issue="some" + fi + a=`echo $result | python3 -m scripts.common.service_status failed` + if [[ "$a" != "" ]]; then + echo The following services have failed: + for i in $a; do + echo $i | sed -e s/\"//g -e 's/^/ /' + done + issue="some" + fi + a=`echo $result | python3 -m scripts.common.service_status shutdown` + if [[ "$a" != "" ]]; then + echo The following services are shutdown: + for i in $a; do + echo $i | sed -e s/\"//g -e 's/^/ /' + done + issue="some" + fi + if [[ "$issue" == "none" ]]; then + echo All services are running + fi + echo + + echo Healthcheck completed +} + ### Main Logic ### # Set FLEDGE_DATA if it does not exist @@ -736,6 +866,9 @@ case "$1" in purge) fledge_purge ;; + healthcheck) + fledge_healthcheck + ;; help) fledge_help ;; From 3a92d1786fc58dec499f335b79106840d0c7c8bb Mon Sep 17 00:00:00 2001 From: Mark Riddoch Date: Wed, 12 Oct 2022 16:56:41 +0100 Subject: [PATCH 45/48] FOGL-7039 improve control operation failure diagnostics (#854) Signed-off-by: Mark Riddoch Signed-off-by: Mark Riddoch --- C/services/south/south_api.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/C/services/south/south_api.cpp b/C/services/south/south_api.cpp index 0825725114..c03eaf11a1 100644 --- a/C/services/south/south_api.cpp +++ b/C/services/south/south_api.cpp @@ -219,7 +219,7 @@ void SouthApi::operation(shared_ptr response, } else if (doc.HasMember("parameters")) { - string responsePayload = QUOTE({ "message" : "If present, parameters must be a JSON object" }); + string responsePayload = QUOTE({ "message" : "If present, parameters of an operation must be a JSON object" }); m_service->respond(response, SimpleWeb::StatusCode::client_error_bad_request,responsePayload); return; } @@ -235,7 +235,7 @@ void SouthApi::operation(shared_ptr response, } else { - string responsePayload = QUOTE({ "status" : "failed" }); + string responsePayload = QUOTE({ "status" : "plugin returned failed status for operation" }); m_service->respond(response, SimpleWeb::StatusCode::client_error_bad_request,responsePayload); } return; @@ -248,6 +248,12 @@ void SouthApi::operation(shared_ptr response, return; } } + else + { + string responsePayload = QUOTE({ "status" : "failed to parse operation payload" }); + m_service->respond(response, SimpleWeb::StatusCode::client_error_bad_request,responsePayload); + return; + } } catch (exception &e) { } string responsePayload = QUOTE({ "status" : "failed" }); From 5cdf9c94dd6f72d279bfd9b2c488503785566e98 Mon Sep 17 00:00:00 2001 From: pronoob Date: Mon, 17 Oct 2022 20:15:02 +0530 Subject: [PATCH 46/48] commnted out fixtures for cleaning pi specially for connector relay. (#855) Commented out fixtures for cleaning pi specially for connector relay. --- tests/system/python/e2e/test_e2e_coap_PI.py | 9 +++++++-- tests/system/python/e2e/test_e2e_csv_PI.py | 9 +++++++-- .../system/python/e2e/test_e2e_csv_multi_filter_pi.py | 9 +++++++-- tests/system/python/e2e/test_e2e_expr_pi.py | 9 +++++++-- .../system/python/e2e/test_e2e_filter_fft_threshold.py | 9 +++++++-- tests/system/python/e2e/test_e2e_modbus_c_pi.py | 9 +++++++-- tests/system/python/e2e/test_e2e_pi_scaleset.py | 9 +++++++-- tests/system/python/e2e/test_e2e_vary_asset_http_pi.py | 10 +++++++--- tests/system/python/pair/test_e2e_fledge_pair.py | 9 +++++++-- 9 files changed, 63 insertions(+), 19 deletions(-) diff --git a/tests/system/python/e2e/test_e2e_coap_PI.py b/tests/system/python/e2e/test_e2e_coap_PI.py index 2448d462b0..bfc70cf069 100644 --- a/tests/system/python/e2e/test_e2e_coap_PI.py +++ b/tests/system/python/e2e/test_e2e_coap_PI.py @@ -77,8 +77,13 @@ def start_south_north(reset_and_start_fledge, add_south, start_north_pi_server_c dp_list = ['sensor', ''] asset_dict = {} asset_dict[asset_name] = dp_list - clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, - [], asset_dict) + # For connector relay we should not delete PI Point because + # when the PI point is created again (after deletion) the compressing attribute for it + # is always true. That means all the data is not stored in PI data archive. + # We lose a large proportion of the data because of compressing attribute. + # This is problematic for the fixture that verifies the data stored in PI. + # clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, + # [], asset_dict) # Define the template file for fogbench fogbench_template_path = os.path.join( diff --git a/tests/system/python/e2e/test_e2e_csv_PI.py b/tests/system/python/e2e/test_e2e_csv_PI.py index 44531f01bc..98f8fcf3bb 100644 --- a/tests/system/python/e2e/test_e2e_csv_PI.py +++ b/tests/system/python/e2e/test_e2e_csv_PI.py @@ -71,8 +71,13 @@ def start_south_north(reset_and_start_fledge, add_south, start_north_pi_server_c dp_list = ['ivalue', 'fvalue', 'svalue', ''] asset_dict = {} asset_dict[asset_name] = dp_list - clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, - [], asset_dict) + # For connector relay we should not delete PI Point because + # when the PI point is created again (after deletion) the compressing attribute for it + # is always true. That means all the data is not stored in PI data archive. + # We lose a large proportion of the data because of compressing attribute. + # This is problematic for the fixture that verifies the data stored in PI. + # clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, + # [], asset_dict) # Define configuration of fledge south playback service south_config = {"assetName": {"value": "{}".format(asset_name)}, "csvFilename": {"value": "{}".format(CSV_NAME)}, diff --git a/tests/system/python/e2e/test_e2e_csv_multi_filter_pi.py b/tests/system/python/e2e/test_e2e_csv_multi_filter_pi.py index 1b3da84c8e..48dbf9cba7 100644 --- a/tests/system/python/e2e/test_e2e_csv_multi_filter_pi.py +++ b/tests/system/python/e2e/test_e2e_csv_multi_filter_pi.py @@ -72,8 +72,13 @@ def start_south_north(self, reset_and_start_fledge, add_south, enable_schedule, # 3. ivaluecrest 4. ivaluepeak asset_dict = {} asset_dict['e2e_filters_RMS'] = dp_list - clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, - [], asset_dict) + # For connector relay we should not delete PI Point because + # when the PI point is created again (after deletion) the compressing attribute for it + # is always true. That means all the data is not stored in PI data archive. + # We lose a large proportion of the data because of compressing attribute. + # This is problematic for the fixture that verifies the data stored in PI. + # clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, + # [], asset_dict) # Define configuration of fledge south playback service south_config = {"assetName": {"value": "{}".format(asset_name)}, diff --git a/tests/system/python/e2e/test_e2e_expr_pi.py b/tests/system/python/e2e/test_e2e_expr_pi.py index bcb635c447..f4ba453340 100644 --- a/tests/system/python/e2e/test_e2e_expr_pi.py +++ b/tests/system/python/e2e/test_e2e_expr_pi.py @@ -70,8 +70,13 @@ def start_south_north(self, reset_and_start_fledge, add_south, enable_schedule, # 3. no data point (Asset name be used in this case.) asset_dict = {} asset_dict[ASSET_NAME] = dp_list - clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, - [], asset_dict) + # For connector relay we should not delete PI Point because + # when the PI point is created again (after deletion) the compressing attribute for it + # is always true. That means all the data is not stored in PI data archive. + # We lose a large proportion of the data because of compressing attribute. + # This is problematic for the fixture that verifies the data stored in PI. + # clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, + # [], asset_dict) cfg = {"expression": {"value": "tan(x)"}, "minimumX": {"value": "45"}, "maximumX": {"value": "45"}, "stepX": {"value": "0"}} diff --git a/tests/system/python/e2e/test_e2e_filter_fft_threshold.py b/tests/system/python/e2e/test_e2e_filter_fft_threshold.py index d6b52a52ed..0040005035 100644 --- a/tests/system/python/e2e/test_e2e_filter_fft_threshold.py +++ b/tests/system/python/e2e/test_e2e_filter_fft_threshold.py @@ -74,8 +74,13 @@ def start_south_north(self, reset_and_start_fledge, add_south, enable_schedule, # 3. Band02 asset_dict = {} asset_dict[ASSET + " " + 'FFT'] = dp_list - clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, - [], asset_dict) + # For connector relay we should not delete PI Point because + # when the PI point is created again (after deletion) the compressing attribute for it + # is always true. That means all the data is not stored in PI data archive. + # We lose a large proportion of the data because of compressing attribute. + # This is problematic for the fixture that verifies the data stored in PI. + # clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, + # [], asset_dict) # Define configuration of Fledge playback service south_config = {"assetName": {"value": "{}".format(asset_name)}, diff --git a/tests/system/python/e2e/test_e2e_modbus_c_pi.py b/tests/system/python/e2e/test_e2e_modbus_c_pi.py index 34795c4bfb..89991de4d6 100644 --- a/tests/system/python/e2e/test_e2e_modbus_c_pi.py +++ b/tests/system/python/e2e/test_e2e_modbus_c_pi.py @@ -82,8 +82,13 @@ def start_south_north(self, reset_and_start_fledge, add_south, remove_directorie dp_list = ['front right', 'rear right', 'front left', 'rear left', ''] asset_dict = {} asset_dict[ASSET_NAME] = dp_list - clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, - [], asset_dict) + # For connector relay we should not delete PI Point because + # when the PI point is created again (after deletion) the compressing attribute for it + # is always true. That means all the data is not stored in PI data archive. + # We lose a large proportion of the data because of compressing attribute. + # This is problematic for the fixture that verifies the data stored in PI. + # clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, + # [], asset_dict) add_south(SOUTH_PLUGIN, south_branch, fledge_url, service_name=SVC_NAME, config=cfg, plugin_lang="C", start_service=False, plugin_discovery_name=PLUGIN_NAME) diff --git a/tests/system/python/e2e/test_e2e_pi_scaleset.py b/tests/system/python/e2e/test_e2e_pi_scaleset.py index 6abb27568c..bf97e9105d 100644 --- a/tests/system/python/e2e/test_e2e_pi_scaleset.py +++ b/tests/system/python/e2e/test_e2e_pi_scaleset.py @@ -82,8 +82,13 @@ def start_south_north_with_filter(self, reset_and_start_fledge, add_south, south asset_dict[ASSET_NAME] = dp_list asset_dict["{}{}".format(ASSET_PREFIX, ASSET_NAME)] = dp_list - clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, - [], asset_dict) + # For connector relay we should not delete PI Point because + # when the PI point is created again (after deletion) the compressing attribute for it + # is always true. That means all the data is not stored in PI data archive. + # We lose a large proportion of the data because of compressing attribute. + # This is problematic for the fixture that verifies the data stored in PI. + # clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, + # [], asset_dict) fogbench_template_path = os.path.join( os.path.expandvars('${FLEDGE_ROOT}'), 'data/template.json') diff --git a/tests/system/python/e2e/test_e2e_vary_asset_http_pi.py b/tests/system/python/e2e/test_e2e_vary_asset_http_pi.py index c67bf72ddc..8267cf3515 100644 --- a/tests/system/python/e2e/test_e2e_vary_asset_http_pi.py +++ b/tests/system/python/e2e/test_e2e_vary_asset_http_pi.py @@ -102,9 +102,13 @@ def start_south_north(self, reset_and_start_fledge, add_south, start_north_pi_se # 5. no data point (Asset name be used in this case.) asset_dict = {} asset_dict[asset_name] = dp_list - - clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, - [], asset_dict) + # For connector relay we should not delete PI Point because + # when the PI point is created again (after deletion) the compressing attribute for it + # is always true. That means all the data is not stored in PI data archive. + # We lose a large proportion of the data because of compressing attribute. + # This is problematic for the fixture that verifies the data stored in PI. + # clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, + # [], asset_dict) south_plugin = "http" add_south("http_south", south_branch, fledge_url, config={"assetNamePrefix": {"value": ""}}, diff --git a/tests/system/python/pair/test_e2e_fledge_pair.py b/tests/system/python/pair/test_e2e_fledge_pair.py index 62f9bece7e..8996bd1971 100644 --- a/tests/system/python/pair/test_e2e_fledge_pair.py +++ b/tests/system/python/pair/test_e2e_fledge_pair.py @@ -112,8 +112,13 @@ def start_south_north_remote(self, reset_and_start_fledge_remote, use_pip_cache, dp_list = ['ivalue', ''] asset_dict = {} asset_dict[remote_asset_name] = dp_list - clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, - [], asset_dict) + # For connector relay we should not delete PI Point because + # when the PI point is created again (after deletion) the compressing attribute for it + # is always true. That means all the data is not stored in PI data archive. + # We lose a large proportion of the data because of compressing attribute. + # This is problematic for the fixture that verifies the data stored in PI. + # clear_pi_system_through_pi_web_api(pi_host, pi_admin, pi_passwd, pi_db, + # [], asset_dict) if remote_fledge_path is None: remote_fledge_path = '/home/{}/fledge'.format(remote_user) From 8b0063723f005553e2e95a2705f9e8200db08bd2 Mon Sep 17 00:00:00 2001 From: dianomicbot Date: Thu, 20 Oct 2022 10:48:46 +0000 Subject: [PATCH 47/48] VERSION changed Signed-off-by: dianomicbot --- VERSION | 2 +- docs/91_version_history.rst | 61 +++++++++++++++++++ docs/scripts/plugin_and_service_documentation | 2 +- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 782dfcd125..d247bccda7 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ -fledge_version=2.0.0 +fledge_version=2.0.1 fledge_schema=58 diff --git a/docs/91_version_history.rst b/docs/91_version_history.rst index e38ca7819a..e3803f11f3 100644 --- a/docs/91_version_history.rst +++ b/docs/91_version_history.rst @@ -25,6 +25,67 @@ Version History Fledge v2 ========== +v2.0.1 +------- + +Release Date: 2022-10-20 + +- **Fledge Core** + + - New Features: + + - Some improvements to the diagnostics for control operations within the system have been made to aid in the development of control pipelines within the system. + - The API to fetch audit log entries has been enhanced to allow a time based filter to be applied. This allows only audit log entries since a given date to be returned to the caller. + - A new option, healthcheck has been added to the command line script used to start, stop and monitor the instance. This runs a number of checks against the system to detect common misconfigurations and issues with the environment that have been observed to cause issues with the system. + - Improvements have been made to error logs to diagnose certain storage faults. Also the ability to recover from some storage faults connected to gathering of statistics has been added. + - The nesting of JSON objects that represent readings was previously limited to two levels within JSON, this limitation has now been lifted in line with the internal representation of nested objects. This is particularly important when handling audit log data in north plugins and now allows full audit log entries to be transmitted via north plugins. + - A third source of data is now available for sending to the north plugins, the internal audit log. This contains information such as configuration changes, services failures and other significant events within the Fledge instance. Note that a plugin must indicate it is able to handle audit data before it will be available within the plugin, currently the OPCUA north plugin is able to accept audit data. + - A fix has been added to prevent a crash when the incorrect number of arguments is given to get_plugin_info. Also the function name to extract has been defaulted to be plugin_info. + - An issue with incorrectly formed JSON when control operations are triggered from the north service has been resolved. + - The SQLite storage plugins have been updated to periodically reclaim free storage. This is useful for installations that experience short term peaks in storage demand as it will release the storage used during those peaks back to the operating system. + - A new API has been added that will fetch the list of packages that are available to be updated on the system. + - Two new API entry points have been added that return health data for the logging subsystems and the storage service. These are used by the healthcheck option of the fledge command script. + - The public REST API documentation has been updated to cover more of the entry points supported and also to include examples of calling the asset browsing and statistics APIs using Grafana. + + + - Bug Fix: + + - An issue with control operation parameters which had embedded quotes within the parameter values has been resolved. This previously caused some control operations from north services to not be processed by the control dispatcher service. + - When modifying a schedule the audit log entry, SCHCH for that changed, was previously added twice. This has now been resolved. + - An issue that prevented a change to the units used for reading rate, e.g. per second, per minute or per hour, not being actioned until a service was restarted has now been fixed. If the rate was also changed then this change would be actioned. + - It was possible to set a reading rate of 0 readings, this would cause the south service to fail. It is now not possible to set a rate of 0. + + +- **GUI** + + - New Features: + + + + - Bug Fix: + + + +- **Plugins** + + - New Features: + + - The foglamp-south-simple-rest plugin has been updated to allow for use of an HTTP proxy. + - Addition of operation support to the control input of the MQTT scripted north plugin + - The PI Server South plugin registers for Stream Updates for all PI Points generated by the point search. + - Support has been added to the OMF north plugin that allows the AVEVA Data Hub to be specified as a destination. + - Documentation has been added for the GCP Pub/Sub north plugin. + - The service dispatcher was previously looking at the wrong service type when sending operation messages to south service, this has now been resolved. + + + - Bug Fix: + + - The foglamp-south-mqtt-scripted plugin has been made more robust to loss of connection to the MQTT broker. It has also become more resilient to incorrectly entered broker addresses and more responsive when the broker is not reachable. + - A bug in the scale-set filter that caused integer values to remain as integers when scaled to a value that could not be represented in an integer, e.g. scaling down or scaling by a non-integer factor, has been resolved. + - The S2OPCUA south plugin provides a configuration option, minimum reporting interval that is used to slow the rate of reporting down for busy item. No reports of changes will be recorded when the change happens more frequently than the value set. In the case of the S2OPCUA plugin this was being ignored. It is now actioned correctly within the plugin. + - The configuration of the bucket storage service had incorrect displays of the the items in the category name and the description of the security category for the service. This has now been corrected. + + v2.0.0 ------- diff --git a/docs/scripts/plugin_and_service_documentation b/docs/scripts/plugin_and_service_documentation index 31771ef462..35a6ce1dad 100644 --- a/docs/scripts/plugin_and_service_documentation +++ b/docs/scripts/plugin_and_service_documentation @@ -3,7 +3,7 @@ # The best default branch to use develop rather than master. As new repository do not have a branch called master any more and having main branch only. if [[ "${DOCBRANCH}" == "" ]]; then # NOTE: During release time we need to replace develop and nightly build with actual released version - export DOCBRANCH=develop + export DOCBRANCH=2.0.1RC export ARCHIVE_BUILD=nightly else # only for dev purpose From dccc81354aacdf0ad736dfdc4a24454b1dc27999 Mon Sep 17 00:00:00 2001 From: Praveen Garg Date: Thu, 20 Oct 2022 21:07:21 +0530 Subject: [PATCH 48/48] chnage-logs cleanup Signed-off-by: Praveen Garg --- docs/91_version_history.rst | 38 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/docs/91_version_history.rst b/docs/91_version_history.rst index e3803f11f3..ea564db3df 100644 --- a/docs/91_version_history.rst +++ b/docs/91_version_history.rst @@ -34,56 +34,40 @@ Release Date: 2022-10-20 - New Features: - - Some improvements to the diagnostics for control operations within the system have been made to aid in the development of control pipelines within the system. - - The API to fetch audit log entries has been enhanced to allow a time based filter to be applied. This allows only audit log entries since a given date to be returned to the caller. - A new option, healthcheck has been added to the command line script used to start, stop and monitor the instance. This runs a number of checks against the system to detect common misconfigurations and issues with the environment that have been observed to cause issues with the system. - - Improvements have been made to error logs to diagnose certain storage faults. Also the ability to recover from some storage faults connected to gathering of statistics has been added. - - The nesting of JSON objects that represent readings was previously limited to two levels within JSON, this limitation has now been lifted in line with the internal representation of nested objects. This is particularly important when handling audit log data in north plugins and now allows full audit log entries to be transmitted via north plugins. - A third source of data is now available for sending to the north plugins, the internal audit log. This contains information such as configuration changes, services failures and other significant events within the Fledge instance. Note that a plugin must indicate it is able to handle audit data before it will be available within the plugin, currently the OPCUA north plugin is able to accept audit data. - - A fix has been added to prevent a crash when the incorrect number of arguments is given to get_plugin_info. Also the function name to extract has been defaulted to be plugin_info. - - An issue with incorrectly formed JSON when control operations are triggered from the north service has been resolved. - The SQLite storage plugins have been updated to periodically reclaim free storage. This is useful for installations that experience short term peaks in storage demand as it will release the storage used during those peaks back to the operating system. + - The API to fetch audit log entries has been enhanced to allow a time based filter to be applied. This allows only audit log entries since a given date to be returned to the caller. - A new API has been added that will fetch the list of packages that are available to be updated on the system. - Two new API entry points have been added that return health data for the logging subsystems and the storage service. These are used by the healthcheck option of the fledge command script. + - The nesting of JSON objects that represent readings was previously limited to two levels within JSON, this limitation has now been lifted in line with the internal representation of nested objects. This is particularly important when handling audit log data in north plugins and now allows full audit log entries to be transmitted via north plugins. + - Improvements have been made to error logs to diagnose certain storage faults. Also the ability to recover from some storage faults connected to gathering of statistics has been added. + - Some improvements to the diagnostics for control operations within the system have been made to aid in the development of control pipelines within the system. - The public REST API documentation has been updated to cover more of the entry points supported and also to include examples of calling the asset browsing and statistics APIs using Grafana. - Bug Fix: - + + - An issue with incorrectly formed JSON when control operations are triggered from the north service has been resolved. + - A fix has been added to prevent a crash when the incorrect number of arguments is given to get_plugin_info. Also the function name to extract has been defaulted to be plugin_info. - An issue with control operation parameters which had embedded quotes within the parameter values has been resolved. This previously caused some control operations from north services to not be processed by the control dispatcher service. - When modifying a schedule the audit log entry, SCHCH for that changed, was previously added twice. This has now been resolved. - An issue that prevented a change to the units used for reading rate, e.g. per second, per minute or per hour, not being actioned until a service was restarted has now been fixed. If the rate was also changed then this change would be actioned. - It was possible to set a reading rate of 0 readings, this would cause the south service to fail. It is now not possible to set a rate of 0. - -- **GUI** - - - New Features: - - - - - Bug Fix: - - - -- **Plugins** +- **Services & Plugins** - New Features: - - The foglamp-south-simple-rest plugin has been updated to allow for use of an HTTP proxy. - - Addition of operation support to the control input of the MQTT scripted north plugin - - The PI Server South plugin registers for Stream Updates for all PI Points generated by the point search. - Support has been added to the OMF north plugin that allows the AVEVA Data Hub to be specified as a destination. - Documentation has been added for the GCP Pub/Sub north plugin. - - The service dispatcher was previously looking at the wrong service type when sending operation messages to south service, this has now been resolved. - Bug Fix: - - - The foglamp-south-mqtt-scripted plugin has been made more robust to loss of connection to the MQTT broker. It has also become more resilient to incorrectly entered broker addresses and more responsive when the broker is not reachable. + + - The service dispatcher was previously looking at the wrong service type when sending operation messages to south service, this has now been resolved. - A bug in the scale-set filter that caused integer values to remain as integers when scaled to a value that could not be represented in an integer, e.g. scaling down or scaling by a non-integer factor, has been resolved. - - The S2OPCUA south plugin provides a configuration option, minimum reporting interval that is used to slow the rate of reporting down for busy item. No reports of changes will be recorded when the change happens more frequently than the value set. In the case of the S2OPCUA plugin this was being ignored. It is now actioned correctly within the plugin. - - The configuration of the bucket storage service had incorrect displays of the the items in the category name and the description of the security category for the service. This has now been corrected. + - The S2OPCUA south plugin provides a configuration option, minimum reporting interval that is used to slow the rate of reporting down for busy items. No reports of changes will be recorded when the change happens more frequently than the value set. In the case of the S2OPCUA plugin this was being ignored. It is now actioned correctly within the plugin. v2.0.0