memory: refactor JSON assembling codes
This commit does nothing but a refactoring around the translation codes
that translate data from dbus objects to JSON.
Existing codes assumes that the |AsyncResponse| is always at a specific
DIMM. This doesn't work if we are doing a efficient level=1 expand, as
introduced initially in
https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/52418, where the
|AsyncResponse| now points to the MemoryCollection.
In order to reuse codes in future changes, this commits refactors many
functions to take a JSON pointer, so any attributes added to a specific
DIMM go to the JSON pointer, rather than always to the root.
1. Tested on my mock environment,
```
URI: /redfish/v1/Systems/system/Memory/dimm0
{
"@odata.id": "/redfish/v1/Systems/system/Memory/dimm0",
"@odata.type": "#Memory.v1_11_0.Memory",
"AllowedSpeedsMHz": [],
"BaseModuleType": "RDIMM",
"BusWidthBits": 0,
"CapacityMiB": 1024,
"DataWidthBits": 0,
"ErrorCorrection": "NoECC",
"FirmwareRevision": "0",
"Id": "dimm0",
"Name": "DIMM Slot",
"OperatingSpeedMhz": 0,
"RankCount": 0,
"Regions": [
{
"MemoryClassification": "Volatile",
"OffsetMiB": 0,
"PassphraseEnabled": false,
"RegionId": "",
"SizeMiB": 1024
}
],
"Status": {
"Health": "OK",
"HealthRollup": "OK",
"State": "Enabled"
}
}
```
2. No new Redfish Validator failures on MemoryCollection on real
hardware:
/redfish/v1/Systems/system/Memory (response time:0:00:00.116538)
MemoryCollection Pass
/redfish/v1/Systems/system/Memory/dimm0 (response time:
0:00:00.201940) Memory Pass
Signed-off-by: Nan Zhou <nanzhoumails@gmail.com>
Change-Id: I61e6c76ca6dd6f129c5d382dcc46a4292a4e1bb7
diff --git a/redfish-core/lib/memory.hpp b/redfish-core/lib/memory.hpp
index fb2dac1..209fa1b 100644
--- a/redfish-core/lib/memory.hpp
+++ b/redfish-core/lib/memory.hpp
@@ -20,6 +20,7 @@
#include <app.hpp>
#include <boost/algorithm/string.hpp>
#include <dbus_utility.hpp>
+#include <nlohmann/json.hpp>
#include <query.hpp>
#include <registries/privilege_registry.hpp>
#include <utils/collection.hpp>
@@ -140,7 +141,8 @@
inline void dimmPropToHex(
const std::shared_ptr<bmcweb::AsyncResp>& aResp, const char* key,
- const std::pair<std::string, dbus::utility::DbusVariantType>& property)
+ const std::pair<std::string, dbus::utility::DbusVariantType>& property,
+ const nlohmann::json::json_pointer& jsonPtr)
{
const uint16_t* value = std::get_if<uint16_t>(&property.second);
if (value == nullptr)
@@ -149,30 +151,31 @@
BMCWEB_LOG_DEBUG << "Invalid property type for " << property.first;
return;
}
-
- aResp->res.jsonValue[key] = "0x" + intToHexString(*value, 4);
+ aResp->res.jsonValue[jsonPtr][key] = "0x" + intToHexString(*value, 4);
}
inline void getPersistentMemoryProperties(
const std::shared_ptr<bmcweb::AsyncResp>& aResp,
- const std::pair<std::string, dbus::utility::DbusVariantType>& property)
+ const std::pair<std::string, dbus::utility::DbusVariantType>& property,
+ const nlohmann::json::json_pointer& jsonPtr)
{
if (property.first == "ModuleManufacturerID")
{
- dimmPropToHex(aResp, "ModuleManufacturerID", property);
+ dimmPropToHex(aResp, "ModuleManufacturerID", property, jsonPtr);
}
else if (property.first == "ModuleProductID")
{
- dimmPropToHex(aResp, "ModuleProductID", property);
+ dimmPropToHex(aResp, "ModuleProductID", property, jsonPtr);
}
else if (property.first == "SubsystemVendorID")
{
dimmPropToHex(aResp, "MemorySubsystemControllerManufacturerID",
- property);
+ property, jsonPtr);
}
else if (property.first == "SubsystemDeviceID")
{
- dimmPropToHex(aResp, "MemorySubsystemControllerProductID", property);
+ dimmPropToHex(aResp, "MemorySubsystemControllerProductID", property,
+ jsonPtr);
}
else if (property.first == "VolatileRegionSizeLimitInKiB")
{
@@ -185,7 +188,8 @@
<< "Invalid property type for VolatileRegionSizeLimitKiB";
return;
}
- aResp->res.jsonValue["VolatileRegionSizeLimitMiB"] = (*value) >> 10;
+ aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeLimitMiB"] =
+ (*value) >> 10;
}
else if (property.first == "PmRegionSizeLimitInKiB")
{
@@ -197,7 +201,8 @@
BMCWEB_LOG_DEBUG << "Invalid property type for PmRegioSizeLimitKiB";
return;
}
- aResp->res.jsonValue["PersistentRegionSizeLimitMiB"] = (*value) >> 10;
+ aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeLimitMiB"] =
+ (*value) >> 10;
}
else if (property.first == "VolatileSizeInKiB")
{
@@ -209,7 +214,7 @@
BMCWEB_LOG_DEBUG << "Invalid property type for VolatileSizeInKiB";
return;
}
- aResp->res.jsonValue["VolatileSizeMiB"] = (*value) >> 10;
+ aResp->res.jsonValue[jsonPtr]["VolatileSizeMiB"] = (*value) >> 10;
}
else if (property.first == "PmSizeInKiB")
{
@@ -220,7 +225,7 @@
BMCWEB_LOG_DEBUG << "Invalid property type for PmSizeInKiB";
return;
}
- aResp->res.jsonValue["NonVolatileSizeMiB"] = (*value) >> 10;
+ aResp->res.jsonValue[jsonPtr]["NonVolatileSizeMiB"] = (*value) >> 10;
}
else if (property.first == "CacheSizeInKB")
{
@@ -231,7 +236,7 @@
BMCWEB_LOG_DEBUG << "Invalid property type for CacheSizeInKB";
return;
}
- aResp->res.jsonValue["CacheSizeMiB"] = (*value >> 10);
+ aResp->res.jsonValue[jsonPtr]["CacheSizeMiB"] = (*value >> 10);
}
else if (property.first == "VoltaileRegionMaxSizeInKib")
@@ -245,7 +250,8 @@
<< "Invalid property type for VolatileRegionMaxSizeInKib";
return;
}
- aResp->res.jsonValue["VolatileRegionSizeMaxMiB"] = (*value) >> 10;
+ aResp->res.jsonValue[jsonPtr]["VolatileRegionSizeMaxMiB"] =
+ (*value) >> 10;
}
else if (property.first == "PmRegionMaxSizeInKiB")
{
@@ -258,7 +264,8 @@
<< "Invalid property type for PmRegionMaxSizeInKiB";
return;
}
- aResp->res.jsonValue["PersistentRegionSizeMaxMiB"] = (*value) >> 10;
+ aResp->res.jsonValue[jsonPtr]["PersistentRegionSizeMaxMiB"] =
+ (*value) >> 10;
}
else if (property.first == "AllocationIncrementInKiB")
{
@@ -271,7 +278,8 @@
<< "Invalid property type for AllocationIncrementInKiB";
return;
}
- aResp->res.jsonValue["AllocationIncrementMiB"] = (*value) >> 10;
+ aResp->res.jsonValue[jsonPtr]["AllocationIncrementMiB"] =
+ (*value) >> 10;
}
else if (property.first == "AllocationAlignmentInKiB")
{
@@ -284,7 +292,8 @@
<< "Invalid property type for AllocationAlignmentInKiB";
return;
}
- aResp->res.jsonValue["AllocationAlignmentMiB"] = (*value) >> 10;
+ aResp->res.jsonValue[jsonPtr]["AllocationAlignmentMiB"] =
+ (*value) >> 10;
}
else if (property.first == "VolatileRegionNumberLimit")
{
@@ -294,7 +303,7 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["VolatileRegionNumberLimit"] = *value;
+ aResp->res.jsonValue[jsonPtr]["VolatileRegionNumberLimit"] = *value;
}
else if (property.first == "PmRegionNumberLimit")
{
@@ -304,7 +313,7 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["PersistentRegionNumberLimit"] = *value;
+ aResp->res.jsonValue[jsonPtr]["PersistentRegionNumberLimit"] = *value;
}
else if (property.first == "SpareDeviceCount")
{
@@ -314,7 +323,7 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["SpareDeviceCount"] = *value;
+ aResp->res.jsonValue[jsonPtr]["SpareDeviceCount"] = *value;
}
else if (property.first == "IsSpareDeviceInUse")
{
@@ -324,7 +333,7 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["IsSpareDeviceEnabled"] = *value;
+ aResp->res.jsonValue[jsonPtr]["IsSpareDeviceEnabled"] = *value;
}
else if (property.first == "IsRankSpareEnabled")
{
@@ -334,7 +343,7 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["IsRankSpareEnabled"] = *value;
+ aResp->res.jsonValue[jsonPtr]["IsRankSpareEnabled"] = *value;
}
else if (property.first == "MaxAveragePowerLimitmW")
{
@@ -347,7 +356,7 @@
<< "Invalid property type for MaxAveragePowerLimitmW";
return;
}
- aResp->res.jsonValue["MaxTDPMilliWatts"] = *value;
+ aResp->res.jsonValue[jsonPtr]["MaxTDPMilliWatts"] = *value;
}
else if (property.first == "ConfigurationLocked")
{
@@ -357,7 +366,7 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["ConfigurationLocked"] = *value;
+ aResp->res.jsonValue[jsonPtr]["ConfigurationLocked"] = *value;
}
else if (property.first == "AllowedMemoryModes")
{
@@ -375,7 +384,8 @@
{
if (boost::ends_with(*value, v))
{
- aResp->res.jsonValue["OperatingMemoryModes"].push_back(v);
+ aResp->res.jsonValue[jsonPtr]["OperatingMemoryModes"].push_back(
+ v);
break;
}
}
@@ -396,7 +406,7 @@
{
if (boost::ends_with(*value, v))
{
- aResp->res.jsonValue["MemoryMedia"].push_back(v);
+ aResp->res.jsonValue[jsonPtr]["MemoryMedia"].push_back(v);
break;
}
}
@@ -412,7 +422,8 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
+ aResp->res.jsonValue[jsonPtr]["SecurityCapabilities"][property.first] =
+ *value;
}
else if (property.first == "MaxPassphraseCount" ||
property.first == "PassphraseLockLimit")
@@ -423,19 +434,21 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["SecurityCapabilities"][property.first] = *value;
+ aResp->res.jsonValue[jsonPtr]["SecurityCapabilities"][property.first] =
+ *value;
}
}
inline void
assembleDimmProperties(std::string_view dimmId,
const std::shared_ptr<bmcweb::AsyncResp>& aResp,
- const dbus::utility::DBusPropertiesMap& properties)
+ const dbus::utility::DBusPropertiesMap& properties,
+ const nlohmann::json::json_pointer& jsonPtr)
{
- aResp->res.jsonValue["Id"] = dimmId;
- aResp->res.jsonValue["Name"] = "DIMM Slot";
- aResp->res.jsonValue["Status"]["State"] = "Enabled";
- aResp->res.jsonValue["Status"]["Health"] = "OK";
+ aResp->res.jsonValue[jsonPtr]["Id"] = dimmId;
+ aResp->res.jsonValue[jsonPtr]["Name"] = "DIMM Slot";
+ aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Enabled";
+ aResp->res.jsonValue[jsonPtr]["Status"]["Health"] = "OK";
for (const auto& property : properties)
{
@@ -446,7 +459,7 @@
{
continue;
}
- aResp->res.jsonValue["DataWidthBits"] = *value;
+ aResp->res.jsonValue[jsonPtr]["DataWidthBits"] = *value;
}
else if (property.first == "MemorySizeInKB")
{
@@ -457,7 +470,7 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["CapacityMiB"] = (*memorySize >> 10);
+ aResp->res.jsonValue[jsonPtr]["CapacityMiB"] = (*memorySize >> 10);
}
else if (property.first == "PartNumber")
{
@@ -467,7 +480,7 @@
{
continue;
}
- aResp->res.jsonValue["PartNumber"] = *value;
+ aResp->res.jsonValue[jsonPtr]["PartNumber"] = *value;
}
else if (property.first == "SerialNumber")
{
@@ -477,7 +490,7 @@
{
continue;
}
- aResp->res.jsonValue["SerialNumber"] = *value;
+ aResp->res.jsonValue[jsonPtr]["SerialNumber"] = *value;
}
else if (property.first == "Manufacturer")
{
@@ -487,7 +500,7 @@
{
continue;
}
- aResp->res.jsonValue["Manufacturer"] = *value;
+ aResp->res.jsonValue[jsonPtr]["Manufacturer"] = *value;
}
else if (property.first == "RevisionCode")
{
@@ -499,7 +512,8 @@
BMCWEB_LOG_DEBUG << "Invalid property type for RevisionCode";
return;
}
- aResp->res.jsonValue["FirmwareRevision"] = std::to_string(*value);
+ aResp->res.jsonValue[jsonPtr]["FirmwareRevision"] =
+ std::to_string(*value);
}
else if (property.first == "Present")
{
@@ -512,7 +526,7 @@
}
if (!*value)
{
- aResp->res.jsonValue["Status"]["State"] = "Absent";
+ aResp->res.jsonValue[jsonPtr]["Status"]["State"] = "Absent";
}
}
else if (property.first == "MemoryTotalWidth")
@@ -522,7 +536,7 @@
{
continue;
}
- aResp->res.jsonValue["BusWidthBits"] = *value;
+ aResp->res.jsonValue[jsonPtr]["BusWidthBits"] = *value;
}
else if (property.first == "ECC")
{
@@ -541,7 +555,7 @@
{
if (boost::ends_with(*value, v))
{
- aResp->res.jsonValue["ErrorCorrection"] = v;
+ aResp->res.jsonValue[jsonPtr]["ErrorCorrection"] = v;
break;
}
}
@@ -565,7 +579,7 @@
{
if (boost::ends_with(*value, v))
{
- aResp->res.jsonValue["BaseModuleType"] = v;
+ aResp->res.jsonValue[jsonPtr]["BaseModuleType"] = v;
break;
}
}
@@ -578,7 +592,8 @@
{
continue;
}
- nlohmann::json& jValue = aResp->res.jsonValue["AllowedSpeedsMHz"];
+ nlohmann::json& jValue =
+ aResp->res.jsonValue[jsonPtr]["AllowedSpeedsMHz"];
jValue = nlohmann::json::array();
for (uint16_t subVal : *value)
{
@@ -596,7 +611,8 @@
<< "Invalid property type for MemoryAttributes";
return;
}
- aResp->res.jsonValue["RankCount"] = static_cast<uint64_t>(*value);
+ aResp->res.jsonValue[jsonPtr]["RankCount"] =
+ static_cast<uint64_t>(*value);
}
else if (property.first == "MemoryConfiguredSpeedInMhz")
{
@@ -605,7 +621,7 @@
{
continue;
}
- aResp->res.jsonValue["OperatingSpeedMhz"] = *value;
+ aResp->res.jsonValue[jsonPtr]["OperatingSpeedMhz"] = *value;
}
else if (property.first == "MemoryType")
{
@@ -618,15 +634,16 @@
// so just leave off
if (!memoryDeviceType.empty())
{
- aResp->res.jsonValue["MemoryDeviceType"] = memoryDeviceType;
+ aResp->res.jsonValue[jsonPtr]["MemoryDeviceType"] =
+ memoryDeviceType;
}
if (value->find("DDR") != std::string::npos)
{
- aResp->res.jsonValue["MemoryType"] = "DRAM";
+ aResp->res.jsonValue[jsonPtr]["MemoryType"] = "DRAM";
}
else if (boost::ends_with(*value, "Logical"))
{
- aResp->res.jsonValue["MemoryType"] = "IntelOptane";
+ aResp->res.jsonValue[jsonPtr]["MemoryType"] = "IntelOptane";
}
}
}
@@ -642,7 +659,8 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["MemoryLocation"][property.first] = *value;
+ aResp->res.jsonValue[jsonPtr]["MemoryLocation"][property.first] =
+ *value;
}
else if (property.first == "SparePartNumber")
{
@@ -653,7 +671,7 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["SparePartNumber"] = *value;
+ aResp->res.jsonValue[jsonPtr]["SparePartNumber"] = *value;
}
else if (property.first == "Model")
{
@@ -664,7 +682,7 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["Model"] = *value;
+ aResp->res.jsonValue[jsonPtr]["Model"] = *value;
}
else if (property.first == "LocationCode")
{
@@ -675,12 +693,12 @@
messages::internalError(aResp->res);
return;
}
- aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
- *value;
+ aResp->res.jsonValue[jsonPtr]["Location"]["PartLocation"]
+ ["ServiceLabel"] = *value;
}
else
{
- getPersistentMemoryProperties(aResp, property);
+ getPersistentMemoryProperties(aResp, property, jsonPtr);
}
}
}
@@ -705,17 +723,17 @@
messages::internalError(aResp->res);
return;
}
- assembleDimmProperties(dimmId, aResp, properties);
+ assembleDimmProperties(dimmId, aResp, properties, ""_json_pointer);
},
service, objPath, "org.freedesktop.DBus.Properties", "GetAll", "");
}
inline void assembleDimmPartitionData(
const std::shared_ptr<bmcweb::AsyncResp>& aResp,
- const dbus::utility::DBusPropertiesMap& properties)
+ const dbus::utility::DBusPropertiesMap& properties,
+ const nlohmann::json::json_pointer& regionPtr)
{
- nlohmann::json& partition =
- aResp->res.jsonValue["Regions"].emplace_back(nlohmann::json::object());
+ nlohmann::json::object_t partition;
for (const auto& [key, val] : properties)
{
if (key == "MemoryClassification")
@@ -772,6 +790,7 @@
partition["SizeMiB"] = (*value >> 10);
}
}
+ aResp->res.jsonValue[regionPtr].emplace_back(std::move(partition));
}
inline void getDimmPartitionData(std::shared_ptr<bmcweb::AsyncResp> aResp,
@@ -789,7 +808,8 @@
return;
}
- assembleDimmPartitionData(aResp, properties);
+ nlohmann::json::json_pointer regionPtr = "/Regions"_json_pointer;
+ assembleDimmPartitionData(aResp, properties, regionPtr);
},
service, path, "org.freedesktop.DBus.Properties", "GetAll",