From 1e8b3e0fe4ce9aa87a35f6c3ba6e506873d5455c Mon Sep 17 00:00:00 2001 From: mansijos Date: Fri, 12 Feb 2021 11:26:57 +0530 Subject: [PATCH] Entity-manager: Add support to update assetTag Asset tag is an updateable property from User level interface like Redfish. User-level interface will update Asset tag in entity-manager, which will further update the needed FRU interface property exposed. Tested: Successfully updated in assetTag interface as well as in fru interface while using set-property and using redfish as well. The new value is preserved after BMC resets. Change-Id: Iab8b24344d1a27486ceafe21aa2b4496706a2944 Signed-off-by: mansijos --- include/EntityManager.hpp | 15 ++-- src/EntityManager.cpp | 148 ++++++++++++++++++++++++++++++++------ 2 files changed, 135 insertions(+), 28 deletions(-) diff --git a/include/EntityManager.hpp b/include/EntityManager.hpp index 5867556..a4e9922 100644 --- a/include/EntityManager.hpp +++ b/include/EntityManager.hpp @@ -29,13 +29,16 @@ #include #include -using DBusProbeObjectT = boost::container::flat_map< - std::string, - std::vector>>; - using FoundDeviceT = std::vector>; +using FoundDeviceInfoT = std::vector< + std::tuple, + std::string, std::string, std::string>>; + +using DBusProbeObjectT = + boost::container::flat_map; + struct PerformScan : std::enable_shared_from_this { @@ -62,12 +65,12 @@ struct PerformProbe : std::enable_shared_from_this { PerformProbe(const std::vector& probeCommand, std::shared_ptr& scanPtr, - std::function&& callback); + std::function&& callback); virtual ~PerformProbe(); std::vector _probeCommand; std::shared_ptr scan; - std::function _callback; + std::function _callback; }; inline void logDeviceAdded(const nlohmann::json& record) diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp index aa1df20..cd73675 100644 --- a/src/EntityManager.cpp +++ b/src/EntityManager.cpp @@ -47,9 +47,14 @@ constexpr const char* lastConfiguration = "/tmp/configuration/last.json"; constexpr const char* currentConfiguration = "/var/configuration/system.json"; constexpr const char* globalSchema = "global.json"; constexpr const int32_t MAX_MAPPER_DEPTH = 0; +constexpr const char* foundObject = "FoundProbe"; constexpr const bool DEBUG = false; +using foundProbeData = std::map; +static foundProbeData foundData; +static std::map mapFoundData; + struct cmp_str { bool operator()(const char* a, const char* b) const @@ -169,7 +174,10 @@ void getInterfaces( return; } - scan->dbusProbeObjects[std::get<2>(call)].emplace_back(resp); + // Save the dbus info along with device info + scan->dbusProbeObjects[std::get<2>(call)].emplace_back( + std::make_tuple(resp, std::get<0>(call), std::get<1>(call), + std::get<2>(call))); }, std::get<0>(call), std::get<1>(call), "org.freedesktop.DBus.Properties", "GetAll", std::get<2>(call)); @@ -274,11 +282,10 @@ void findDbusObjects(std::vector>&& probeVector, // probes dbus interface dictionary for a key with a value that matches a regex bool probeDbus(const std::string& interface, const std::map& matches, - FoundDeviceT& devices, std::shared_ptr scan, + FoundDeviceInfoT& devices, std::shared_ptr scan, bool& foundProbe) { - std::vector>& - dbusObject = scan->dbusProbeObjects[interface]; + FoundDeviceInfoT& dbusObject = scan->dbusProbeObjects[interface]; if (dbusObject.empty()) { foundProbe = false; @@ -287,8 +294,9 @@ bool probeDbus(const std::string& interface, foundProbe = true; bool foundMatch = false; - for (auto& device : dbusObject) + for (auto& deviceInfo : dbusObject) { + auto& device = std::get<0>(deviceInfo); bool deviceMatches = true; for (auto& match : matches) { @@ -305,7 +313,7 @@ bool probeDbus(const std::string& interface, } if (deviceMatches) { - devices.emplace_back(device); + devices.emplace_back(deviceInfo); foundMatch = true; deviceMatches = false; // for next iteration } @@ -315,11 +323,8 @@ bool probeDbus(const std::string& interface, // default probe entry point, iterates a list looking for specific types to // call specific probe functions -bool probe( - const std::vector& probeCommand, - std::shared_ptr scan, - std::vector>& - foundDevs) +bool probe(const std::vector& probeCommand, + std::shared_ptr scan, FoundDeviceInfoT& foundDevs) { const static std::regex command(R"(\((.*)\))"); std::smatch match; @@ -449,8 +454,9 @@ bool probe( // probe passed, but empty device if (ret && foundDevs.size() == 0) { - foundDevs.emplace_back( - boost::container::flat_map{}); + foundDevs.emplace_back(std::make_tuple( + boost::container::flat_map{}, + std::string{}, std::string{}, std::string{})); } if (matchOne && ret) { @@ -465,13 +471,13 @@ bool probe( PerformProbe::PerformProbe(const std::vector& probeCommand, std::shared_ptr& scanPtr, - std::function&& callback) : + std::function&& callback) : _probeCommand(probeCommand), scan(scanPtr), _callback(std::move(callback)) {} PerformProbe::~PerformProbe() { - FoundDeviceT foundDevs; + FoundDeviceInfoT foundDevs; if (probe(_probeCommand, scan, foundDevs)) { _callback(foundDevs); @@ -556,6 +562,47 @@ void addArrayToDbus(const std::string& name, const nlohmann::json& array, } } +template +bool persistAssetTag(const PropertyType& newVal, + const std::string& jsonPointerString) +{ + std::size_t found = jsonPointerString.find_last_of("/\\"); + std::string jsonPointerPath = jsonPointerString.substr(0, found); + + auto it = mapFoundData.find(jsonPointerPath); + if (it == mapFoundData.end()) + { + std::cerr << "Error in finding jsonPointerPath in mapFoundData" + << "\n"; + return false; + } + + foundProbeData& tmpMap = it->second; + auto foundConn = tmpMap.find("foundConn"); + auto foundPath = tmpMap.find("foundPath"); + auto foundIntf = tmpMap.find("foundIntf"); + if (foundConn == tmpMap.end() || foundPath == tmpMap.end() || + foundIntf == tmpMap.end()) + { + std::cerr << "No prob object data is avaliable in foundProbeData" + << "\n"; + return false; + } + + SYSTEM_BUS->async_method_call( + [](const boost::system::error_code& ec) { + if (ec) + { + std::cerr << "Error setting AssetTag in FRU interface " << ec + << "\n"; + } + }, + foundConn->second, foundPath->second, "org.freedesktop.DBus.Properties", + "Set", foundIntf->second, "PRODUCT_ASSET_TAG", + std::variant(newVal)); + return true; +} + template void addProperty(const std::string& propertyName, const PropertyType& value, sdbusplus::asio::dbus_interface* iface, @@ -568,11 +615,21 @@ void addProperty(const std::string& propertyName, const PropertyType& value, iface->register_property(propertyName, value); return; } + iface->register_property( propertyName, value, - [&systemConfiguration, + [propertyName, &systemConfiguration, jsonPointerString{std::string(jsonPointerString)}]( const PropertyType& newVal, PropertyType& val) { + if (propertyName == "AssetTag") + { + if (!persistAssetTag(newVal, jsonPointerString)) + { + std::cerr << "error setting AssetTag in FRU interface\n"; + return -1; + } + } + val = newVal; if (!setJsonFromPointer(jsonPointerString, val, systemConfiguration)) @@ -970,6 +1027,11 @@ void postToDbus(const nlohmann::json& newConfiguration, populateInterfaceFromJson(systemConfiguration, jsonPointerPath, boardIface, boardValues, objServer); jsonPointerPath += "/"; + + std::string foundConn; + std::string foundPath; + std::string foundIntf; + // iterate through board properties for (auto& boardField : boardValues.items()) { @@ -979,9 +1041,32 @@ void postToDbus(const nlohmann::json& newConfiguration, createInterface(objServer, boardName, boardField.key(), boardKeyOrig); - populateInterfaceFromJson(systemConfiguration, - jsonPointerPath + boardField.key(), - iface, boardField.value(), objServer); + if (boardField.key() == "FoundProbe") + { + foundConn = boardField.value()["Connection"]; + foundPath = boardField.value()["Path"]; + foundIntf = boardField.value()["Interface"]; + } + if (boardField.key() == + "xyz.openbmc_project.Inventory.Decorator.AssetTag") + { + foundData["foundConn"] = foundConn; + foundData["foundPath"] = foundPath; + foundData["foundIntf"] = foundIntf; + mapFoundData[jsonPointerPath + boardField.key()] = + foundData; + + populateInterfaceFromJson( + systemConfiguration, jsonPointerPath + boardField.key(), + iface, boardField.value(), objServer, + sdbusplus::asio::PropertyPermission::readWrite); + } + else + { + populateInterfaceFromJson( + systemConfiguration, jsonPointerPath + boardField.key(), + iface, boardField.value(), objServer); + } } } @@ -1278,7 +1363,7 @@ void PerformScan::run() auto thisRef = shared_from_this(); auto probePointer = std::make_shared( probeCommand, thisRef, - [&, recordPtr, probeName](FoundDeviceT& foundDevices) { + [&, recordPtr, probeName](FoundDeviceInfoT& foundDevices) { _passed = true; std::set usedNames; @@ -1294,7 +1379,8 @@ void PerformScan::run() for (auto itr = foundDevices.begin(); itr != foundDevices.end();) { - std::string recordName = getRecordName(*itr, probeName); + std::string recordName = + getRecordName(std::get<0>(*itr), probeName); auto fromLastJson = lastJson.find(recordName); if (fromLastJson != lastJson.end()) @@ -1328,6 +1414,15 @@ void PerformScan::run() continue; } + nlohmann::json recordVal = *recordPtr; + // Save the dbus connection, path and interface info + // of the device + recordVal[foundObject]["Connection"] = + std::get<1>(*itr); + recordVal[foundObject]["Path"] = std::get<2>(*itr); + recordVal[foundObject]["Interface"] = + std::get<3>(*itr); + int index = std::stoi( nameIt->get().substr(indexIdx), nullptr, 0); @@ -1349,8 +1444,9 @@ void PerformScan::run() std::optional replaceStr; - for (auto& foundDevice : foundDevices) + for (auto& foundDeviceInfo : foundDevices) { + auto& foundDevice = std::get<0>(foundDeviceInfo); nlohmann::json record = *recordPtr; std::string recordName = getRecordName(foundDevice, probeName); @@ -1382,6 +1478,14 @@ void PerformScan::run() } } + // Save the dbus connection, path and interface info + // of the device + record[foundObject]["Connection"] = + std::get<1>(foundDeviceInfo); + record[foundObject]["Path"] = std::get<2>(foundDeviceInfo); + record[foundObject]["Interface"] = + std::get<3>(foundDeviceInfo); + if (replaceStr) { std::cerr << "Duplicates found, replacing " -- 2.17.1