Add ServiceIdentification
Implements GET and PATCH support for ServiceIdentification in
Managers/bmc and service root.
Tested:
- Refish Service Validator passes
- Tested on romulus:
1. GET initial value
```
curl -k "https://$BMC/redfish/v1"
{
...
}
```
ServiceIdentification is not yet present in service root,
as expected
```
curl -k -H "X-Auth-Token: $XAUTH_TOKEN" "https://$BMC/redfish/v1/Managers/bmc"
{
...
"ServiceIdentification": "",
...
}
```
2. PATCH and GET with valid value
```
curl -k -X PATCH "https://$BMC/redfish/v1/Managers/bmc" -H "X-Auth-Token: $XAUTH_TOKEN" \
-H 'Content-Type: application/json' --data-raw '{"ServiceIdentification": "foo"}'
{
"@Message.ExtendedInfo": [
{
"@odata.type": "#Message.v1_1_1.Message",
"Message": "The request completed successfully.",
"MessageArgs": [],
"MessageId": "Base.1.19.Success",
"MessageSeverity": "OK",
"Resolution": "None."
}
]
}
curl -k "https://$BMC/redfish/v1"
{
...
"ServiceIdentification": "foo",
...
}
curl -k -H "X-Auth-Token: $XAUTH_TOKEN" "https://$BMC/redfish/v1/Managers/bmc"
{
...
"ServiceIdentification": "foo",
...
}
```
3. PATCH and GET with invalid value
```
curl -k -X PATCH "https://$BMC/redfish/v1/Managers/bmc" -H "X-Auth-Token: $XAUTH_TOKEN" \
-H 'Content-Type: application/json' --data-raw '{"ServiceIdentification": "$$$"}'
{
"ServiceIdentification@Message.ExtendedInfo": [
{
"@odata.type": "#Message.v1_1_1.Message",
"Message": "The value provided for the property ServiceIdentification is not valid.",
"MessageArgs": [
"ServiceIdentification"
],
"MessageId": "Base.1.19.PropertyValueError",
"MessageSeverity": "Warning",
"Resolution": "Correct the value for the property in the request body and resubmit the request if the operation failed."
}
]
}
curl -k -X PATCH "https://$BMC/redfish/v1/Managers/bmc" -H "X-Auth-Token: $XAUTH_TOKEN" \
-H 'Content-Type: application/json' --data-raw '{"ServiceIdentification": "2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"}'
{
"error": {
"@Message.ExtendedInfo": [
{
"@odata.type": "#Message.v1_1_1.Message",
"Message": "The string 'ServiceIdentification' exceeds the length limit 99.",
"MessageArgs": [
"ServiceIdentification",
"99"
],
"MessageId": "Base.1.19.StringValueTooLong",
"MessageSeverity": "Warning",
"Resolution": "Resubmit the request with an appropriate string length."
}
],
"code": "Base.1.19.StringValueTooLong",
"message": "The string 'ServiceIdentification' exceeds the length limit 99."
}
}
curl -k "https://$BMC/redfish/v1"
{
...
"ServiceIdentification": "foo",
...
}
curl -k -H "X-Auth-Token: $XAUTH_TOKEN" "https://$BMC/redfish/v1/Managers/bmc"
{
...
"ServiceIdentification": "foo",
...
}
```
Change-Id: I5b71a73e947ec64cabb8d93c8503a18fb43b8937
Signed-off-by: Corey Ethington <cethington@coreweave.com>
diff --git a/docs/Redfish.md b/docs/Redfish.md
index 252507b..20ed111 100644
--- a/docs/Redfish.md
+++ b/docs/Redfish.md
@@ -41,6 +41,7 @@
- Managers
- RedfishVersion
- Registries
+- ServiceIdentification
- SessionService
- Systems
- Tasks
@@ -565,6 +566,7 @@
- PowerState
- SerialNumber
- ServiceEntryPointUUID
+- ServiceIdentification
- SparePartNumber
- Status
- UUID
diff --git a/include/persistent_data.hpp b/include/persistent_data.hpp
index efdfcfa..d210800 100644
--- a/include/persistent_data.hpp
+++ b/include/persistent_data.hpp
@@ -104,6 +104,15 @@
systemUuid = *jSystemUuid;
}
}
+ else if (item.first == "service_identification")
+ {
+ const std::string* jServiceIdentification =
+ item.second.get_ptr<const std::string*>();
+ if (jServiceIdentification != nullptr)
+ {
+ serviceIdentification = *jServiceIdentification;
+ }
+ }
else if (item.first == "auth_config")
{
const nlohmann::json::object_t* jObj =
@@ -298,6 +307,7 @@
eventServiceConfig.retryTimeoutInterval;
data["system_uuid"] = systemUuid;
+ data["service_identification"] = serviceIdentification;
data["revision"] = jsonRevision;
data["timeout"] = SessionStore::getInstance().getTimeoutInSeconds();
@@ -383,6 +393,7 @@
}
std::string systemUuid;
+ std::string serviceIdentification;
};
inline ConfigFile& getConfig()
diff --git a/redfish-core/include/utils/manager_utils.hpp b/redfish-core/include/utils/manager_utils.hpp
new file mode 100644
index 0000000..a58f357
--- /dev/null
+++ b/redfish-core/include/utils/manager_utils.hpp
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-FileCopyrightText: Copyright OpenBMC Authors
+#pragma once
+
+#include "async_resp.hpp"
+#include "error_messages.hpp"
+#include "persistent_data.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <memory>
+#include <string_view>
+
+namespace redfish
+{
+
+namespace manager_utils
+{
+
+inline void setServiceIdentification(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ std::string_view serviceIdentification)
+{
+ constexpr const size_t maxStrSize = 99;
+ constexpr const char* allowedChars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 _-";
+ if (serviceIdentification.size() > maxStrSize)
+ {
+ messages::stringValueTooLong(asyncResp->res, "ServiceIdentification",
+ maxStrSize);
+ return;
+ }
+ if (serviceIdentification.find_first_not_of(allowedChars) !=
+ std::string_view::npos)
+ {
+ messages::propertyValueError(asyncResp->res, "ServiceIdentification");
+ return;
+ }
+
+ persistent_data::ConfigFile& config = persistent_data::getConfig();
+ config.serviceIdentification = serviceIdentification;
+ config.writeData();
+ messages::success(asyncResp->res);
+}
+
+inline void getServiceIdentification(
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const bool isServiceRoot)
+{
+ std::string_view serviceIdentification =
+ persistent_data::getConfig().serviceIdentification;
+
+ // This property shall not be present if its value is an empty string or
+ // null: Redfish Data Model Specification 6.125.3
+ if (isServiceRoot && serviceIdentification.empty())
+ {
+ return;
+ }
+ asyncResp->res.jsonValue["ServiceIdentification"] = serviceIdentification;
+}
+
+} // namespace manager_utils
+
+} // namespace redfish
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 40848f4..3b6be77 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -23,6 +23,7 @@
#include "registries/privilege_registry.hpp"
#include "utils/dbus_utils.hpp"
#include "utils/json_utils.hpp"
+#include "utils/manager_utils.hpp"
#include "utils/sw_utils.hpp"
#include "utils/systemd_utils.hpp"
#include "utils/time_utils.hpp"
@@ -796,7 +797,7 @@
asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
"/redfish/v1/Managers/{}", BMCWEB_REDFISH_MANAGER_URI_NAME);
asyncResp->res.jsonValue["@odata.type"] =
- "#Manager.v1_14_0.Manager";
+ "#Manager.v1_15_0.Manager";
asyncResp->res.jsonValue["Id"] = BMCWEB_REDFISH_MANAGER_URI_NAME;
asyncResp->res.jsonValue["Name"] = "OpenBmc Manager";
asyncResp->res.jsonValue["Description"] =
@@ -820,6 +821,8 @@
"/redfish/v1/Managers/{}/EthernetInterfaces",
BMCWEB_REDFISH_MANAGER_URI_NAME);
+ manager_utils::getServiceIdentification(asyncResp, false);
+
if constexpr (BMCWEB_VM_NBDPROXY)
{
asyncResp->res.jsonValue["VirtualMedia"]["@odata.id"] =
@@ -964,6 +967,7 @@
std::optional<nlohmann::json::object_t> fanZones;
std::optional<nlohmann::json::object_t> stepwiseControllers;
std::optional<std::string> profile;
+ std::optional<std::string> serviceIdentification;
if (!json_util::readJsonPatch( //
req, asyncResp->res, //
@@ -977,7 +981,8 @@
"Oem/OpenBmc/Fan/PidControllers", pidControllers, //
"Oem/OpenBmc/Fan/Profile", profile, //
"Oem/OpenBmc/Fan/StepwiseControllers",
- stepwiseControllers //
+ stepwiseControllers, //
+ "ServiceIdentification", serviceIdentification //
))
{
return;
@@ -1000,6 +1005,12 @@
asyncResp, *locationIndicatorActive, managerId);
}
+ if (serviceIdentification)
+ {
+ manager_utils::setServiceIdentification(
+ asyncResp, serviceIdentification.value());
+ }
+
RedfishService::getInstance(app).handleSubRoute(req, asyncResp);
});
}
diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp
index 34f0e31..a67a75d 100644
--- a/redfish-core/lib/service_root.hpp
+++ b/redfish-core/lib/service_root.hpp
@@ -11,6 +11,7 @@
#include "persistent_data.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
+#include "utils/manager_utils.hpp"
#include <boost/beast/http/field.hpp>
#include <boost/beast/http/verb.hpp>
@@ -80,6 +81,7 @@
"/redfish/v1/EventService";
asyncResp->res.jsonValue["TelemetryService"]["@odata.id"] =
"/redfish/v1/TelemetryService";
+ manager_utils::getServiceIdentification(asyncResp, true);
asyncResp->res.jsonValue["Cables"]["@odata.id"] = "/redfish/v1/Cables";
asyncResp->res.jsonValue["Links"]["ManagerProvidingService"]["@odata.id"] =